基於STM32F030R8Tx實現按鍵掃描

  • 準備工程,此例程在以下鏈接的例程的基礎上添加的按鍵掃描功能

https://blog.csdn.net/mygod2008ok/article/details/106954917

  • 新建BSP_key.c和BSP_key.h並加入到工程

 

  • BSP_key.c的內容如下

/**
* @file BSP_key.c
* @author jzhou
* @version V1.0
* @date 11-Nov-2019
* @copyright Chileaf LTD
* @brief 按鍵掃描模塊
*   實現單按鍵或多按鍵的短按,長按,短按鬆開,長按鬆開等鍵值
*/


#include "BSP_key.h"
#include "BSP_pwm.h"


//###############################################################################################################################
/** @file
*
* @defgroup BSP_key file:BSP_key文件
* @{
* @ingroup BSP_key file
* @brief 按鍵掃描模塊
* @details 按鍵功能處理,主要是產生按鍵鍵值
*/
//###############################################################################################################################

//-----------------------以下爲按鍵引腳配置及初時化--------------------------
/**
*
* @brief 按鍵引腳配置信息初時化
*/
static const SCAN_KEY_INFO scan_key[] = {
	{GPIOA,GPIO_PIN_12},
	{GPIOA,GPIO_PIN_11},
};



/**
* @brief 獲取鍵值
*/
static KEY_TYPE_VAR get_key_value(void)
{
	KEY_TYPE_VAR KeyTemp = 0;
	
	// 讀按鍵IO電平狀態
  for(KEY_TYPE_VAR i=0; i<TOTAL_KEY_NUM;i++)
  {
		
	if(HAL_GPIO_ReadPin(scan_key[i].control_port,scan_key[i].enable_pin) == 0)
	{
		KeyTemp |= 1<<i;
	}	
  }
	return KeyTemp;
}

/**
* @brief 按鍵引腳初時化配置
*/
static void key_pin_init(void)
{
	__HAL_RCC_GPIOA_CLK_ENABLE();  
	GPIO_InitTypeDef  GPIO_InitStruct;
  /* -2- Configure IOs in output push-pull mode to drive external LEDs */
  GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull  = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;

	for(uint8_t i=0; i<TOTAL_KEY_NUM; i++)
	{
			GPIO_InitStruct.Pin = scan_key[i].enable_pin;
			HAL_GPIO_Init(scan_key[i].control_port, &GPIO_InitStruct);
	}
}
//----------------------------------------------------------------------------



//-----------------------變量定義----------------------------------------------

static KEY_TYPE_VAR KeyBuffer;
static keyFunc keyFunctionHandler = NULL;



/**
* @brief 按鍵鍵值掃描
*  掃描按鍵狀態返回對應的鍵值
* @param None
* @retval uint8_t
*  - 返回按鍵鍵值
*/
static KEY_TYPE_VAR OSReadKey(void)
{
	static E_KEY_SCAN_STATUS KeyEventCnt;
	static KEY_TYPE_VAR KeySampleCnt;
  KEY_TYPE_VAR KeyTemp = get_key_value();

	switch(KeyEventCnt )
	{
		case CHECK_HAS_KEY_DOWN:         // 有鍵按下
			if(KeyTemp != 0)
			{
				KeySampleCnt=0;
				KeyBuffer=KeyTemp;
				KeyEventCnt = KEY_EVENT_CHECK; 
			}	
			break;
		case KEY_EVENT_CHECK:  //按鍵事件檢測
			if(KeyTemp == KeyBuffer )
			{
				KeyBuffer |= KEY_OFF;
				return KeyTemp ;  //返回短按事件
			}
			else if(KeyTemp == (KeyBuffer & ~(KEY_OFF | KEY_LONG_ON)))
			{
					if(++KeySampleCnt>LONG_ON_DITHERING_COUNTER)  //長按時間大於2秒,此時間可以重定義
					{
						KeySampleCnt = LONG_ON_DITHERING_COUNTER-SYS_TICK_COUNTER/8;   // 重複觸發長按事件閥值
						KeyBuffer |= KEY_LONG_ON;
						return  KeyTemp | KEY_LONG_ON ; //返回長按事件
					}
			}
			else if(KeyTemp ==0)	
			{
				KeyEventCnt = CHECK_HAS_KEY_DOWN;
                                if((KeyBuffer & KEY_OFF) != KEY_OFF)
				    return 0;   //無效鍵
#if LONG_KEY_OFF_EVENT_ENABLED
				return KeyBuffer & ~KEY_BLOCK_FLAG;   //返回短按鬆開和長按鬆開事件
#else
				return KeyBuffer & ~(KEY_BLOCK_FLAG | KEY_LONG_ON);   //返回鬆開事件
#endif
			}		
			else if(((KeyBuffer & KEY_LONG_ON)==0) &&(KeySampleCnt < 5)) //多鍵同時按下,允許的按下時間,超過此時間檢測到多鍵將無效
			{
					KeyEventCnt = CHECK_HAS_KEY_DOWN;
			}
			break;
		}
	return 0;
	
}


