Skip to main content
Visitor II
October 22, 2024
Question

STM32L432 EXTI strange behaviour

  • October 22, 2024
  • 2 replies
  • 1819 views

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... 

    This topic has been closed for replies.

    2 replies

    Graduate
    October 22, 2024

    Declare flag as volatile. Rewrite the handler code to use "else if" instead of just "if" - its not possible to enter more than one if anyway.

     

    Even better: don't use EXTI at all. It makes no sense. Do it all in timer interrupt with 20 ms period.

    tompaAuthor
    Visitor II
    October 22, 2024

    Hello gbm,

    Thank you very much for your reply,

    yes flag is declared as volatile and all the tick variables also, I tried also to do a printf from interrupt (only for debugging purpose) but the problem persists...  

    Uh, not to use EXTI is also an interesting idea for think about it but now I wonder why this is not working properly...  

     

    Graduate
    October 22, 2024

    In your code, if any of A, B or Select is pressed, you call the handlers for all three of them instead of checking which pin caused the interrupt and invoking only the handler for that pin. That's the problem.

    Graduate II
    October 22, 2024

    Consider to use the timer encoder hardware for the encoder task. Using interrupt  for encoder task is error prone.

    tompaAuthor
    Visitor II
    October 22, 2024

    Hello Uwe Bonnes,

    Thank you very much for your reply,

    uh I have a finished PCB so I can't do that unfortunately.

    Actually my encoder is working very well... My buttons are acting strange...