2024-10-22 05:24 AM - last edited on 2024-10-22 01:17 PM by SofLit
Hi,
I have three buttons - START, STOP and CH_SELECT which are serviced using EXTI interrupts. I have also a rotary encoder (A and B pins). Every button line is serviced on a separate IRQ line. Debouncing of the switch and rotary encoder pins is handled in HAL_GPIO_EXTI Callback function.
The code is actually working but sometimes, actually very often, code snippet of wrong button is executed. When I pressing for example button START sometimes I get “STOP button pressed” or “CH_SELECT_button pressed” randomly. Rotary encoder works very well. Am I missing something, every help is really appreciated.
Microcontrooller is STM32L431 with 80MHz master clock. I am using STM32CubeIDE 1.16.1
Those are my EXTI handlers (in stm32l4xx_it.c file):
void EXTI4_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(STOP_BUTTON_Pin);
}
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(START_BUTTON_Pin);
}
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(A_Pin);
HAL_GPIO_EXTI_IRQHandler(B_Pin);
HAL_GPIO_EXTI_IRQHandler(CH_SELECT_Pin);
}
This is my callback function (in main.c file):
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
uint32_t currentTime = HAL_GetTick();
if ((currentTime - lastDebounceTime) < DEBOUNCE_DELAY_ENCODER) {
return;
}
lastDebounceTime = currentTime;
if (GPIO_Pin == A_Pin) {
if (HAL_GPIO_ReadPin(B_GPIO_Port, B_Pin) == GPIO_PIN_SET) {
encoderValue+=20;
if(encoderValue>2666) encoderValue=0;
} else {
encoderValue-=20;
if(encoderValue<0) encoderValue=2666;
}
}
if (GPIO_Pin == B_Pin) {
if (HAL_GPIO_ReadPin(A_GPIO_Port, A_Pin) == GPIO_PIN_SET) {
encoderValue-=20;
if(encoderValue<0) encoderValue=2666;
} else {
encoderValue+=20;
if(encoderValue>2666) encoderValue=0;
}
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, encoderValue);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, encoderValue);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, encoderValue);
}
//START button
if (GPIO_Pin == START_BUTTON_Pin) {
if ((currentTime - last_start_button_tick) > DEBOUNCE_DELAY_BUTTON) {
last_start_button_tick = currentTime;
treatment_time=0;
start_treatment=1;
TIM1->CR1 |= TIM_CR1_CEN; //start timer1
//printf("start button pressed\n\r");
flag=1;
}
}
//STOP button
if (GPIO_Pin == STOP_BUTTON_Pin) {
if ((currentTime - last_stop_button_tick) > DEBOUNCE_DELAY_BUTTON) {
last_stop_button_tick = currentTime;
start_treatment=0;
//printf("stop button pressed\n\r");
flag=2;
}
}
//CH_SELECT button
if (GPIO_Pin == CH_SELECT_Pin) {
if ((currentTime - last_ch_select_tick) > DEBOUNCE_DELAY_BUTTON) {
last_ch_select_tick = currentTime;
//printf("CH_SELECT button pressed\n\r");
flag=3;
}
}
}
I am printing debug messages in the main loop:
while(1) {
if(flag==1) { printf("START button pressed\n\r"); flag=0;}
if(flag==2) { printf("STOP button pressed\n\r"); flag=0;}
if(flag==3) { printf("CH_SELECT button pressed\n\r"); flag=0;}
//…
//…
}
AND my debounce values are:
const uint32_t DEBOUNCE_DELAY_ENCODER = 50;
const uint32_t DEBOUNCE_DELAY_BUTTON = 50;
Thank you very much, I really appreciated any advice...
2024-10-22 10:44 PM - edited 2024-10-22 10:46 PM
@tompa wrote:
Unfortunately I can't implement timer interrupt for polling the buttons because in the main I have a very time demanding task - I need to generate very precise pulses of 1 to 15us width and with repetition rate of 10Hz to 500Hz.
And during that pulses my buttons should be active (enabled) so interrupt of some 50ms for buttons polling will ruine my pulses timing.
1. Of course you can use some low priority timer interrupt, like the already-running SysTick, for polling the switches.
2. Any interrupt breaks the execution of your main loop - SysTick, EXTI, whatever.
3. Precise pulses should be generated using timer output and timer interrupt service routine or DMA.
4 For user interaction, delay of 30 ms is not noticeable - that's about buttons. With encoder, from my experience, sampling should be faster, like few ms period. This is, however, much less important than the conceptual changes you have to implement in order to get the device operational. With the current approach you won't achieve it.
2024-10-22 10:58 PM
Hello Karl,
Thank you very much for your reply,
Well I have to generate pulses on 12 pins because I need to drive three H bridges...
Arr... about debouncing actually I use Systick for getting current time at every EXTI interrupt, checking it with last debounce time and check the difference against constant DEBOUNCE_DELAY_BUTTON.
And I am capturing only falling edge trigger...
Uh, is that wrong approach ?
2024-10-23 05:23 AM
Uhh Thank you very much for useful tips,
It is obvious that I have to implement big conceptual changes unfortunatelly... :(