void DisLongKeyContinueResponse(void)
{
	KeyBuffer |= KEY_BLOCK_EVENT;   //長按鍵僅響應一次事件
}

//#####################################################################################################


/**
* @brief 按鍵事件註冊
*/
void key_init(keyFunc fun)
{
	key_pin_init(); 
	keyFunctionHandler = fun;
}




/** 
* @brief 按鍵事件處理,此函數中定時事件中調用,此例程在25Hz中調用
*/
void keyProcessHandler(void)
{
	 KEY_TYPE_VAR event = OSReadKey();
	if(event == NO_KEY_EVENT)
		return;
	
//	NRF_LOG_INFO("KEY=%x",event);
	if(keyFunctionHandler != NULL)
	{
		keyFunctionHandler((E_KEY_VALUE)event);
	}

}





/**@}*/
  • BSP_key.h的內容如下: 

#ifndef BSP_KEY__H
#define BSP_KEY__H
#include "sdk_config.h"
#include "stm32f0xx.h"

/** @file
*
* @defgroup BSP_key file:BSP_key文件
* @{
* @ingroup BSP_key file
* @brief 按鍵掃描模塊
* @details 按鍵功能處理,主要是產生按鍵鍵值
*/
#ifdef __cplusplus
extern "C" {
#endif

#define LONG_KEY_OFF_EVENT_ENABLED   1   //區分長按鬆開事件,否則短按鬆開和長按鬆開事件統一爲鬆開事件


/**
* @brief 按鍵引腳配置結構體
*
*/
typedef struct 
{
	GPIO_TypeDef *control_port;   //!< IO端口地址
	uint16_t enable_pin;          //!< 引腳序號
}SCAN_KEY_INFO;

/************************************************************************/


#define TOTAL_KEY_NUM		sizeof(scan_key)/sizeof(SCAN_KEY_INFO)  //!< 按鍵總個數
#define LONG_ON_DITHERING_COUNTER (SYS_TICK_COUNTER*2) //!< 定義長按按下確認需要的時間,如果是每40毫秒調用一次OSReadKey()


//-------選擇支持按鍵最大的鍵個數,默認支持5個按鍵-----------
//#define KEY_NUM_MAX_13
#ifdef  KEY_NUM_MAX_13
#define  KEY_TYPE_VAR		uint16_t
#define LONG_KEY_FLAG			0X8000
#define OFF_KEY_FLAG      0X4000
#define BLOCK_LONG_FLAG   0X2000
#else
#define  KEY_TYPE_VAR		uint8_t
#define LONG_KEY_FLAG			0X80
#define OFF_KEY_FLAG      0X40
#define BLOCK_LONG_FLAG   0X20
#endif

//##################################################################################
/**
* @brief 按鍵鍵值定義
*/
typedef enum
{
	 NO_KEY_EVENT = 0,
   KEY_LONG_ON	=	LONG_KEY_FLAG,           //!< 長按MASK值
   KEY_OFF	=		  OFF_KEY_FLAG,           //!< 鬆開MASK值
	 KEY_BLOCK_FLAG = BLOCK_LONG_FLAG,     // !<阻塞標記>
   KEY_BLOCK_EVENT =	KEY_LONG_ON | KEY_OFF | BLOCK_LONG_FLAG,    //!< 阻塞長按鍵
//-----------------------------------------------------------------------------------------
	 UP_KEY_SHORT = 0x01,						                     // KEY1短按鍵值
	 UP_KEY_LONG = UP_KEY_SHORT | KEY_LONG_ON,           // KEY1長按鍵值
	 UP_KEY_OFF = UP_KEY_SHORT | KEY_OFF,                // KEY1短按鬆開鍵值
	 UP_KEY_LONG_OFF = UP_KEY_LONG | KEY_OFF,            // KEY1長按鬆開鍵值
	
	 DOWN_KEY_SHORT = 0x02,                              // KEY2短按鍵值
	 DOWN_KEY_LONG = DOWN_KEY_SHORT |  KEY_LONG_ON,			// KEY2長按鍵值
	 DOWN_KEY_OFF = DOWN_KEY_SHORT | KEY_OFF,           // KEY2短按鬆開鍵值
	 DOWN_KEY_LONG_OFF = DOWN_KEY_LONG | KEY_OFF,       // KEY2長按鬆開鍵值
	
	 UP_DOWN_KEY_SHORT = UP_KEY_SHORT | DOWN_KEY_SHORT,    // KEY1+KEY2短按鍵值
	 UP_DOWN_KEY_LONG = UP_DOWN_KEY_SHORT | KEY_LONG_ON,   // KEY1+KEY2長按鍵值
	 UP_DOWN_KEY_OFF = UP_DOWN_KEY_SHORT | KEY_OFF,        // KEY1+KEY2短按鬆開鍵值  
	 UP_DOWN_KEY_LONG_OFF = UP_DOWN_KEY_LONG | KEY_OFF,    // KEY1+KEY2長按鬆開鍵值
}E_KEY_VALUE;



typedef enum
{
	CHECK_HAS_KEY_DOWN,
	KEY_EVENT_CHECK,
}E_KEY_SCAN_STATUS;

/**
* @brief 按鍵處理功能函數指針
*/

typedef void (*keyFunc)(E_KEY_VALUE keyValue);




//#####################################################################################
/**
*  @defgroup BSP_KEY_API 按鍵功能API
*  @{
*/
//############################ API ####################################################
/** 
*  @brief 按鍵引腳初時化
*  @param [in] keyFunc fun 按鍵處理函函數指針
*  @return 
* - None
*/
void key_init(keyFunc fun);

/** 
*  @brief 按鍵掃描處理
*  @param None
*  @return 
* - None
* @note 此函數需要在系統嘀嗒事件中調用
*/
void keyProcessHandler(void);




/**
* @brief 長按鍵阻止
*	Routine Name:	DisLongKeyContinueResponse
*	Form:		void DisLongKeyContinueResponse(void)	
*	Parameters:	void
*	Return Value:	void
*	Description: if call this function in the key process function,so it keep 
*	 continue long key msg to generate
*
* @param None
* @return None
*/
void DisLongKeyContinueResponse(void);

//####################################################################################
/**@}*/
#ifdef __cplusplus
  }
