2018-04-20 04:03 AM
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-pressSolved! Go to Solution.
2018-04-20 04:14 AM
To detect long button press, you can follow these instructions:
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
}
}
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-04-20 04:14 AM
To detect long button press, you can follow these instructions:
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
}
}
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2018-04-20 04:18 AM
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.