cancel
Showing results for 
Search instead for 
Did you mean: 

How to detect button Long press and short press,where buttons acts as gpio interrupts

vsiri
Associate

I have tried something like below in my interrupt function but i was unable to detect long press ,every time it was detecting short press.

static timestamp_pressed=-1;

if (timestamp_pressed == -1) 

{

user just pressed the button

 timestamp_pressed = HAL_GetTick(); // milliseconds since startup

if (HAL_GetTick() - timestamp_pressed > 3000)

{

// 3000 milliseconds = 3 seconds are over

   state_Long=1;   

timestamp_pressed = -1;

  }

else

  {

  state_short=1;

  timestamp_pressed=-1;

}

7 REPLIES 7
PSpei
Associate II

I'm not going to be of any direct help as I'm trying to learn STM32 coming from a PIC background. I have the following code that works for PIC and detects short and long press and even toggles an output (buzzer) once inside the long loop. Hopefully you can adapt, and post the code back.

char AdvancedButton(char *port, char pin, char active_state, uint16_t time_ms_short, uint16_t time_ms_long) {
 
	unsigned int cnt = 0;
	char result = 0;
	unsigned int time;
 
	time = (time_ms_long - time_ms_short);
 
	if ((*port >> pin & 0x01) == active_state) {
		result = 1;
		vdelay_ms(time_ms_short);  // Debounce time
		while ((*port >> pin & 0x01) == active_state) {
			if (++cnt >= time) {
				result = 2;
				// Make a beep to signal long press achieved
				while ((*port >> pin & 0x01) == active_state) { 
					// wait till button released
				}
				break;
			}
			delay_ms(1);
		}
	}
 
	return result;
}

Cheers,

Paul

AvaTar
Lead

You need to differ between events.

On button down, start the timer to measure the press length.

On button up, evaluate the elapsed time and raise the appropriate event.

Only debouncing makes the algorithm slightly more complex.

PSpei
Associate II

If you wait until the button is released before checking the elapsed time then there is no opportunity to sound a beep, flash a LED or whatever to alert the user that a long press has happened.

True, but only if one would want to do that. I can't read that requirement out of the OP's post.

PSpei
Associate II

Perhaps he doesn't know what he wants yet =) I'm a bit like that.

After some playing around, this works fine.

		pressed = AdvancedButton(GPIOD, GPIO_Pin_11, 1, 30, 3000);
 
		if (pressed == 1) {
			printf("%s\r\n", "Short Press");
		}else if (pressed == 2) {
			printf("%s\r\n", "Long Press");
		}
 
 
 
uint8_t AdvancedButton(GPIO_TypeDef *port, uint16_t pin, uint8_t active_state, uint16_t time_ms_short, uint16_t time_ms_long) {
 
	uint8_t result = 0;
	uint16_t time;
	uint32_t last_val;
 
	time = time_ms_long - time_ms_short;
	last_val = millis();
 
	if (TM_GPIO_GetInputPinValue(port, pin) == active_state) {
		result = 1;
		delay_ms(time_ms_short);	// Debounce Time
 
		while (TM_GPIO_GetInputPinValue(port, pin) == active_state) {
			if (millis() - last_val >= time) {
				result = 2;
				//
				// Make a beep or something here
				//
				while (TM_GPIO_GetInputPinValue(port, pin) == active_state) {}
				break;
			}
		}
	}
	delay_ms(100);	// Short delay to counter debounce on release
	return result;
}
 
 
 
 

The questions are:

- Does the target hardware have any audio output (beep) at all ?

- Would it even be heard at the deployment side ?

For systems I came across last years, the answers were always no.

Which doesn't mean they do not exist ...

PSpei
Associate II

In my case I'm designing the PCB with a buzzer so that I can have some audible feedback when the long press has occured. Being on the same board as the pushbutton, being able to hear it really isn't an issue.

Ohh, almost forgot, I have a couple of macros defined.

// Define macro to read pin state
#define TM_GPIO_GetOutputPinValue(GPIOx, GPIO_Pin)	(((GPIOx)->ODR & (GPIO_Pin)) == 0 ? 0 : 1)
#define TM_GPIO_GetInputPinValue(GPIOx, GPIO_Pin)   (((GPIOx)->IDR & (GPIO_Pin)) == 0 ? 0 : 1)