rtt packages button drive
前幾天寫了個按鍵驅動,參考了MulitButton的數據結構的用法,邏輯實現並不一樣。
Button_drive是一個小巧的按鍵驅動,支持單擊、雙擊、長按、連續觸發等(後續可以在按鍵控制塊中添加觸發事件),理論上可無限量擴展Button,Button_drive採用按鍵觸發事件回調方式處理業務邏輯,支持在RTOS中使用,我目前僅在RT-Thread上測試過。
1Button_t Button1; 2Button_t Button2;
1 Button_Create("Button1", //按鍵名字 2 &Button1, //按鍵句柄 3 Read_Button1_Level, //按鍵電平檢測函數介面 4 BTN_TRIGGER); //觸發電平 5 6 ......
1 Button_Attach(&Button1,BUTTON_DOWM,Btn2_Dowm_CallBack); //按鍵單擊 2 Button_Attach(&Button1,BUTTON_DOUBLE,Btn2_Double_CallBack); //雙擊 3 Button_Attach(&Button1,BUTTON_LONG,Btn2_Long_CallBack); //長按 4 5 .......
1Button_Process(); //需要周期調用按鍵處理函數
需要用戶實現的 2 個函數:
1uint8_t Read_Button1_Level(void) 2{ 3 return GPIO_ReadInputDataBit(BTN1_GPIO_PORT,BTN1_GPIO_PIN); 4} 5 6uint8_t Read_Button2_Level(void) 7{ 8 return GPIO_ReadInputDataBit(BTN2_GPIO_PORT,BTN2_GPIO_PIN); 9} 10 11// 這是我在stm32上簡單測試的偽代碼,以實際源碼為準
1void Btn1_Dowm_CallBack(void *btn) 2{ 3 PRINT_INFO("Button1 單擊!"); 4} 5 6void Btn1_Double_CallBack(void *btn) 7{ 8 PRINT_INFO("Button1 雙擊!"); 9} 10 11void Btn1_Long_CallBack(void *btn) 12{ 13 PRINT_INFO("Button1 長按!"); 14 15 Button_Delete(&Button2); 16 PRINT_INFO("刪除Button1"); 17 Search_Button(); 18}
Button_drive開放源碼,按鍵控制塊採用數據結構方式,按鍵事件採用枚舉類型,確保不會重複,也便於添加用戶需要邏輯,採用宏定義方式定義消抖時間、連按觸發時間、雙擊時間間隔、長按時間等,便於修改。
Button_Process()
支持按鍵刪除操作,用戶無需在代碼中刪除對應的按鍵創建於映射鏈接代碼,也無需刪除關於按鍵的任何回調事件處理函數,只需調用Button_Delete()函數即可,這樣子,就不會處理關於被刪除按鍵的任何狀態。當然目前按鍵內存不會釋放,如果使用os的話,建議釋放按鍵內存。
Button_Delete()
1/* 2 每個按鍵對應1個全局的結構體變數。 3 其成員變數是實現消抖和多種按鍵狀態所必須的 4*/ 5typedef struct button 6{ 7 /* 下面是一個函數指針,指向判斷按鍵手否按下的函數 */ 8 uint8_t (*Read_Button_Level)(void); /* 讀取按鍵電平函數,需要用戶實現 */ 9 10 char Name[BTN_NAME_MAX]; 11 12 uint8_t Button_State : 4; /* 按鍵當前狀態(按下還是彈起) */ 13 uint8_t Button_Last_State : 4; /* 上一次的按鍵狀態,用於判斷雙擊 */ 14 uint8_t Button_Trigger_Level : 2; /* 按鍵觸發電平 */ 15 uint8_t Button_Last_Level : 2; /* 按鍵當前電平 */ 16 17 uint8_t Button_Trigger_Event; /* 按鍵觸發事件,單擊,雙擊,長按等 */ 18 19 Button_CallBack CallBack_Function[number_of_event]; 20 uint8_t Button_Cycle; /* 連續按鍵周期 */ 21 22 uint8_t Timer_Count; /* 計時 */ 23 uint8_t Debounce_Time; /* 消抖時間 */ 24 25 uint8_t Long_Time; /* 按鍵按下持續時間 */ 26 27 struct button *Next; 28 29}Button_t;
1typedef enum { 2 BUTTON_DOWM = 0, 3 BUTTON_UP, 4 BUTTON_DOUBLE, 5 BUTTON_LONG, 6 BUTTON_CONTINUOS, 7 BUTTON_CONTINUOS_FREE, 8 BUTTON_ALL_RIGGER, 9 number_of_event, /* 觸發回調的事件 */ 10 NONE_TRIGGER 11}Button_Event;
1#define BTN_NAME_MAX 32 //名字最大為32位元組 2 3/* 按鍵消抖時間40ms, 建議調用周期為20ms 4 只有連續檢測到40ms狀態不變才認為有效,包括彈起和按下兩種事件 5*/ 6 7#define CONTINUOS_TRIGGER 0 //是否支持連續觸發,連發的話就不要檢測單雙擊與長按了 8 9/* 是否支持單擊&雙擊同時存在觸發,如果選擇開啟宏定義的話,單雙擊都回調,只不過單擊會延遲響應, 10 因為必須判斷單擊之後是否觸發了雙擊否則,延遲時間是雙擊間隔時間 BUTTON_DOUBLE_TIME。 11 而如果不開啟這個宏定義,建議工程中只存在單擊/雙擊中的一個,否則,在雙擊響應的時候會觸發一次單擊, 12 因為雙擊必須是有一次按下並且釋放之後才產生的 */ 13#define SINGLE_AND_DOUBLE_TRIGGER 1 14 15/* 是否支持長按釋放才觸發,如果打開這個宏定義,那麼長按釋放之後才觸發單次長按, 16 否則在長按指定時間就一直觸髮長按,觸發周期由 BUTTON_LONG_CYCLE 決定 */ 17#define LONG_FREE_TRIGGER 0 18 19#define BUTTON_DEBOUNCE_TIME 2 //消抖時間 (n-1)*調用周期 20#define BUTTON_CONTINUOS_CYCLE 1 //連按觸發周期時間 (n-1)*調用周期 21#define BUTTON_LONG_CYCLE 1 //長按觸發周期時間 (n-1)*調用周期 22#define BUTTON_DOUBLE_TIME 15 //雙擊間隔時間 (n-1)*調用周期 建議在200-600ms 23#define BUTTON_LONG_TIME 50 /* 持續n秒((n-1)*調用周期 ms),認為長按事件 */ 24 25#define TRIGGER_CB(event) 26 if(btn->CallBack_Function[event]) 27 btn->CallBack_Function[event]((Button_t*)btn)
1 Button_Create("Button1", 2 &Button1, 3 Read_KEY1_Level, 4 KEY_ON); 5 Button_Attach(&Button1,BUTTON_DOWM,Btn1_Dowm_CallBack); //單擊 6 Button_Attach(&Button1,BUTTON_DOUBLE,Btn1_Double_CallBack); //雙擊 7 Button_Attach(&Button1,BUTTON_CONTINUOS,Btn1_Continuos_CallBack); //連按 8 Button_Attach(&Button1,BUTTON_CONTINUOS_FREE,Btn1_ContinuosFree_CallBack); //連按釋放 9 Button_Attach(&Button1,BUTTON_LONG,Btn1_Long_CallBack); //長按 10 11 12 Button_Create("Button2", 13 &Button2, 14 Read_KEY2_Level, 15 KEY_ON); 16 Button_Attach(&Button2,BUTTON_DOWM,Btn2_Dowm_CallBack); //單擊 17 Button_Attach(&Button2,BUTTON_DOUBLE,Btn2_Double_CallBack); //雙擊 18 Button_Attach(&Button2,BUTTON_CONTINUOS,Btn2_Continuos_CallBack); //連按 19 Button_Attach(&Button2,BUTTON_CONTINUOS_FREE,Btn2_ContinuosFree_CallBack); //連按釋放 20 Button_Attach(&Button2,BUTTON_LONG,Btn2_Long_CallBack); //長按 21 22 Get_Button_Event(&Button1); 23 Get_Button_Event(&Button2);
流光大佬的要求,讓我玩一玩RTT的rtkpgs,打算用Button_drive練一練手吧。
目前我已將按鍵驅動做成軟體包(packages),如果使用RT-Thread操作系統的話,可以在env中直接配置使用!
步驟如下:
推薦閱讀: