cancel
Showing results for 
Search instead for 
Did you mean: 

Detecting long button press on STM32F3

Tony Blake
Associate II
Posted on April 20, 2018 at 13:03

Hi,

I'm trying to detect a long button press on an STM32F3.

I have a push button connected to a GPIO on the STM32F3 configured with an external interrupt request (EXTI9_5_IRQn). The interrupt handler (HAL_GPIO_EXTI_IRQHandler) is successfully triggered when the button is pressed and it subsequently calls the callback function (HAL_GPIO_EXTI_Callback).

I have attempted to detect a long button press by creating a counter variable inside the callback function and incrementing it while the GPIO pin is HIGH (i.e. while the button is pressed). A long button press could therefore be detected when the counter reaches a certain value (i.e. a period of time has elapsed). Unfortunately, the GPIO pin state will not update until the program exits the callback function and I get stuck in an infinite loop like so:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

    uint8_t counter = 0;

    

     if(GPIO_Pin == POWER_DET_GPIO_PIN){

        

          if(POWER_DET_GPIO_PIN_STATE == 1){

               while(POWER_DET_GPIO_PIN_STATE){

                      counter++; // program gets stuck here

               }

          }

         if(counter == someval){

                  // long button press detected

         }

     }    

}

Can anyone help me out here? Is there a simpler way to detect a long button press?

Cheers,

Tony

#stm32f3 #button-interrupt #long-press
1 ACCEPTED SOLUTION

Accepted Solutions
Tilen MAJERLE
ST Employee
Posted on April 20, 2018 at 13:14

To detect long button press, you can follow these instructions:

  • Detect any pin change (interrupt on any pin change) and save the time of this interrupt to single variable
  • In the main loop, process check if:
    • Current state is what is want (GPIO pin down or high, depends on configuration)
    • Time between now and last debounce time is greater than minimal time for detecting long press.
  • When you detect this, you have long press.

Pseudo code would look something like that:

uin32_t button_processed = 0, lastDebounceTime;
//
//Interrupt should trigger on both edges
//
void
GPIO_IRQ_HANDLER(void) {
 lastDebounceTime = HAL_GetTick();
 button_processed = 0;
}
int
main(void) {
 ...
 ...
 while ( ) {
 //Is button currently pressed?
 //Was button already processed?
 //Is the time ok to detect long press?
 if (gpio_button_is_pressed_State() && 
 !button_processed &&
 HAL_GetTick() - lastDebounceTime > yourMinimalTime) {
 button_processed = 1; //Save variable, you want to process only once 
 //in single long press
 //Do the job for long press
 }
 }
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

View solution in original post

2 REPLIES 2
Tilen MAJERLE
ST Employee
Posted on April 20, 2018 at 13:14

To detect long button press, you can follow these instructions:

  • Detect any pin change (interrupt on any pin change) and save the time of this interrupt to single variable
  • In the main loop, process check if:
    • Current state is what is want (GPIO pin down or high, depends on configuration)
    • Time between now and last debounce time is greater than minimal time for detecting long press.
  • When you detect this, you have long press.

Pseudo code would look something like that:

uin32_t button_processed = 0, lastDebounceTime;
//
//Interrupt should trigger on both edges
//
void
GPIO_IRQ_HANDLER(void) {
 lastDebounceTime = HAL_GetTick();
 button_processed = 0;
}
int
main(void) {
 ...
 ...
 while ( ) {
 //Is button currently pressed?
 //Was button already processed?
 //Is the time ok to detect long press?
 if (gpio_button_is_pressed_State() && 
 !button_processed &&
 HAL_GetTick() - lastDebounceTime > yourMinimalTime) {
 button_processed = 1; //Save variable, you want to process only once 
 //in single long press
 //Do the job for long press
 }
 }
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

henry.dick
Senior II
Posted on April 20, 2018 at 13:18

focus on the logic first and then its implementation on your particular hardware - implementation is trivial for most problems once you have figured out the logic.

I would do this:

char read_button(char button) {
 static uint16_t button_count = 0;

 if (button_pressed(button)) button_count +=1; //increment button_count if the button is pressed
 else button_count = 0; //reset button_count if button isn't pressed
 return (button_count == 0)?BUTTON_NOTPRESSED: (button_count < DEBOUNCE_TH)?BUTTON_BOUNCE:(button_count < SHORTPRESS_TH)?BUTTON_SHORTPRESS:BUTTON_LONGPRESS;
}
�?�?�?�?�?�?�?�?�?�?�?�?

use more brackets than I did to make sure that the priority is right.