## [STM32 GPIO EXTI] - Detection of the falling and rising edges of a button press and release **Board:** NUCLEO-F072RB **IDE:** STM32CubeIDE --- ### Introduction --- This article introduces how to use GPIO interrupt (EXIT) to detect the button press or release via falling and rising edges and use HAL_GetTick() to measure the time, determining whether the button is a short press or a long press. If it's a long press, the LED will blink. --- ### STM32CubeMX settings --- ![image](https://hackmd.io/_uploads/SyRoka7F0.png) **PC13:** Configure as GPIO_EXTI for the button. **PA5:** Configure as GPIO output for the LED. ![image](https://hackmd.io/_uploads/Sy1re67FC.png) GPIO mode: select Rising/Falling edge trigger detection. ![image](https://hackmd.io/_uploads/S1qhg6QKR.png) Enable EXTI interrupts. --- ### HAL_GPIO_EXTI_IRQHandler() --- **stm32f0xx_it.c:** you can see *HAL_GPIO_EXTI_IRQHandler()* in *EXTI4_15_IRQHandler()*, the function will be called when the button is pressed or released. ![image](https://hackmd.io/_uploads/Hkp0lpXFA.png) --- ### HAL_GPIO_EXTI_Callback() --- **stm32f0xx_hal_gpio.h:** you can see HAL_GPIO_EXTI_Callback(), we will use it to write some button long press and short press logic. ![image](https://hackmd.io/_uploads/HkORWpmKC.png) --- ### main.c --- When the callback function HAL_GPIO_EXTI_Callback() is called, use HAL_GPIO_ReadPin() to detect falling or rising edge trigger. * **Falling edge:** GPIO_PIN_RESET * **Rising edge:** GPIO_PIN_SET If the button is pressed for more than 1 second, set isLongPressed to true. Then, in the super loop, the LED blinking will be triggered. Since interrupts are not suitable for time-consuming operations, the blinking is handled outside the interrupt. ```c= //main.c #define LONG_PRESS_THR (1000) //1 second uint32_t btnPressTime = 0; uint32_t btnReleaseTime = 0; uint32_t btnPressDuration = 0; bool isLongPressed = false; void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_PIN_13 == GPIO_Pin) {//Check if the button is triggered if (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_Pin)) { //Falling edge HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); //Turn on the LED when button is pressed btnPressTime = HAL_GetTick(); //Record the time the button is pressed } else {//Rising edge btnReleaseTime = HAL_GetTick(); //Record the time the button is released btnPressDuration = btnReleaseTime - btnPressTime; //Calculate the duration from when the button is pressed to when it is released if (LONG_PRESS_THR < btnPressDuration) { //Check if the duration exceeds the long press threshold isLongPressed = true; //Set the flag to true for the main while() loop to detect } else { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); //Turn off the LED if the button is short-pressed } } } } ``` Since HAL_Delay() cannot be used within an interrupt callback function,handle the LED blinking in this main loop. Additionally, avoid using HAL_GPIO_TogglePin() to ensure the LED is turned off in each iteration. ```c= //main.c while (1) { if (isLongPressed) { isLongPressed = false; uint8_t i; for (i = 0; 5 > i; i++) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); HAL_Delay(100); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET); HAL_Delay(100); } } } ``` --- ### Youtube Video --- {%youtube YGOQh48LIOM %} When the button is pressed, the green LED turns ON; otherwise, when the button is released, the green LED turns OFF. If the button is pressed for more than 1 second, the green LED will start blinking after the button is released. --- ### Reference --- * https://wiki.st.com/stm32mcu/wiki/Getting_started_with_GPIO