STM32 GPIO Peripheral Guide – CubeMX Configuration and HAL Examples

Dec 25, 2025
STM32 GPIO Programming

STM32 microcontrollers are powerful and highly flexible, but this flexibility comes at the cost of complexity. Programming an STM32 MCU often requires configuring many low-level registers for each peripheral, which can be time-consuming and error-prone, especially for beginners. To simplify this process, STM32CubeMX was introduced. It provides a graphical interface that allows developers to configure peripherals easily and automatically generates the corresponding initialization code. In this article, we use STM32CubeMX to demonstrate how to configure GPIO pins for input and output on an STM32 microcontroller. Additionally, the Hardware Abstraction Layer (HAL) provides a higher-level, portable API that hides most register-level details. It is also worth noting that STM32CubeMX is fully integrated into STM32CubeIDE, making it the standard development environment for STM32 applications.

STM32CubeIDE Installation Page

The main goal of this article is to reduce friction for beginners who want to start programming STM32 microcontrollers, allowing them to focus on concepts rather than on configuration complexity.   If you are beginning with STM32 or want a solid foundation, this guide is for you. In practice, we will configure the GPIO pins in Input and output modes to interact with a button and an LED, respectively.

END Result:

STM32 GPIO tutorial end result

 

This article is part of the STM32 Introduction Course, which guides beginners step by step through the fundamentals of STM32 microcontroller programming. Each chapter builds a solid foundation, starting with core concepts and gradually introducing more advanced topics.

STM32 Programming Course For Beginners

STM32 Programming Course for beginners

Topics to be covered:

  • What is the GPIO Peripheral
  • STM32 GPIO Input and Output Modes Explanation
  • STM32 GPIO Pull‑Up / Pull‑Down Resistors
  • Creating a project in STM32CubeIDE
  • STM32 GPIO Configuration in STM32CubeMx
  • Writing code to control LEDS using a button

What Is the STM32 GPIO Peripheral?

The GPIO peripheral enables the microcontroller to interact with the external world via physical pins. Each GPIO pin can:

  • Read a digital voltage level (input mode)

  • Drive a voltage level (output mode)

  • Be connected internally to a peripheral (alternate function mode: UART, SPI, I2C, timers, etc.)

  • Read an analog signal (analog mode)

In STM32 microcontrollers, GPIO pins are grouped into ports:

  • GPIOA, GPIOB, GPIOC, …

  • Each port typically has 16 pins (PA0–PA15, PB0–PB15, etc.).

Each port is controlled by its own registers and clock.

STM32 GPIO: Input and Output Modes in details

STM32 GPIO pins work with digital logic levels:

  • Logic 1 (HIGH) → voltage close to VDD (typically 3.3 V)

  • Logic 0 (LOW) → voltage close to 0 V (GND)

When a pin is configured as:

  • Output: the microcontroller actively drives the pin HIGH or LOW

  • Input: the microcontroller senses the voltage present on the pin

Voltages above a certain threshold are interpreted as HIGH (1), while voltages below another threshold are interpreted as LOW (0).  In this tutorial, we will configure the basic modes of the GPIO Peripheral: input and output modes. Using these modes, we will learn to interact with a button and drive an LED. 

 

STM32 GPIO Pull‑Up / Pull‑Down Resistors

When an input pin is left unconnected, it is said to be floating. A floating input may randomly read HIGH or LOW due to noise.

To prevent this, GPIO inputs use pull resistors:

  • Pull‑Up: forces the pin HIGH when nothing drives it

  • Pull‑Down: forces the pin LOW when nothing drives it

STM32 MCUs provide internal pull‑up and pull‑down resistors that can be enabled directly in software using CubeMX or HAL, eliminating the need for external resistors in many cases. 

The classic example of the GPIO Input mode is reading the state of a button. However, using a pull-up or pull-down resistor with the button is essential. The figure below illustrates how it works. When connecting a pull-up resistor, pressing the button (closed gate) sets the voltage to 0V, whereas releasing the button (open gate) sets it to 3V. The pull-down resistor works similarly but provides opposite states. To sum up, connecting either a pull-up or pull-down resistor to the button allows us to determine the button state using the GPIO Input mode.

STM32 GPIO Control Hardware and Software

In this tutorial, I will use the Nucleo-L412kB Microcontroller Board. I will connect LEDs to PA9 and PA10 pins, and the button to PB7. I configure PB7 as a GPIO Input and PA9/PA10 as GPIO outputs. But you can use any other microcontroller you have.

 

STM32 LED and button hardware

I use STM32CubeIDE as a programming tool. It includes everything we need: STM32CubeMX graphical tool to configure Peripherals and Hardware Abstraction Layer (HAL) libraries.

STM32 GPIO Configuration in STM32CubeMx

Next, let me show how to configure the GPIO peripheral using the STM32CubeMx graphical tool. First, we install the STM32CubeIDE application, which includes everything needed to program STM32 MCUs. Once the IDE is installed, launch it. It will prompt for a workspace, a folder to store our projects. You can create one and browse it when launching the IDE.

STM32CubeIDE workspace

Once launched, you will be taken to the welcome page. Here, press 'Start new STM32 project.'

STM32CubeIDE new project

After, we choose the board we are using. You can search for it in the list. In my example, I am using Nucleo-L412Kb, but you must enter the board you possess.

STM32CubeIDE board selector

Finally, we enter the project name and press 'Finish.'

STM32CubeIDE Project name

Next, I configure PA9 and PA10 as output pins, while PB7 as a GPIO input.

STM32 GPIO Output Mode

STM32 GPIO Input Mode

Next, we connect a pull-up resistor to PB7. This step is essential for reading the button's state. 

STM32 GPIO Pull-up and Pull-down resistor configuration

Finally, we can save the final and generate the code.
STM32CubeMx generate code button

Once code generation is finished, open the main.c file and examine the main() function. You will see several initialization and configuration functions that the tool automatically generated. At the end of the function, there is an infinite while(1) loop. Any code that must run continuously during program execution should be placed within this loop.

STM32CubeIDE while loop

 

The next step is to write code to control the GPIO output pins.

Function to Control the GPIO Output Pin:

// We use HAL_GPIO_WritePin function to control the state of the pin:
HAL_GPIO_WritePin(GPIO_TypeDef\* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
/* It has three arguments:
1. GPIOx - Port (GPIOA, GPIOB, GPIOC, etc.)
2. GPIO_Pin - Pin(GPIO_PIN_0, GPIO_PIN_1, etc)
3. PinState - Pin state (GPIO_PIN_RESET or GPIO_PIN_SET) */

 

Function to read the state of the GPIO Input Pin:

// We use HAL_GPIO_ReadPin function to control the state of the pin:
HAL_GPIO_ReadPin(GPIO_TypeDef\* GPIOx, uint16_t GPIO_Pin); 
/* It has two arguments: 
1. GPIOx - Port (GPIOA, GPIOB, GPIOC, etc.) 
2. GPIO_Pin - Pin(GPIO_PIN_0, GPIO_PIN_1, etc) 
It returns the status of the pin: GPIO_PIN_RESET or GPIO_PIN_SET 
*/

 

Using these functions, we implement logic to control the LED state when the button is pressed. We write our code within the while loop to repeatedly read the button's state.

if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);
} else
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);
}

 STM32 GPIO LED Control

Please pay attention that we wrote this code between /* USER CODE BEGIN ... and /* USER CODE END ... comments. These comments serve as "guards" that prevent the code from being erased when updating the STM32CubeMX (.IOC) file. Next time we update the microcontroller configuration using the IOC file, the software will regenerate all files and erase any code outside the comments. Therefore, writing our code between these "guard" comments is super important.

Finally, we build (hammer) and press the debug button. 

STM32CubeIDE debug and build button

Then, if everything is correct, a debug perspective opens up. 

STM32CubeIDE switch to debug perspective 

We press the resume button and observe how pressing and releasing it changes the LED state. This is the end of the article. If you want further detailed guide on STM32 Programming, check out my STM32 Programming Course for beginners:

STM32 Course for beginners

STM32CubeIDE resume debug