Skip to main content
Visitor II
May 8, 2024
Question

Debouncing using registers

  • May 8, 2024
  • 1 reply
  • 3999 views

Hello, first of all, thanks for all the previous help to everyone. I want to debounce my input, using registers, but I'm running into the issue of it "not working" I am surely missing something in the logic I am overlooking.
here is my interrupt

void Interrupt_Init(void){
 EXTI15_10_Init();
 NVIC->IP[EXTI15_10_IRQn] = (1 << 4);
 NVIC->ISER[40 >> 5] |= (1 << (40 % 32));
}

union InterruptFlag {
 struct {
 volatile bool flag: 1; // Just one bit for our flag
 volatile bool press: 1;
 } bits_access;
 uint32_t reg; // We'll use this for byte access
};
volatile union InterruptFlag flag = { .bits_access.flag = 0 }; // Initialize to 0
volatile uint16_t pressTime;
volatile bool lastButtonPress=0;
volatile bool buttonPress=1;

void EXTI15_10_IRQHandler(void){
flag.bits_access.flag = !flag.bits_access.flag;
EXTI->PR |= (1<<13); // Clear PR to re-enable EXTI interrupt

}
bool debounceButton(){
	 TIM3->CR1 |= TIM_CR1_CEN;
	if((GPIOC->IDR & GPIO_IDR_ID13)!=lastButtonPress){
		 	 if(GPIOC->IDR & GPIO_IDR_ID13){
		 		 pressTime=TIM3->CNT;

		 	 }else{
		 		 if(pressTime>10){
		 			 flag.bits_access.press=1;
		 		 	 return 1;
		 		 }
		 	 }
		 	 lastButtonPress=GPIOC->IDR & GPIO_IDR_ID13;
		 }
	return 0;
}

and above is the debouncing function

and this is what happens in the main function;

while (1)
 {

	 int x;
	 for(x=0; x<500; x++)
	 {
	 	 if(debounceButton()== 1){
	 		 	 	x=x-1;
	 	 	 TIM2->CCR1=x;
	 	 	 }
	 	 else{
	 		 	 	TIM2->CCR1=x;
	 		 	 	delayTRIP(1);
	 	 }}

	 for(x=500; x>0; x--)
	 {
	 	 if(debounceButton()== 1){
	 		 	 	 x=x+1;
	 		 	 	 TIM2->CCR1=x;
	 	 	 	 	 }
	 	 else{
	 	 	 	 TIM2->CCR1=x;
	 	 	 delayTRIP(1);
	 }

	 }
 }}

]

 the button should stop when I press the button for x amount of milliseconds, but whatever I put into the debounce functin doesnt work 

    This topic has been closed for replies.

    1 reply

    ST Employee
    May 9, 2024

    Hello @Petrarka

    I think that the ISR should only flag that a button press event has occurred. It should not toggle the flag by using 

    flag.bits_access.flag = !flag.bits_access.flag;

    So instead: 

    void EXTI15_10_IRQHandler(void){
     if(EXTI->PR & (1<<13)){ // Check if the interrupt is from the correct pin
     flag.bits_access.flag = 1; // Set the flag to indicate button press event
     EXTI->PR |= (1<<13); // Clear PR to re-enable EXTI interrupt
     }
    }

    In the debounce function, I suggest the following code ( after defining DEBOUNCE_TIME_MS and BUTTON_PRESSED_STATE) 

    bool debounceButton(){
     if(flag.bits_access.flag){ // Check if an interrupt has occurred
     flag.bits_access.flag = 0; // Clear the interrupt flag
     if((GPIOC->IDR & GPIO_IDR_ID13) != lastButtonPress){ // Check if the button state has changed
     lastButtonPress = GPIOC->IDR & GPIO_IDR_ID13; // Update the last button state
     pressTime = TIM3->CNT; // Reset the timer count
     } else {
     if((TIM3->CNT - pressTime) > DEBOUNCE_TIME_MS){ // Check if the button has been stable for the debounce time
     if(lastButtonPress == BUTTON_PRESSED_STATE){ // Check if the button is pressed
     flag.bits_access.press = 1; // Set the press flag
     return true;
     }
     }
     }
     }
     return false;
    }

    Also, to  control the PWM value independently of the for-loop counter, use a seperate variable to track the PWM value and only update TIM2->CCR1 with this variable

    Make sure delayTRIP(1) is not a blocking delay