stm32按鍵 長按 短按 函數 二

在學習過程中,遇到了要使用很多個按鍵的情況,(沒有同時按下的處理,沒有用矩陣鍵盤)。一增加一個新按鍵,需要改動的地方太多,在網上看了一篇博客

https://blog.csdn.net/jiejiemcu/article/details/83097992

覺得它使用的方法不錯,就進行學習研究,移植到stm32單片機上。這種編程思想值得學習,做個小總結。

typedef struct button
{
	/* 下面是一個函數指針,指向判斷按鍵手否按下的函數 */
  uint8_t (*Read_Button_Level)(void); /* 讀取按鍵電平函數,需要用戶實現 */
	 
	char Name[BTN_NAME_MAX];
	uint8_t Button_State   :      4;          /* 按鍵當前狀態(按下還是彈起) */
	uint8_t Button_Last_State :   4;    	  /* 上一次的按鍵狀態,用於判斷雙擊 */
	uint8_t Button_Trigger_Level: 2;          /* 按鍵觸發電平 */
	uint8_t Button_Last_Level:    2;          /* 按鍵當前電平 */
  uint8_t Button_Trigger_Event;               /* 按鍵觸發事件,單擊,雙擊,長按等 */
	
	Button_CallBack CallBack_Function[number_of_event];
	
	uint8_t Button_Cycle;                      /* 連續按鍵週期 */
	uint8_t Timer_Count;                       /* 計時 */
	uint8_t Debounce_Time;                     /* 消抖時間 */
	
	uint8_t Long_Time_Record;                  /* 有長按記錄 */
	uint8_t Long_Time;                         /* 按鍵按下持續時間 */
	struct button *Next;
}Button_t

uint8_t (*Read_Button_Level)(void); /* 讀取按鍵電平函數,需要用戶實現 */

這段代碼是一個函數指針形式,指向函數的指針,可以用來塞用戶的函數

函數指針的定義:如果在程序中定義了一個函數,那麼在編譯時系統就會爲這個函數代碼分配一段存儲空間,這段存儲空間的首地址稱爲這個函數的地址。而且函數名錶示的就是這個地址。既然是地址我們就可以定義一個指針變量來存放,這個指針變量就叫作函數指針變量,簡稱函數指針。

關於函數指針的詳解:

 https://blog.csdn.net/luoyayun361/article/details/80428882

Button_CallBack CallBack_Function[number_of_event];  這是一個回調函數的數組,

#define TRIGGER_CB(event) \ if(btn->CallBack_Function[event]) \ btn->CallBack_Function[event]((Button_t*)btn)

這個是關於回調的解析:

https://blog.csdn.net/booirror/article/details/20007009

通過jlink_rttview 進行打印,按鍵的信息

按鍵1按下,短按,雙擊,長按,長按釋放

這裏是20ms輪詢一下相應的按鍵狀態查詢函數

按鍵的創建程序,相應的回調函數,事件和stm32的低層函數進行連接

/************************************************************
  * @brief   按鍵創建
  * @param   name : 按鍵名稱
  * @param   btn : 按鍵結構體
  * @param   read_btn_level : 按鍵電平讀取函數,需要用戶自己實現返回uint8_t類型的電平
  * @param   btn_trigger_level : 按鍵觸發電平
  * @note    NULL
  ***********************************************************/
void Button_Create(const char *name,
	               Button_t   *btn,
                   uint8_t(*read_btn_level)(void),
			uint8_t btn_trigger_level)
{
  if(btn == NULL)
	{
	    SEGGER_RTT_WriteString(0, RTT_CTRL_TEXT_BRIGHT_RED"struct button is null!"RTT_CTRL_RESET"\n");
	}
  
	memset(btn,0,sizeof(*btn));
	StrnCopy(btn->Name,name,BTN_NAME_MAX);
	
  btn->Button_State = NONE_TRIGGER;           
  btn->Button_Last_State = NONE_TRIGGER;      
  btn->Button_Trigger_Event = NONE_TRIGGER;   
  btn->Read_Button_Level = read_btn_level;   
  btn->Button_Trigger_Level = btn_trigger_level;  
  btn->Button_Last_Level = btn->Read_Button_Level();  
  btn->Debounce_Time = 0;
	btn->Long_Time_Record = 0;
  SEGGER_RTT_printf(0,"button create success \n");

  Add_Button(btn);
  Print_Btn_Info(btn);

}

相應的回調函數,用戶可以將要處理的事件放在這段函數裏

/************************************************************
  * @brief   相應的回調事件
  * @param   btn:處理的按鍵
  * @return  NULL
  * @note    用戶可在這裏添加自己的事件處理函數
  ***********************************************************/
void Btn1_Down_CallBack(void *btn)
{
   SEGGER_RTT_printf(0,"Btn1_Down_CallBack\n");
}
void Btn1_Double_CallBack(void *btn)
{
   SEGGER_RTT_printf(0,"Btn1_Double_CallBack\n");
}
void Btn1_Long_CallBack(void *btn)
{
   SEGGER_RTT_printf(0,"Btn1_Long_CallBack\n");
}
void Btn1_LongFree_CallBack(void *btn)
{
   SEGGER_RTT_printf(0,"Btn1_LongFree_CallBack\n");
}

這是修改後,並應用的工程,希望從網絡中學習到更多的東西

鏈接:https://pan.baidu.com/s/1o3xpBR1_bWkAQx1kgv5yNA 
提取碼:27pt 
 

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