#endif
/**@}*/
#endif
  • 在main函數中調用key_init函數初時化註冊按鍵事件

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	RTT_INIT();
  HAL_Init();
  SystemClock_Config();
 
	BSP_adc_init();
	
      BSP_wdt_init(IWDG_OVER_TIME);
   
	delay_init();
  
	//--------初時化串口------------------------------------
  
        BSP_uart_init();
	
	 MX_RTC_Init();
	
	 BSP_start_adc_count(8);
	
	start_buzzer_beep_sound();
	
	reply_stm32_version();
	
	 //-------------按鍵初時化-------------------------------		
	key_init(key_event_handler);
	
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
		if(s_wakeup_flag)  //任務處理模式
		{
			BSP_wdt_feed();
			tick_25hz_handler();
			tick_1hz_handler();
			uart_data_handler();
		}
		else  // 省電模式
		{
			HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
		}
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
  • key_event_handler函數實現鍵值處理


/**
* @brief 按鍵功能處理
*   分配ID及獲取歷史數據按鍵功能響應處理
* @param [in] E_KEY_VALUE 按鍵鍵值
* @retval 
* - None
*/
static void key_event_handler(E_KEY_VALUE keyValue)
{
	
	
	switch(keyValue)
	{
		case UP_KEY_SHORT:
			NRF_LOG_INFO("UP_KEY_SHORT=%x",keyValue);
			break;
		case DOWN_KEY_SHORT:
			NRF_LOG_INFO("DOWN_KEY_SHORT=%x",keyValue);
			break;
		case UP_DOWN_KEY_SHORT:
			NRF_LOG_INFO("UP_DOWN_KEY_SHORT=%x",keyValue);
			break;
		case UP_KEY_OFF:      
			
			  NRF_LOG_INFO("UP_KEY_OFF=%x",keyValue);
				break;
		case DOWN_KEY_OFF: 
			   NRF_LOG_INFO("DOWN_KEY_OFF=%x",keyValue);
				
			break;
		case UP_DOWN_KEY_OFF:
			 NRF_LOG_INFO("UP_DOWN_KEY_OFF=%x",keyValue);
			break;
	
	 case UP_KEY_LONG:    //此事件未調用阻止長按鍵,此事件會不停觸發,直到按鍵鬆開
		 NRF_LOG_INFO("UP_KEY_LONG=%x",keyValue);
		 break;
	 case UP_KEY_LONG_OFF:
		 NRF_LOG_INFO("UP_KEY_LONG_OFF=%x",keyValue);
		 break;
	 case DOWN_KEY_LONG:
		   NRF_LOG_INFO("DOWN_KEY_LONG=%x",keyValue);
			 DisLongKeyContinueResponse();  //阻止長按鍵,僅觸發一次
			break;
	 case DOWN_KEY_LONG_OFF:
		  NRF_LOG_INFO("DOWN_KEY_LONG_OFF=%x",keyValue);
		 break;
	 case UP_DOWN_KEY_LONG:
		NRF_LOG_INFO("UP_DOWN_KEY_LONG=%x",keyValue);
		 DisLongKeyContinueResponse();  //阻止長按鍵,僅觸發一次
		 break;
	 case UP_DOWN_KEY_LONG_OFF:
		 NRF_LOG_INFO("UP_DOWN_KEY_LONG_OFF=%x",keyValue);
		 break;
		default:
			break;
	}
	
}
  • 在tick_25hz_handler函數中調用keyProcessHandler函數進行按鍵掃描 


/**
* @brief 25Hz handler
*
*/
static void tick_25hz_handler(void)
{
	if((s_wakeup_flag & TICK_FOR_25HZ) == 0)
	  return;
	s_wakeup_flag &= CLEAR_TICK_FOR_25HZ;
//####################################################################################
	//---------TODO this to add 25hz event handler-----------
	BSP_adc_convert_handler();
        buzzer_beep_sound_handler();
	uart1_rec_timeout();
	keyProcessHandler();
}
  • 分析下按鍵掃描原理實現

1. 按鍵列表變量,此例程只使用了2個IO作爲按鍵,實現更多按鍵只需在scan_key數組中添加IO信息即可


/**
* @brief 按鍵引腳配置結構體
*
*/
typedef struct 
{
	GPIO_TypeDef *control_port;   //!< IO端口地址
	uint16_t enable_pin;          //!< 引腳序號
}SCAN_KEY_INFO;

//-----------------------以下爲按鍵引腳配置及初時化--------------------------
/**
*
* @brief 按鍵引腳配置信息初時化
*/
static const SCAN_KEY_INFO scan_key[] = {
	{GPIOA,GPIO_PIN_12},
	{GPIOA,GPIO_PIN_11},
};

2.按鍵初時化函數,對scan_key數組中的IO配置成輸入上拉,即按鍵低電平爲按下

/**
* @brief 按鍵引腳初時化配置
*/
static void key_pin_init(void)
{
	__HAL_RCC_GPIOA_CLK_ENABLE();  
	GPIO_InitTypeDef  GPIO_InitStruct;
  /* -2- Configure IOs in output push-pull mode to drive external LEDs */
  GPIO_InitStruct.Mode  = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull  = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;

	for(uint8_t i=0; i<TOTAL_KEY_NUM; i++)
	{
		GPIO_InitStruct.Pin = scan_key[i].enable_pin;
		HAL_GPIO_Init(scan_key[i].control_port, &GPIO_InitStruct);
	}
}

3.get_key_value函數獲取IO電平值,對scan_key數組中的IO從下標0開始讀取IO電平值,如有按鍵按下,將相應位置1,例如下標0的IO被按下,則鍵值的第0位置1,依此類推,下標1的IO被按下,則鍵值的第1位置1,如果沒有任何鍵按下,則鍵值爲0,也就是說,可以通過判斷鍵值不爲0說明有鍵按下


/**
* @brief 獲取鍵值
*/
static KEY_TYPE_VAR get_key_value(void)
{
	KEY_TYPE_VAR KeyTemp = 0;
	
	// 讀按鍵IO電平狀態
   for(KEY_TYPE_VAR i=0; i<TOTAL_KEY_NUM;i++)
   {
		
	if(HAL_GPIO_ReadPin(scan_key[i].control_port,scan_key[i].enable_pin) == 0)
	{
		KeyTemp |= 1<<i;
	}	
   }
   return KeyTemp;
}

4.OSReadKey函數實現鍵值事件,此函數是按鍵掃描的核心,按鍵去抖,短按,長按,短按鬆開,長按鬆開,多鍵等都是由此函數實現

/**
* @brief 按鍵鍵值掃描
*  掃描按鍵狀態返回對應的鍵值
* @param None
* @retval uint8_t
*  - 返回按鍵鍵值
*/
static KEY_TYPE_VAR OSReadKey(void)
{
	static E_KEY_SCAN_STATUS KeyEventCnt;
	static KEY_TYPE_VAR KeySampleCnt;
  KEY_TYPE_VAR KeyTemp = get_key_value();

	switch(KeyEventCnt )
	{
		case CHECK_HAS_KEY_DOWN:         // 有鍵按下
			if(KeyTemp != 0)
			{
				KeySampleCnt=0;
				KeyBuffer=KeyTemp;
				KeyEventCnt = KEY_EVENT_CHECK; 
			}	
			break;
		case KEY_EVENT_CHECK:  //按鍵事件檢測
			if(KeyTemp == KeyBuffer )
			{
				KeyBuffer |= KEY_OFF;
				return KeyTemp ;  //返回短按事件
			}
			else if(KeyTemp == (KeyBuffer & ~(KEY_OFF | KEY_LONG_ON)))
			{
					if(++KeySampleCnt>LONG_ON_DITHERING_COUNTER)  //長按時間大於2秒,此時間可以重定義
					{
						KeySampleCnt = LONG_ON_DITHERING_COUNTER-SYS_TICK_COUNTER/8;   // 重複觸發長按事件閥值
						KeyBuffer |= KEY_LONG_ON;
						return  KeyTemp | KEY_LONG_ON ; //返回長按事件
					}
			}
			else if(KeyTemp ==0)	
			{
				KeyEventCnt = CHECK_HAS_KEY_DOWN;
                                if((KeyBuffer & KEY_OFF) != KEY_OFF)
				    return 0;   //無效鍵
#if LONG_KEY_OFF_EVENT_ENABLED
				return KeyBuffer & ~KEY_BLOCK_FLAG;   //返回短按鬆開和長按鬆開事件
#else
				return KeyBuffer & ~(KEY_BLOCK_FLAG | KEY_LONG_ON);   //返回鬆開事件
#endif
			}		
			else if(((KeyBuffer & KEY_LONG_ON)==0) &&(KeySampleCnt < 5)) //多鍵同時按下,允許的按下時間,超過此時間檢測到多鍵將無效
			{
					KeyEventCnt = CHECK_HAS_KEY_DOWN;
			}
			break;
		}
	return 0;
	
}

 4.1  以第1個按鍵(scan_key[0]對應的IO)爲例 

    4.11 短按事件

     a. 按住第1個按鍵,OSReadKey函數每25Hz調用一次,函數中調用了 get_key_value獲取IO鍵值,第1個鍵對應的BIT0會置位,其它的位爲0,則IO鍵值爲1

            KEY_TYPE_VAR KeyTemp = get_key_value();

   b. KeyTemp的值爲1,KeyEventCnt狀態機初時值爲CHECK_HAS_KEY_DOWN,則進入分支CHECK_HAS_KEY_DOWN,

   由於KeyTemp爲1,條件if(KeyTemp != 0)滿足,執行按鍵計數清0,暫存鍵值到KeyBuffer,KeyBuffer值變成1,狀態機

   KeyEventCnt遷移到KEY_EVENT_CHECK狀態

