cancel
Showing results for 
Search instead for 
Did you mean: 

Debouncing using registers

Petrarka
Associate II

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 

1 REPLY 1
Sarra.S
ST Employee

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 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.