cancel
Showing results for 
Search instead for 
Did you mean: 

External interrupt and button debounce

JJoao.1
Associate III

Hi all,

 I currently work on STM32F030K6 .

I am working with a reed switch connected to pin PA8 (EXTI8).

I havec onfigured the PIN like : "external Interrupt Mode rising/falling ....
I need to perform an action on the rising edge AND on the falling edge.
But since the switch is slow there are certainly bounces.
What would be the good method to not detect the bounces.
I tried to set a timer but it does not work. I tried to disable the interrupts but it does not work either.

 

I have create a test code like this.

 

 

 while (1)
  {
	  if (Bouton_WU == 1)  // ILS
	  {		 
		  HAL_Delay(500);
		  Bouton_WU = 0;
		  Envoi_msg();
	  } 
	  if (test > 5)
	  {
		  test = 0;
	  }
}

 

 

 

 

 

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	switch (GPIO_Pin)
	{
		case ILS_Pin:	Bouton_WU = 1; 
                                 test++; 
		                 break;
	}
}

 

 

 

I tried to use the function :  "HAL_NVIC_DisableIRQ(EXTI4_15_IRQn);"   in several places in the code without succes.

I tried to put some HAL_delays without succes.

I used the debugger to watch the value of my variable "test", and the value is higher 10 in every change of my switch.

 

do you have any idea to deal with the problem ?


thanks for reading me

 

1 ACCEPTED SOLUTION

Accepted Solutions
gbm
Lead III

For a button, you always need a timer interrupt. So - there is no point in using any other interrupt.

Add the code similar to this to SysTick ISR: (define BUTTON_PRESSED macro to return non-zero when button is pressed)

#define BUTTON_PRESSED (~B1_GPIO->IDR & B1_PIN)
static uint8_t btn_div;

if (btn_div == 20)
{
    btn_div = 0;
    static bool btn_prev;
    bool btn_curr = BUTTON_PRESSED;
    if (!btn_prev && btn_curr)
        onButtonPressed();
    btn_prev = btn_curr;
}

 

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

View solution in original post

4 REPLIES 4
TDK
Guru

There are many methods for debouncing a switch in software. This is the one I prefer:

  • When the pin changes state, assume the state change is real (i.e. act upon the switch press) and set a timer. If the pin changes state within, say, 50 ms of when that timer is set, ignore the new state. You can use HAL_GetTick() for this check.

If you don't have noise on the line, this is a good method since it lets you respond instantly to the event.

If you feel a post has answered your question, please click "Accept as Solution".
JJoao.1
Associate III

Thank for your answer TDK,

But in fact the pin change state so quickly.

I don't know why i can't put a HAL_Delay() in the interrupt ! 

I try to wake up by standby mode, and I need to determinate wich pin wake up the STM32 and in which sens ( up to down or down to up)

 

 

while (1)
  {
	  if (Bouton_WU == 1)  // ILS
	  {		 
		  HAL_Delay(500);
           printf ("test=%u\r\n",test);
		  Bouton_WU = 0;
           test = 0;
		  //do something
           GoToStopMode();
          }
  }
void GoToStopMode(void)
{
	//Sleep wake up by EXTI
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	switch (GPIO_Pin)
	{
		case ILS_Pin:						
						Bouton_WU = 1;
						test++;
						break;

		break;
	}
}

 

 

Here is the result every time I switch.

In one way it's ok, but in the other way I have some bounces

 

Test:1                                                                        
Test:6                                                                        
Test:1                                                                        
Test:5                                                                        
Test:1                                                                        
Test:5
                                                                        
                                                                                
             

 

 

 

>>I don't know why i can't put a HAL_Delay() in the interrupt ! 

Typically because that needs an interrupt to work, one that can preempt the interrupt you're now in and blocking. Interrupts ideally complete almost immediately, not linger half a second blocking darn near everything..

It would make more sense to flag the initial event, and then monitor subsequently in the SysTick handler at every 1ms from then on out.

You can time stamp the event in the EXTI, either with the HAL Tick count, or a much higher resolution count from a maximal, free-running, TIM via TIM->CNT register.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gbm
Lead III

For a button, you always need a timer interrupt. So - there is no point in using any other interrupt.

Add the code similar to this to SysTick ISR: (define BUTTON_PRESSED macro to return non-zero when button is pressed)

#define BUTTON_PRESSED (~B1_GPIO->IDR & B1_PIN)
static uint8_t btn_div;

if (btn_div == 20)
{
    btn_div = 0;
    static bool btn_prev;
    bool btn_curr = BUTTON_PRESSED;
    if (!btn_prev && btn_curr)
        onButtonPressed();
    btn_prev = btn_curr;
}

 

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice