{"id":4456,"date":"2026-05-20T09:24:34","date_gmt":"2026-05-20T09:24:34","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=4456"},"modified":"2026-05-20T09:27:31","modified_gmt":"2026-05-20T09:27:31","slug":"getting-started-with-stm32-low-layer-ll-external-interrupt","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=4456","title":{"rendered":"Getting Started with STM32 Low Layer (LL):\u00a0External Interrupt"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"559\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v-1024x559.png\" alt=\"\" class=\"wp-image-4457\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v-1024x559.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v-300x164.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v-768x419.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v-1150x627.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v-750x409.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v-400x218.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v-250x136.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/Gemini_Generated_Image_nl7voknl7voknl7v.png 1408w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Break away from continuous polling loops by utilizing the STM32F4\u2019s\u00a0<strong>External Interrupt\/Event Controller (EXTI)<\/strong>\u00a0to capture asynchronous hardware events instantly. This guide demonstrates how to map a physical pin to an interrupt line using Low Layer (LL) drivers, allowing the microcontroller to execute a dedicated service routine the exact millisecond a button is pressed or a sensor changes state.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Introduction.<\/li>\n\n\n\n<li>STM32CubeMX setup.<\/li>\n\n\n\n<li>Importing Project to STM32CubeIDE.<\/li>\n\n\n\n<li>Firmware development.<\/li>\n\n\n\n<li>Results.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">1. Introduction:<\/h2>\n\n\n\n<p>In embedded systems architecture, continuously checking the state of a pin in a&nbsp;<code>while<\/code>&nbsp;loop\u2014known as polling\u2014is highly inefficient. It consumes 100% of the CPU&#8217;s processing power and risks missing critical events if the microcontroller is busy executing another block of code. The&nbsp;<strong>External Interrupt\/Event Controller (EXTI)<\/strong>&nbsp;solves this fundamental dilemma by shifting the responsibility from software monitoring to hardware detection.<\/p>\n\n\n\n<p>By leveraging the STM32F4&#8217;s EXTI peripheral, you configure the silicon to watch specific pins autonomously. When a physical transition occurs (such as a voltage change from a button press), the hardware instantly pauses the main program execution, saves its current state, and jumps to a dedicated&nbsp;<strong>Interrupt Service Routine (ISR)<\/strong>.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Core Mechanics of EXTI in Low Layer (LL)<\/h5>\n\n\n\n<p>Implementing EXTI via Low Layer drivers strips away the abstract callback wrappers found in HAL, exposing the true hardware pipeline. To capture an external event, three distinct layers must be bridged:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>System Configuration (SYSCFG):<\/strong>\u00a0Microcontrollers pack hundreds of physical pins but have a limited number of internal interrupt channels. The SYSCFG peripheral acts as a multiplexer, mapping your specific physical pin (like\u00a0<strong>PC13<\/strong>) to the corresponding internal interrupt line (<strong>EXTI Line 13<\/strong>).<\/li>\n\n\n\n<li><strong>The EXTI Controller:<\/strong>\u00a0This layer dictates\u00a0<em>how<\/em>\u00a0the hardware should react. Using LL functions, you can configure the edge detector to trip on a\u00a0<strong>Rising Edge<\/strong>\u00a0(voltage goes low-to-high), a\u00a0<strong>Falling Edge<\/strong>\u00a0(voltage goes high-to-low), or\u00a0<strong>Both<\/strong>.<\/li>\n\n\n\n<li><strong>The Nested Vectored Interrupt Controller (NVIC):<\/strong>\u00a0Positioned inside the ARM Cortex-M4 core, the NVIC is the ultimate gatekeeper of all exceptions. It manages the execution priority of the interrupt, ensuring that time-critical hardware tasks take precedence over standard application logic.<\/li>\n<\/ul>\n\n\n\n<p>By configuring these registers directly with LL, you ensure the absolute lowest possible latency between a physical finger pressing a button and your firmware executing a response. This guide will walk you through setting up this high-performance pipeline, paving the way for low-power sleep modes and ultra-responsive applications.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. STM32CubeMX Configuration:<\/h2>\n\n\n\n<p>Open STM32CubeMX as start a new project as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1024x662.jpg\" alt=\"\" class=\"wp-image-3990\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1024x662.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-300x194.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-768x497.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1536x993.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-2048x1324.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-1150x744.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-750x485.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-400x259.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_11-04-37-250x162.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Search for your STM32 MCU, select the MCU and click on Start New Project as follows:<\/p>\n\n\n\n<p>This guide shall use STM32F767Zi Nucleo-144 board<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"723\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-1024x723.png\" alt=\"\" class=\"wp-image-4421\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-1024x723.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-300x212.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-768x542.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-1536x1084.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-2048x1445.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-1150x812.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-750x529.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-400x282.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-54-43-250x176.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Since STM32F7 is an ARM Cortex M7, it requires to setup the cache, we shall go with the default setup since we don\u2019t care about it right now.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"239\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-1024x239.png\" alt=\"\" class=\"wp-image-4422\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-1024x239.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-300x70.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-768x179.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-1150x268.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-750x175.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-400x93.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54-250x58.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-02_09-55-54.png 1346w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from user manual of Nucleo-144, we can find that the user button is connected to PC13 and LEDS as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>LD1 is connected to PB0.<\/li>\n\n\n\n<li>LD2 is connected to PB7.<\/li>\n\n\n\n<li>LD3 is connected to PB14.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"931\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-1024x931.png\" alt=\"\" class=\"wp-image-4458\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-1024x931.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-300x273.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-768x698.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-1536x1397.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-2048x1863.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-1150x1046.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-750x682.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-400x364.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_11-58-40-250x227.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We shall use LD2 and LD3 for this guide.<\/p>\n\n\n\n<p>Set PB7 and PB14 as output as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-1024x662.png\" alt=\"\" class=\"wp-image-4459\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-00-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, set PC13 as EXTI line 13 as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-1024x662.png\" alt=\"\" class=\"wp-image-4460\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-02-59-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from System Core, NVIC, enable EXTI line 13 from NVIC tab as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-1024x593.png\" alt=\"\" class=\"wp-image-4461\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-1024x593.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-300x174.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-768x445.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-1536x890.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-2048x1186.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-1150x666.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-750x434.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-400x232.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-03-36-250x145.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>From Code Generation, enable code generation for the interrupt as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-1024x593.png\" alt=\"\" class=\"wp-image-4462\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-1024x593.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-300x174.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-768x445.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-1536x890.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-2048x1186.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-1150x666.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-750x434.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-400x232.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-05-33-250x145.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Project Manager tab, select advanced settings and enable LL for every peripheral as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-1024x662.png\" alt=\"\" class=\"wp-image-4463\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-06-42-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>From Code Generation, enable Generate peripheral initialization as pair of .c\/.h file as follows: <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-1024x662.png\" alt=\"\" class=\"wp-image-4464\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-09-41-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Finally, from Project tab, give the project a name and set Toolchain\/IDE to STM32CubeIDE and click on generate code as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"662\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-1024x662.png\" alt=\"\" class=\"wp-image-4465\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-1024x662.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-300x194.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-768x497.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-1536x993.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-2048x1324.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-1150x744.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-750x485.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-400x259.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/05\/2026-05-20_12-11-18-250x162.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Thats all for STM32CubeMX configuration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Importing the Project to STM32CubeIDE:<\/h2>\n\n\n\n<p>Open STM32CubeIDE, select your workspace and click on Launch.<\/p>\n\n\n\n<p>From the IDE, click File and select STM32 Project Create\/Import as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"873\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1024x873.jpg\" alt=\"\" class=\"wp-image-3997\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1024x873.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-300x256.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-768x655.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-1150x981.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-750x640.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-400x341.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21-250x213.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_16-57-21.jpg 1524w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, from Import STM32 Project, select STM32CubeMX\/STM32CubeIDE Project and click on Next as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"769\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1024x769.jpg\" alt=\"\" class=\"wp-image-3998\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1024x769.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-300x225.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-768x577.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-1150x863.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-750x563.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-400x300.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37-250x188.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2025\/11\/2025-11-26_17-00-37.jpg 1172w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Next, select the folder that contains the .ioc file and click on Finish as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"652\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1024x652.jpg\" alt=\"\" class=\"wp-image-4360\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1024x652.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-300x191.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-768x489.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1536x977.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-1150x732.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-750x477.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-400x255.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41-250x159.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/2026-04-11_11-31-41.jpg 1760w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Note: Project name is for reference only.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Firmware Development:<\/h2>\n\n\n\n<p>First, we need to implement time base, for how to implement time base, please refer to <a href=\"https:\/\/blog.embeddedexpert.io\/?p=4443\" data-type=\"link\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=4443\" target=\"_blank\" rel=\"noreferrer noopener\">this guide<\/a>.<\/p>\n\n\n\n<p>Next, in stm32f7xx_it.c source file, in user code begin external variables (EV), declare the following external variables:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">extern volatile uint8_t exti_triggered;\nextern volatile uint32_t currentTime;<\/pre><\/div>\n\n\n\n<p>Next, in <strong>void<\/strong> <strong>EXTI15_10_IRQHandler<\/strong>(<strong>void<\/strong>) function, in USER CODE BEGIN LL_EXTI_LINE_13, set exti_triggered to 1, capture the current ticks and store it in currentTime and set pin PB7 to high as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\"> exti_triggered=1;\n currentTime=getCurrentTicks();\n LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_7);<\/pre><\/div>\n\n\n\n<p>Next, in main.c source file.<\/p>\n\n\n\n<p>In user code begin PV, declare the following variables:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">volatile uint8_t exti_triggered;\n\nvolatile uint32_t currentTime;<\/pre><\/div>\n\n\n\n<p>Declare a macro that holds a period for LED to remains on as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#define period 2000<\/pre><\/div>\n\n\n\n<p>The led shall be on for 2 seconds.<\/p>\n\n\n\n<p>Next, in while 1 loop, in user code begin 3:<\/p>\n\n\n\n<p>Check if the two seconds elapsed and exti is triggered, if the condition is true, turn off the led and reset the exti flag as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">if((getCurrentTicks()-currentTime&gt;period)&amp;&amp;exti_triggered==1)\n{\n  LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_7);\n  exti_triggered=0;\n\n}<\/pre><\/div>\n\n\n\n<p>Next, toggle the LED connected to PB14 each 500ms as follows:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">if(getCurrentTicks()%500==0)\n{\n  LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_14);\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the firmware.<\/p>\n\n\n\n<p>Save, build the project and run it as follows:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"34\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1024x34.png\" alt=\"\" class=\"wp-image-4349\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1024x34.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-300x10.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-768x26.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1536x51.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-1150x38.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-750x25.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-400x13.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1-250x8.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2026\/04\/image-1.png 1986w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>You may download the project from <a href=\"https:\/\/github.com\/hussamaldean\/Embedded-Expert-Post-Projects\/tree\/main\/Projects\/LL_EXTI\" data-type=\"link\" data-id=\"https:\/\/github.com\/hussamaldean\/Embedded-Expert-Post-Projects\/tree\/main\/Projects\/LL_EXTI\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Results:<\/h2>\n\n\n\n<p>You should get the following when you run the project on STM32F767Zi Nucleo-144:<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"External Interrupt on STM32F7 using Low Layer (LL)\" width=\"1170\" height=\"658\" src=\"https:\/\/www.youtube.com\/embed\/5nRS8UyBr4E?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>Happy coding \ud83d\ude09<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Break away from continuous polling loops by utilizing the STM32F4\u2019s\u00a0External Interrupt\/Event Controller (EXTI)\u00a0to capture asynchronous hardware events instantly. This guide demonstrates how to map a physical pin to an interrupt line using Low Layer (LL) drivers, allowing the microcontroller to execute a dedicated service routine the exact millisecond a button is pressed or a sensor [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,11,12],"tags":[],"class_list":["post-4456","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4456"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4456"}],"version-history":[{"count":2,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4456\/revisions"}],"predecessor-version":[{"id":4468,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/4456\/revisions\/4468"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}