Posted these in the wrong order, it wouldn’t be a newbie example if you weren’t flashing an onboard LED now.
A simple LED blink is a useful first GPIO output test for the ATmega4809 Curiosity Nano and Curiosity Nano Explorer. The example confirms that the project can be built and programmed successfully while also demonstrating the basic sequence required to control a physical output from firmware.
The LED pin is configured as an output before the program repeatedly changes its state, producing an easily observed indication that both the firmware and hardware connection are operating correctly.
Although blinking an LED is deliberately simple, the same GPIO operations form the basis of more substantial embedded projects. Digital outputs can be used for status indicators, control signals, chip-select lines and interfaces to external driver circuits.
The example is also a convenient starting point for examining the ATmega4809’s modern PORT architecture, including its dedicated direction and output registers, before progressing to pushbuttons, interrupts, hardware timers and PWM. The existing VS Code project can therefore be extended without changing the basic development workflow.
Lets go through the steps
Step 1: Update .vscode/c_cpp_properties.json
This was mine – you’ll need to make sure the version is correct 3.6.299 and the path
{
"configurations": [
{
"name": "ATmega4809",
"includePath": [
"${workspaceFolder}/**",
"C:/Users/user/.mchp_packs/Microchip/ATmega_DFP/3.6.299/include/**"
],
"defines": [
"__AVR_ATmega4809__",
"F_CPU=20000000UL"
],
"forcedInclude": [
"C:/Users/user/.mchp_packs/Microchip/ATmega_DFP/3.6.299/include/avr/io.h"
],
"compilerPath": "C:/Program Files/Microchip/xc8/v3.10/avr/bin/avr-gcc.exe",
"cStandard": "c11",
"intelliSenseMode": "windows-gcc-x86"
}
],
"version": 4
}
Test Script (Onboard LED Blink + 20 MHz Clock)
#define F_CPU 20000000UL // 20 MHz internal oscillator
#include <avr/io.h>
#include <util/delay.h>
void System_Init(void)
{
// Disable the default 6x clock prescaler to run CPU at full 20 MHz
CPU_CCP = CCP_IOREG_gc; // Unlock protected configuration registers
CLKCTRL.MCLKCTRLB = 0x00; // Prescaler disabled (CLKOUT = 20 MHz)
// Set Pin PF5 (User LED0) as Digital Output
PORTF.DIRSET = PIN5_bm;
}
int main(void)
{
System_Init();
while (1)
{
// PORTF.OUTTGL hardware-toggles PF5 on every write
PORTF.OUTTGL = PIN5_bm;
_delay_ms(500);
}
return 0;
}
Build & Program in VS Code
This can be a test – especially if you never use VS Code
-
Open the Command Palette (Ctrl + Shift + P).
-
Run C/C++: Rescan Workspace to refresh IntelliSense.
-
Select MPLAB: Select Device -> ATmega4809.
-
Select MPLAB: Select Tool -> Curiosity Nano.
-
Run MPLAB: Program Device.
Common File Types in This Directory
-
io.h: The main standard header file that detects your targeted board/chip and includes the specific header file automatically.
-
iom*.h: Specific register definitions for individual ATmega models (e.g., iom1284p.h, iom2560.h). These define register names like PORTB, DDRB, UCSR0A, and bit names like RXCIE0.
-
iom328p.h (or similar): Defines the precise memory-mapped I/O addresses for the microcontroller’s hardware peripherals.
How It Got There
-
Installed By: Microchip Studio (formerly Atmel Studio), MPLAB X IDE, VS Code or the avr-gcc toolchain compiler.
- Usage: When you write C/C++ code for ATmega chips and include #include <avr/io.h>, your compiler looks inside this exact directory structure to map human-readable C names directly to the physical hardware addresses on the chip.
And thats all there is to it – thats the easy stuff gone. Lets getgoing.
