Skip to main content
Associate II
May 8, 2024
Question

Debouncing using registers

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 

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.