Skip to main content
Visitor II
August 27, 2018
Question

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

  • August 27, 2018
  • 5 replies
  • 8231 views

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;

}

    This topic has been closed for replies.

    5 replies

    Visitor II
    January 29, 2019

    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

    Visitor II
    January 29, 2019

    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.

    Visitor II
    January 30, 2019

    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.

    Visitor II
    January 30, 2019

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

    Visitor II
    January 30, 2019

    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;
    }
     
     
     
     

    Visitor II
    January 30, 2019

    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 ...

    Visitor II
    January 30, 2019

    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)