c. 第2次25Hz時間到,再次調用 OSReadKey函數,再次獲取IO鍵值,如果IO還是被按下,那麼BIT0仍然保持爲1,否則爲0

         KEY_TYPE_VAR KeyTemp = get_key_value();

 c.1 先看第2次按鍵仍然按下的情況,KeyTemp爲1,KeyEventCnt狀態值爲KEY_EVENT_CHECK,則進入此分支執行,KeyBuffer的值第1次掃描的時候預存爲1,那麼if(KeyTemp == KeyBuffer )條件滿足,則將KeyBuffer的值與KEY_OFF的值按位或

運算,最後返回KeyTemp的值,此值爲1,正好是短按鍵鍵值

 

c.2 如果第2次掃描到按鍵爲鬆開,則 KEY_TYPE_VAR KeyTemp = get_key_value(); KeyTemp的值爲0,那麼返回無效鍵值0

 

5.短按鬆開,產生短按事件後,第3次或2秒以內掃描按鍵是鬆開,KeyTemp爲0,KeyBuffer有KEY_OFF標誌,則返回鬆開鍵值

            KeyBuffer & ~KEY_BLOCK_FLAG; 

6.長按事件,如果第1個按鍵一直按下且時間超過2秒,由於KeyBuffer在短按事件產生時被加上了KEY_OFF標記,所以此條件不成立,這條分KeyTemp == (KeyBuffer & ~(KEY_OFF | KEY_LONG_ON))會成立,原因是將KEY_OFF,KEY_LONG_ON標誌屏蔽了,由於按鍵按住時間超過LONG_ON_DITHERING_COUNTER的次數(2秒),則返回長按鍵值KeyTemp | KEY_LONG_ON,如果一直按下,會每隔LONG_ON_DITHERING_COUNTER-SYS_TICK_COUNTER/8時間再次觸發長按事件

 

7.長按鬆開事件,如果產生了長按事件後,按鍵鬆開後,則KeyBuffer值中有長按鍵值和KEY_OFF標誌,返回了長按事件

8.多鍵事件,如果第1個和第2個按鍵都被按下,第0位和第1位都被置1,則KeyTemp 的值爲3,

     KEY_TYPE_VAR KeyTemp = get_key_value(); 

那麼其短按事件爲

  

其它鍵值和單鍵產生類似,多鍵的允許接收時間如下條件

9.長按鍵阻塞,即僅觸發一次長按事件,在長按事件中調用DisLongKeyContinueResponse函數會阻賽長按事件被重複觸發

void DisLongKeyContinueResponse(void)
{
	KeyBuffer |= KEY_BLOCK_EVENT;   //長按鍵僅響應一次事件
}

