cancel
Showing results for 
Search instead for 
Did you mean: 

Debouncing

sne_123
Associate III

Can anyone help me with debounce code in C for Rising and falling edge interrupt??

20 REPLIES 20
Jaroslav BECKA
ST Employee

My favorite article about debouncing. It contains both hardware and software solutions.

Hopefully, it will help.

http://www.ganssle.com/debouncing.htm

THIS ^ Jack Ganssle's columns should be required reading for every hardware or firmware engineer.

S.Ma
Principal

Get a main loop 50msec flag set regularly, one set, clear it and scan your key like a "stoboscopic" view.

Increase the counter when it's pressed, clear it when released. Consider it pressed after 3 increments = 50x3=150msec triple check.

Of course, you can keep counting up and send key level events (first pressed, repeated press, pressed 5 seconds, etc...)

sne_123
Associate III

Thank you everyone for your help. I solved the issue. :)

sne_123
Associate III

Thank you all for answering.. I have solved the issue... :) created a debounce check using time check of 10ms as well as kept a check for previous states.

Why i should never use EXTI interrupt for switches ?

You can't really use EXTI to *debounce* a switch; you can use EXTI to *wake* a sleeping MCU, then debounce using a timer, for example.

Loppi
Associate III

It may be a bit late but I had a similar problem. As of why we should *never* use EXTI for button sampling, I don't know. I could just think of people don't want to go through using some static variables and using HAL_GetTick to keep track of the time.

Here is what I have used to debounce the user button of a STMXXX_NUCLEO board to control digital RGBs:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	uint32_t now = HAL_GetTick();
 
	static uint32_t lastUserButtonRisingI = 500;
	static uint32_t lastUserButtonFallingI = 500;
	static uint8_t lastEdge = 1;
 
	uint8_t currentEdge = HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin);
 
	if ((lastEdge == currentEdge)||
		      (currentEdge == fallingEdge && ((now - lastUserButtonFallingI) <= 10)) ||
		      (currentEdge == risingEdge && ((now - lastUserButtonRisingI) <= 10)))
		__NOP(); // debouncer
 
	else
	{
		if (currentEdge == fallingEdge)
		{
			lastUserButtonFallingI = now;
		}
		else
		{
			lastUserButtonRisingI = now;
		}
 
		uint32_t diff = lastUserButtonRisingI - lastUserButtonFallingI;
		if (currentEdge == risingEdge && diff >= 10 && diff <= 500) {
			// Single press
			LED_Brightness += 5;
			if (LED_Brightness > 45) LED_Brightness = 0;
		}
		if (currentEdge == risingEdge && diff >= 1000 && diff <= 8000) {
			// Long press
			if (++LEDmode > NUMBER_MODE)
				LEDmode = 1;
		}
	}
	lastEdge = currentEdge;
}

SPeac.1
Associate II

A bit of a late reply...

BUT.. you can use EXTI, set for both edges.

EXTI interrupt starts a timer if not started (say 1ms intervals). It also sets a counter to say 5.

Each Timer interrupt you decrement the counter (but not past 0), when it reaches 0, you read the IO line and save it as its new value then stop the timer.

This is a simple 5ms debounce using EXTI and TIM.

The advantage is its not running if the input is static. Also since it sets a time base, you can run as many inputs as you want.

Simon

@Jack Peacock_2 How about configuring a gpio interrupt to be triggered for both edges,

let's say, if I consider rising edge to be first & next falling edge to be second edge.

Declare one byte volatile variable, out of which only first 2 bits, bit-0 & bit-1 will be used as: bit-0 set on first interrupt (I assume key pressed), bit-1 set on second interrupt (I assume key released), once I get the value 0x03 in this variable, I may generate a s/w interrupt or an event or push 1 in a queue reserved to detect pin status change, lets call it a key event.

Process whatever upon this key event & clear the variable

Do I still need to make logic for debouncing? or this can be done utilizing available gpio configuration.

It is my intuition that key cannot be released until it is pressed. So, I consider first interrupt as key pressed & second as key released.

I would appreciate you response...