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.