函數調用後,由於KeyBuffer被添加了KEY_BLOCK_EVENT標誌,則以下

(((KeyBuffer & KEY_LONG_ON)==0) &&(KeySampleCnt < 5))分支將不再滿足條件,即進行了長按阻塞

 

  • keyProcessHandler函數 


/** 
* @brief 按鍵事件處理,此函數中定時事件中調用,此例程在25Hz中調用
*/
void keyProcessHandler(void)
{
	 KEY_TYPE_VAR event = OSReadKey();
	if(event == NO_KEY_EVENT)
		return;
	
//	NRF_LOG_INFO("KEY=%x",event);
	if(keyFunctionHandler != NULL)
	{
		keyFunctionHandler((E_KEY_VALUE)event);
	}

}

此函數在25Hz函數中調用(40毫秒調用一次),event爲NO_KEY_EVENT將不將任何處理,如果有鍵值產生,則調用函數指針keyFunctionHandler進行事件回調

  • key_event_handler回調函數,此函數由使用者編寫,由初時化函數key_init進行註冊 


/**
* @brief 按鍵功能處理
*   分配ID及獲取歷史數據按鍵功能響應處理
* @param [in] E_KEY_VALUE 按鍵鍵值
* @retval 
* - None
*/
static void key_event_handler(E_KEY_VALUE keyValue)
{
	
	
	switch(keyValue)
	{
		case UP_KEY_SHORT:  // UP 短按
			NRF_LOG_INFO("UP_KEY_SHORT=%x",keyValue); 
			break;
		case DOWN_KEY_SHORT:   // DOWN 短按
			NRF_LOG_INFO("DOWN_KEY_SHORT=%x",keyValue);
			break;
		case UP_DOWN_KEY_SHORT:  // UP+DOWN 短按
			NRF_LOG_INFO("UP_DOWN_KEY_SHORT=%x",keyValue);
			break;
		case UP_KEY_OFF:      // UP 短按鬆開
			
			  NRF_LOG_INFO("UP_KEY_OFF=%x",keyValue);
				break;
		case DOWN_KEY_OFF:   // DWON 短按鬆開
			   NRF_LOG_INFO("DOWN_KEY_OFF=%x",keyValue);
				
			break;
		case UP_DOWN_KEY_OFF:  // UP + DOWN 短按鬆開
			 NRF_LOG_INFO("UP_DOWN_KEY_OFF=%x",keyValue);
			break;
	
	 case UP_KEY_LONG:    //UP長按,此事件未調用阻止長按鍵,此事件會不停觸發,直到按鍵鬆開
		 NRF_LOG_INFO("UP_KEY_LONG=%x",keyValue);
		 break;
	 case UP_KEY_LONG_OFF:  //UP長按鬆開
		 NRF_LOG_INFO("UP_KEY_LONG_OFF=%x",keyValue);
		 break;
	 case DOWN_KEY_LONG: //DOWN長按
		   NRF_LOG_INFO("DOWN_KEY_LONG=%x",keyValue);
			 DisLongKeyContinueResponse();  //阻止長按鍵,僅觸發一次
			break;
	 case DOWN_KEY_LONG_OFF: // DOWN長按鬆開
		  NRF_LOG_INFO("DOWN_KEY_LONG_OFF=%x",keyValue);
		 break;
	 case UP_DOWN_KEY_LONG:  // UP+DOWN長按
		NRF_LOG_INFO("UP_DOWN_KEY_LONG=%x",keyValue);
		 DisLongKeyContinueResponse();  //阻止長按鍵,僅觸發一次
		 break;
	 case UP_DOWN_KEY_LONG_OFF:  // UP+DOWN長按鬆開
		 NRF_LOG_INFO("UP_DOWN_KEY_LONG_OFF=%x",keyValue);
		 break;
		default:
			break;
	}
	
}
  • Demo運行結果

  • Demo下載地址:

https://download.csdn.net/download/mygod2008ok/12554839

 

 

 

 

 

 

         

 

 

 

 

 

 

 


 

 

   

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章