STM8L simple key processing (short press, long press)


In development, we often encounter occasions where the number of keys is small, but we need to realize multiple types of trigger functions, such as short press, long press, double click, etc., that is, the so-called key reuse. Generally, the terminal is received in the interrupt function for delay judgment, anti shake and other processing. But the interrupt processing can't be too long, so a slightly better implementation basically uses a timer to scan and process. For this key reuse function, there is a great implementation in ESP ESP project ESP IOT solution, which you can refer to. This paper describes a simple implementation method, which is simple and easy to use.

1, Implementation principle

  1. In order to reduce the number of interrupt entry, handle the rising and falling interrupts of the key respectively
  2. Set a timer with high resolution, such as 1ms, to increase the count automatically
  3. When the key trigger (up or down) interrupt arrives, start the timer
  4. When the key release interrupt arrives, stop the timer and judge whether it is short press or long press according to the counting situation

2, Use steps

1. Key interrupt initialization

The code is as follows (example):
The specific pins are replaced according to the application. This is PF5. Note that the priority is set high

void exti_button_key_init(void)
	/ Init key pin //
	GPIO_Init(GPIOF, GPIO_Pin_5, GPIO_Mode_In_PU_IT);

	EXTI_SetPortSensitivity(EXTI_Port_F, EXTI_Trigger_Rising|EXTI_Trigger_Falling);
	EXTI_SetHalfPortSelection(EXTI_HalfPort_F_MSB ,ENABLE);
	EXTI_SetHalfPortSelection(EXTI_HalfPort_F_LSB ,DISABLE);
	ITC_SetSoftwarePriority( EXTIE_F_PVD_IRQn, ITC_PriorityLevel_1);	

2. Timer operation

The code is as follows (example):
The interrupt priority is set higher to reduce the interference of other processes. If high accuracy is not required, the timer can be adjusted to 10ms or more.

void keyscan_timer_init(void)
    CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, ENABLE);

    /* (1/16MHz)*16*1000 = 1ms */
    TIM3_TimeBaseInit(TIM3_Prescaler_16, TIM3_CounterMode_Up, 1000);
    TIM3_ITConfig(TIM3_IT_Update, ENABLE);

    ITC_SetSoftwarePriority(TIM3_UPD_OVF_TRG_BRK_USART3_TX_IRQn , ITC_PriorityLevel_1);

void keyscan_timer_start(void)
	keyscan_counter = 0;

void keyscan_timer_stop(void)

3. Interrupt handling

  • Timer interrupt processing
  • External interrupt handling
		// Clear interrupt after reading status (judging press and release)
		BitStatus state = GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_5);
		if( state == RESET ) { // Press to start counting
		} else { // Release and stop counting
		// Short press judgment (the time interval can be customized to distinguish between anti shake and long press)
		if( keyscan_counter >= 100 && keyscan_counter < 3000 ) { 
			g_key_press = KEY_SHORT_PRESS; // Handle key status elsewhere
		// Long press judgment
		else if( keyscan_counter >= 3000 ) {
			g_key_press = KEY_LONG_PRESS; // //Handle key status elsewhere


  • The above scheme meets the basic functions. If you need to support double clicking, additional work needs to be done. It will not be expanded here
  • Due to the problems of the above implementation method, the key will not respond until it is released. If you keep pressing it for a long time, it will not respond. If you want to achieve long-term pressing, you can automatically increase according to the pin value and count and judge in the timer interrupt processing.

I hope it will help you.

Tags: Single-Chip Microcomputer

Posted on Fri, 22 Oct 2021 00:46:16 -0400 by JADASDesigner