I'm trying to write a simple debounce program on an STM32F4. Code as follows:



  //Configure PB7 as output and PC13 as input pull-down

  //Configure Timer 2 for 20ms delay
  TIM2->PSC = 95;
  TIM2->ARR = 19999;
  TIM2->CR1 |= TIM_CR1_URS;



 while (1)

    /* USER CODE BEGIN 3 */
      if (GPIOC->IDR & GPIO_IDR_ID13)
          TIM2->CR1 |= TIM_CR1_CEN;            //Enable Timer 2

IRQ Handler:

void TIM2_IRQHandler(void)
    TIM2->SR &= ~TIM_SR_UIF;                   // Reset Update Interrupt Flag on Timer 2 Status Register 
    if (GPIOC->IDR & GPIO_IDR_ID13)
        GPIOB->ODR ^= GPIO_ODR_OD7;            // Toggle PB7
        TIM2->CR1 &= ~TIM_CR1_CEN;             // Disable Timer 2

I'm using a delay of 20ms on Timer 2 and toggling the LED on PB7. The LED does toggle, but it doesn't behave like a debounced switch and flickers as the LED turns on. Where am I going wrong?

  • \$\begingroup\$ What do you expect the code to do then? Based on the code, as long as you press the button, it will keep turning on the timer, and the timer will keep toggling the LED. \$\endgroup\$ – Justme May 2 at 17:27
  • \$\begingroup\$ @Justme I’d like it to behave like a normal debounced switch, toggle whenever pressed. I’ve read Ganssle’s algorithm for debouncing but I’m just confused as to how to go about it. \$\endgroup\$ – Joshua John May 2 at 18:49
  • \$\begingroup\$ I think you should forget debouncing and timers for a while and concentrate on the program logic how to toggle the LED only when a button push is first detected, not toggle a LED while the button is being held pushed down. \$\endgroup\$ – Justme May 2 at 18:50
  • \$\begingroup\$ @Justme I know how to toggle the LED when the button push is first detected, it’s just a matter of removing all the timer stuff and replacing TIM2->CR1 |= TIM_CR1_CEN with GPIOB->ODR ^= GPIO_ODR_OD7. That’s worked for me. I want to learn how to debounce the switch so that I won’t see any ripple on the output. \$\endgroup\$ – Joshua John May 2 at 19:02
  • \$\begingroup\$ You need an extra variable for your code to 'remember' if it's already toggled the LED for the current button-press so that it doesn't just continuously toggle. If you use a bool, then only toggle the LED in the ISR if it's false, and then immediately set it to true. Only set it back to false when you see that the button has been released. \$\endgroup\$ – brhans May 2 at 19:35

Make 2 global variables called tick and previousTick, or whatever you want, and inside the timer ISR increment the tick variable by 1. then check if the difference between this tick and previoustick is larger than a value of your choice then consider the button debounced, otherwise if the difference of this tick and previousTick is not large enough then that means your button has bounced. At the end of ISR set previousTick = tick.

Psuedo code:

   uint32_t tick = 0 ; 
   uint32_t previousTick = 0 ; 
       if( (tick - previousTick) > 5 ) 
           // using your 20ms this means  100ms spread.
           // then *do some stuff here because button has been deboucned.*
           //*do nothing or something else here since button has been clicked too rapidly  or is boucning*
       previousTick = tick;
  • \$\begingroup\$ These variables need to be declared as volatile or the compiler might make strange assumptions during optimization. Anyway, there's likely no good reason for not sticking the debounce code itself inside the timer ISR and store the debounced result in a variable instead. \$\endgroup\$ – Lundin Jun 10 at 14:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.