STM32: How to use External Interrupts (EXTI)

STM32 HAL Tutorial: Interrupt-Driven GPIO for Responsive Applications

Abstract

Learn how to use STM32 external interrupts (EXTI) with HAL drivers to handle buttons in real-time. Step-by-step guide for interrupt-driven LED control.

1. Introduction

In Episode 3, we learned how to control an LED using polling. While effective, polling constantly checks the button state and consumes CPU cycles.

External interrupts (EXTI) allow the MCU to respond to events instantly, freeing the CPU to perform other tasks.

In this episode, you’ll learn:

  • How to configure GPIO pins as EXTI inputs in CubeMX.
  • How to write interrupt service routines (ISR) using HAL.
  • How to implement responsive LED control using interrupts.
Episode 4 – STM32 Basics_ EXTI - Imge (1)
Special thanks to Fritzing for the generated image.

This approach is more efficient and is widely used in embedded systems.

2. Prerequisites

Ensure you have:

  • A STM32 board with USER button and LED.
  • STM32CubeIDE installed.
  • Knowledge of GPIO input and output (from Episodes 2 & 3).

3. Configuring External Interrupt in CubeMX

Step 1 – Open Project

  • Create a new project in STM32CubeMX.

Step 2 – Configure Button Pin for EXTI

  • Select your button pin (commonly PC13).
  • Set mode to GPIO_Input with External Interrupt (EXTI).
  • Choose Trigger:
    • Rising Edge → Trigger when button is released.
    • Falling Edge → Trigger when button is pressed.
    • Rising_Falling Edge → Trigger on both press and release.

Step 3 – Enable NVIC Interrupt

  • CubeMX automatically assigns NVIC interrupt priority.
  • Verify it in Configuration → NVIC Settings.
Episode 4 – STM32 Basics_ EXTI (3)

Step 4 – Generate Code

  • Click Project → Generate Code to update HAL initialization.

4. Writing the Interrupt Service Routine (ISR)

STM32CubeMX generates a callback function called

				
					HAL_GPIO_EXTI_Rising_Callback(). Open main.c and locate the /*USER CODE BEGIN 4*/ region:
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == GPIO_PIN_13) // Check button pin
    {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Toggle LED
    }
}
				
			

An alternative approach would be to flag the interrupt occurrence using a variable and poll for it in the main loop or any other function.

Code Explanation

  • The callback is executed only when the button generates an interrupt.
  • GPIO_Pin parameter identifies which pin triggered the EXTI.
  • HAL_GPIO_TogglePin() toggles the LED state instantly.

Tip: No need for while(1) polling; the MCU responds automatically.

5. Compiling and Running the Project

Step 1 – Build

  • Click Build (hammer icon) or [Ctrl+B].

Step 2 – Flash

  • Connect your STM32 board via USB.
  • Click Run (green arrow) or enter in Debug mode.

Step 3 – Test

  • Press the button: LED toggles immediately with each press.
  • Release the button if configured for falling edge, or press again if using rising-falling edge.
Episode 4 – STM32 Basics_ EXTI (5)

6. Handling Debouncing in Interrupts

Mechanical buttons can still bounce, despite having the C16 to filter it. To reduce false triggers, it is possible to wait for a given time between edges. Below is the code example assuming falling edge:

				
					void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
    static uint32_t last_interrupt_time = 0;
    uint32_t current_time = HAL_GetTick(); // Milliseconds since MCU start

    if(GPIO_Pin == GPIO_PIN_13)
    {
        if((current_time - last_interrupt_time) > 50) // 50ms debounce
        {
            HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
            last_interrupt_time = current_time;
        }
    }
}
				
			
  • HAL_GetTick() provides the system time in milliseconds.
  • Only toggles LED if enough time has passed since the last press.

7. Common Issues & Fixes

Issue Cause Solution
Interrupt not triggering Pin not configured as EXTI Verify CubeMX EXTI settings
LED toggles multiple times Button bouncing Implement debounce logic
Compilation error HAL_NVIC function missing Regenerate code in CubeMX
Wrong LED behavior NVIC priority conflict Check NVIC configuration

8. Hands-On Lab Recap

You learned:

  • How to configure GPIO pins for external interrupts.
  • How to write ISR using HAL callback.
  • How to toggle an LED in real-time.
  • How to implement debouncing in interrupt-driven code.

This method is efficient and widely used in responsive embedded applications.

9. What’s Next

In Episode 5, we’ll explore Timers and PWM:

  • Configure hardware timers using CubeMX.
  • Generate periodic interrupts.
  • Control LEDs and motors with precise timing.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top