傑傑本身寫的一個按鍵驅動,支持單雙擊、連按、長按;採用回調處理按鍵事件(自定義消抖時間),使用只需3步,建立按鍵,按鍵事件與回調處理函數連接映射,週期檢查按鍵。git
源碼地址:github.com/jiejieTop/B…。做者:傑傑github
前幾天寫了個按鍵驅動,參考了MulitButton的數據結構的用法,邏輯實現並不同。在這裏感謝全部的開源開發者,讓我從中學到了不少,同時網絡也是一個好平臺,也但願全部的開發者能造成良性循環,從網絡中學知識,回饋到網絡中去。感謝MulitButton的做者0x1abin,感謝兩位rtt的大佬:大法師、流光。網絡
Buttondrive是一個小巧的按鍵驅動,支持單擊、雙擊、長按、連續觸發等(後續能夠在按鍵控制塊中添加觸發事件),理論上可無限量擴展Button,Buttondrive採用按鍵觸發事件回調方式處理業務邏輯,支持在RTOS中使用,我目前僅在RT-Thread上測試過。寫按鍵驅動的目的是想要將用戶按鍵邏輯與按鍵處理事件分離,用戶無需處理複雜麻煩的邏輯事件。數據結構
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2nhPnwqF-1571148176402)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/1.png?raw=true)]函數
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wtGvjTjq-1571148176403)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/2.png?raw=true)]工具
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QUypOh2s-1571148176403)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/3.png?raw=true)]開發工具
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LfsbuM1W-1571148176404)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/4.png?raw=true)]測試
Button_t Button1;
Button_t Button2; 複製代碼
Button_Create("Button1", //按鍵名字
&Button1, //按鍵句柄
Read_Button1_Level, //按鍵電平檢測函數接口
BTN_TRIGGER); //觸發電平
......複製代碼
Button_Attach(&Button1,BUTTON_DOWM,Btn2_Dowm_CallBack); //按鍵單擊
Button_Attach(&Button1,BUTTON_DOUBLE,Btn2_Double_CallBack); //雙擊
Button_Attach(&Button1,BUTTON_LONG,Btn2_Long_CallBack); //長按
.......複製代碼
Button_Process(); //須要週期調用按鍵處理函數複製代碼
須要用戶實現的 2 個函數:ui
uint8_t Read_Button1_Level(void)
{
return GPIO_ReadInputDataBit(BTN1_GPIO_PORT,BTN1_GPIO_PIN);
}
uint8_t Read_Button2_Level(void)
{
return GPIO_ReadInputDataBit(BTN2_GPIO_PORT,BTN2_GPIO_PIN);
}
// 這是我在stm32上簡單測試的僞代碼,以實際源碼爲準
複製代碼
void Btn1_Dowm_CallBack(void *btn)
{
PRINT_INFO("Button1 單擊!");
}
void Btn1_Double_CallBack(void *btn)
{
PRINT_INFO("Button1 雙擊!");
}
void Btn1_Long_CallBack(void *btn)
{
PRINT_INFO("Button1 長按!");
Button_Delete(&Button2);
PRINT_INFO("刪除Button1");
Search_Button();
}複製代碼
Button_drive開放源碼,按鍵控制塊採用數據結構方式,按鍵事件採用枚舉類型,確保不會重複,也便於添加用戶須要邏輯,採用宏定義方式定義消抖時間、連按觸發時間、雙擊時間間隔、長按時間等,便於修改。同時全部被建立的按鍵採用單鏈表方式連擊,用戶只管建立,無需理會按鍵處理,只需調用Button_Process()
便可,在函數中會自動遍歷全部被建立的按鍵。支持按鍵刪除操做,用戶無需在代碼中刪除對應的按鍵建立於映射連接代碼,也無需刪除關於按鍵的任何回調事件處理函數,只需調用Button_Delete()
函數便可,這樣子,就不會處理關於被刪除按鍵的任何狀態。固然目前按鍵內存不會釋放,若是使用os的話,建議釋放按鍵內存。spa
/*
每一個按鍵對應1個全局的結構體變量。
其成員變量是實現消抖和多種按鍵狀態所必須的
*/
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; /* 按鍵按下持續時間 */
struct button *Next;
}Button_t;
複製代碼
typedef enum {
BUTTON_DOWM = 0,
BUTTON_UP,
BUTTON_DOUBLE,
BUTTON_LONG,
BUTTON_CONTINUOS,
BUTTON_CONTINUOS_FREE,
BUTTON_ALL_RIGGER,
number_of_event, /* 觸發回調的事件 */
NONE_TRIGGER
}Button_Event;
複製代碼
#define BTN_NAME_MAX 32 //名字最大爲32字節
/* 按鍵消抖時間40ms, 建議調用週期爲20ms
只有連續檢測到40ms狀態不變才認爲有效,包括彈起和按下兩種事件
*/
#define CONTINUOS_TRIGGER 0 //是否支持連續觸發,連發的話就不要檢測單雙擊與長按了
/* 是否支持單擊&雙擊同時存在觸發,若是選擇開啓宏定義的話,單雙擊都回調,只不過單擊會延遲響應,
由於必須判斷單擊以後是否觸發了雙擊不然,延遲時間是雙擊間隔時間 BUTTON_DOUBLE_TIME。
而若是不開啓這個宏定義,建議工程中只存在單擊/雙擊中的一個,不然,在雙擊響應的時候會觸發一次單擊,
由於雙擊必須是有一次按下而且釋放以後才產生的 */
#define SINGLE_AND_DOUBLE_TRIGGER 1
/* 是否支持長按釋放才觸發,若是打開這個宏定義,那麼長按釋放以後才觸發單次長按,
不然在長按指定時間就一直觸發長按,觸發週期由 BUTTON_LONG_CYCLE 決定 */
#define LONG_FREE_TRIGGER 0
#define BUTTON_DEBOUNCE_TIME 2 //消抖時間 (n-1)*調用週期
#define BUTTON_CONTINUOS_CYCLE 1 //連按觸發週期時間 (n-1)*調用週期
#define BUTTON_LONG_CYCLE 1 //長按觸發週期時間 (n-1)*調用週期
#define BUTTON_DOUBLE_TIME 15 //雙擊間隔時間 (n-1)*調用週期 建議在200-600ms
#define BUTTON_LONG_TIME 50 /* 持續n秒((n-1)*調用週期 ms),認爲長按事件 */
#define TRIGGER_CB(event) \
if(btn->CallBack_Function[event]) \
btn->CallBack_Function[event]((Button_t*)btn)複製代碼
Button_Create("Button1",
&Button1,
Read_KEY1_Level,
KEY_ON);
Button_Attach(&Button1,BUTTON_DOWM,Btn1_Dowm_CallBack); //單擊
Button_Attach(&Button1,BUTTON_DOUBLE,Btn1_Double_CallBack); //雙擊
Button_Attach(&Button1,BUTTON_CONTINUOS,Btn1_Continuos_CallBack); //連按
Button_Attach(&Button1,BUTTON_CONTINUOS_FREE,Btn1_ContinuosFree_CallBack); //連按釋放
Button_Attach(&Button1,BUTTON_LONG,Btn1_Long_CallBack); //長按
Button_Create("Button2",
&Button2,
Read_KEY2_Level,
KEY_ON);
Button_Attach(&Button2,BUTTON_DOWM,Btn2_Dowm_CallBack); //單擊
Button_Attach(&Button2,BUTTON_DOUBLE,Btn2_Double_CallBack); //雙擊
Button_Attach(&Button2,BUTTON_CONTINUOS,Btn2_Continuos_CallBack); //連按
Button_Attach(&Button2,BUTTON_CONTINUOS_FREE,Btn2_ContinuosFree_CallBack); //連按釋放
Button_Attach(&Button2,BUTTON_LONG,Btn2_Long_CallBack); //長按
Get_Button_Event(&Button1);
Get_Button_Event(&Button2);複製代碼
流光大佬的要求,讓我玩一玩RTT的rtkpgs,打算用Button_drive練一練手吧。
目前我已將按鍵驅動作成軟件包(packages),若是使用RT-Thread操做系統的話,能夠在env中直接配置使用!
步驟以下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gG59d3Yn-1571148176404)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/5.png?raw=true)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-amGYFH8P-1571148176404)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/6.png?raw=true)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-O0a0wqdi-1571148176404)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/7.png?raw=true)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-O5sGP0CE-1571148176405)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/8.png?raw=true)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EYxByBVm-1571148176407)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/9.png?raw=true)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-e0pdTFhz-1571148176407)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/10.png?raw=true)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-lXNX8VeJ-1571148176407)(https://github.com/jiejieTop/ButtonDrive/blob/master/png/11.png?raw=true)]
buildpkg 是用於生成 RT-Thread package 的快速構建工具。
一個優秀的 package 應該是這樣的:
爲了方便快速的生成 RT-Thread package 規範化模板 以及 減輕開源倉庫遷移 RT-Thread 的前期準備工做的負擔,基於此目的的 buildpkg 應運而生,爲開發 Rt-Thread 的 package 的開發者提供輔助開發工具。
buildpkg.exe make pkgdemo
buildpkg.exe make cstring https://github.com/liu2guang/cstring.git
buildpkg.exe update pkgname
長參數 |
短參數 | 描述 |
---|---|---|
--version=v1.0.0 | -v v1.0.0 | 設置 package 的版本 |
--license=MIT | -l MIT | 設置 package 所遵循的版權協議 |
--submodule | -s | 刪除 git 子模塊 |
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CT6Hxh28-1571148176408)(/figures/buildpkg.gif)]
相關代碼能夠在公衆號後臺獲取。歡迎關注「物聯網IoT開發」公衆號