GPIO output: blink the LED
GPIO (General-Purpose Input/Output) lets your code set a pin high (3.3 V) or low (0 V). We create the first project for the NUCLEO-F401RE and blink the green LED on pin PA5: one second on, one second off.
In this lesson · 5 steps
What GPIO is
A microcontroller is more than a CPU. Around the CPU sit peripherals: blocks of hardware that each do one job. UART sends data, timers count time, I2C talks to sensors. GPIO is the simplest one: it controls the pins directly. That is why every new microcontroller starts with GPIO.
In output mode your code sets the pin: high is 3.3 V, low is 0 V. With an LED on the pin, high turns it on and low turns it off.
Pin names
STM32 pins are grouped in ports called A, B, C… with up to 16 pins each (0 to 15). PA5 means port A, pin 5. PC13 means port C, pin 13. On the NUCLEO-F401RE the green LED is on PA5 and the blue button is on PC13, so we need no extra wiring.
1Start a project from the board
- Open STM32CubeMX → Access to Board Selector
- Search
NUCLEO-F401RE, select it, press Start Project - "Initialize all peripherals with their default Mode?" → No
2PA5 as an output, named LED_CONTROL
- The pinout view shows the chip with every pin labelled
- Click PA5 →
GPIO_Output - Right-click PA5 → Enter User Label →
LED_CONTROL
LED_CONTROL_Pin and LED_CONTROL_GPIO_Port. The code then says what the pin is for, not just its number.3Generate the code and open it in CubeIDE
- Project Manager tab: Project Name =
STM32_GPIO_PROGRAMMING, Project Location = a new folder for all your course projects (for exampleSTM32_Course), Toolchain / IDE =STM32CubeIDE→ Generate Code - When it is done → Open Project
- CubeIDE asks for a workspace, the folder where it keeps its settings. Pick the folder you chose as the Project Location: the folder that contains your project folder, not the project folder itself
- In the Project Explorer on the left, open your project →
Core→Src→ double-clickmain.c
4Blink code
Turn the LED on, wait one second, turn it off, wait one second. The loop repeats forever.Grey lines are already in the file: add only the coloured ones. Copy takes just those.
/* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(LED_CONTROL_GPIO_Port, LED_CONTROL_Pin, GPIO_PIN_SET); HAL_Delay(1000); HAL_GPIO_WritePin(LED_CONTROL_GPIO_Port, LED_CONTROL_Pin, GPIO_PIN_RESET); HAL_Delay(1000); /* USER CODE END WHILE */
HAL_GPIO_WritePin takes the port, the pin and the state: GPIO_PIN_SET for 3.3 V, GPIO_PIN_RESET for 0 V. HAL_Delay waits the given number of milliseconds. Always write your code between USER CODE BEGIN and USER CODE END: when CubeMX generates the code again, everything outside those lines is replaced.5Build, flash and run
- Plug in the board. Press Debug (the bug icon). CubeIDE builds the project and flashes it over the ST-LINK
- The first time, an Edit Configuration window opens: press OK. If CubeIDE asks to switch to the Debug perspective, press Switch
- The program stops at the start of
main(). Press Resume (F8) to run - Before you change the code again, press Terminate (the red square) to stop debugging. To get back to the editor, click the C/C++ perspective button at the top right (or Window → Perspective → Open Perspective → C/C++)
Check & troubleshoot
What you should see
- The green LED (LD2) blinks: one second on, one second off
If it doesn't work
- Debug fails, no ST-LINK found: use a USB cable that carries data (some only charge), and check the ST-LINK driver was installed with CubeIDE
- Build error on LED_CONTROL_Pin: the user label must be exactly
LED_CONTROL; fix it in CubeMX and generate the code again - LED does not blink: after Debug, press Resume; the program stops at the start of main() until you do
- Your code is gone after Generate Code: keep every line inside a USER CODE section
Good to know
HAL_Delaykeeps the CPU waiting and doing nothing. Chapter 5 shows how a timer runs code at a fixed rate instead.