看到以前一個老友寫的MultiButton開源按鍵組件的剖析講解,它的設計思想簡潔且高效,如下是他的博客介紹的MultiButton這個教程:
MultiButton | 一個小巧簡單易用的事件驅動型按鍵驅動模塊
至於介紹和使用在這裏我就很少說了,相信看上面這篇文章你應該就懂了,但我想,能不能跟菜單操做綁定在一塊呢?這樣我不就能夠利用起來,實現一個高效穩定的菜單+按鍵結合狀態機框架?web
縱觀網上不少寫菜單框架的,要不寫得太死板,要不太冗長了,超級麻煩,也很差維護和升級,個人項目設計原則:簡單看得懂,實用,穩定。框架
一般一些手持式設備都會有各類各樣的按鍵,好比左、中、右、肯定、返回、電源鍵等等,以我目前公司的產品,通常就這幾個按鍵。svg
但公司的產品主要的業務邏輯仍是應用,應用邏輯其實就是利用按鍵+頁面的形式來體現,這就少不了須要實現一套簡單、高效、穩定、可拓展、可維護的菜單+按鍵的軟件框架,有了這麼一套好用的框架,後面隨便換一個產品,就不用從新再去開發了,咱們就能夠專一於應用實現,把精力放在更有意義的軟件業務邏輯上來。函數
接下來咱們在MultiButton的.h文件中添加菜單框架相關的結構體以及一些枚舉:測試
/*菜單,具體是哪一個頁面,這個留給用戶本身去添加*/ typedef enum { MAIN_PAGE = 0, LOG_PAGE, } MENU; /*事件值,能夠留給用戶本身去定義,這裏我定義了一些我須要的事件*/ typedef enum { /*第一個事件爲-1用來定義一個防止重複觸發的值*/ NULL_KEY_EVENT = -1, LEFT_KEY_SHORT = 0, LEFT_KEY_LONG = 1, ENTER_KEY_SHORT = 2, ENTER_KEY_LONG = 3, RIGHT_LEY_SHORT = 4, RIGHT_KEY_LONG = 5, UP_KEY_SHORT = 6, UP_KEY_LONG = 7, DOWN_KEY_SHORT = 6, DOWN_KEY_LONG = 7, RETRUN_KEY_SHORT = 8, RETRUN_KEY_LONG = 9, POWER_KEY_SHORT = 10, POWER_KEY_LONG = 11, } EVENT_CODE; /*菜單操做結構體*/ typedef struct Menu { /*當前正在執行的頁面*/ uint8_t Current_Page ; /*當前觸發的事件*/ int KeyEvent ; } Menu ; /*菜單初始化*/ void menu_init(struct Menu *handle, uint8_t Page, int EVENT_CODE); /*獲取當前菜單*/ uint8_t Get_Menu(struct Menu *handle); /*菜單跳轉*/ void Set_Menu(struct Menu *handle, uint8_t Page); /*獲取當前發生的事件值*/ int Get_Event_Code(struct Menu *handle); /*設置當前發生的事件值*/ void Set_Event_Code(struct Menu *handle, int Event_Code);
再來看看.c文件相關函數的實現:ui
/*菜單初始化*/ void menu_init(struct Menu *handle, uint8_t Page, int EVENT_CODE) { memset(handle, 0, sizeof(struct Menu)); handle->Current_Page = Page ; handle->KeyEvent = EVENT_CODE ; } /*菜單跳轉*/ void Set_Menu(struct Menu *handle, uint8_t Page) { handle->Current_Page = Page ; } /*獲取當前菜單*/ uint8_t Get_Menu(struct Menu *handle) { return handle->Current_Page ; } /*設置當前發生的事件值*/ void Set_Event_Code(struct Menu *handle, int Event_Code) { handle->KeyEvent = Event_Code ; } /*獲取當前發生的事件值*/ int Get_Event_Code(struct Menu *handle) { return handle->KeyEvent ; }
很是簡單,菜單的操做就在MutilButton的兩個文件中添加完成了,接下來看看怎麼來使用吧?
一、常規的MultiButton的使用方法.net
//這裏我 Button button ; /*讀取按鍵狀態*/ uint8_t read_button_pin_status(void) { return HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin); ; }
初始化multi_button並註冊button event設計
button_init(&button, read_button_pin_status, 0); button_attach(&button, SINGLE_CLICK, button_callback); button_attach(&button, LONG_RRESS_START, button_callback); button_start(&button);
當前我註冊的這個按鍵的回調函數是同一個函數,而同一個函數作不一樣的處理:code
void button_callback(void *event) { uint8_t button_event = get_button_event(&button) ; switch(button_event) { case SINGLE_CLICK: /*當按鍵發生單擊時,註冊爲ENTER_KEY_SHORT*/ Set_Event_Code(&menu, ENTER_KEY_SHORT); break ; case LONG_RRESS_START: /*當按鍵發生長按時,註冊爲ENTER_KEY_LONG*/ Set_Event_Code(&menu, ENTER_KEY_LONG); break ; default: break ; } }
二、初始化菜單以及初始化觸發事件xml
Menu menu ; //初始化頁面爲主頁面,初始事件爲NULL_KEY_EVENT menu_init(&menu, MAIN_PAGE, NULL_KEY_EVENT);
三、循環調用菜單處理函數(用戶自行實現)
while(1) { /*用戶代碼*/ /*......*/ Menu_Handler(&menu); /*......*/ /*用戶代碼*/ }
注意,這裏還須要一個5ms的定時器來調用button_ticks();這樣MultiButton才能真正工做起來,我採用的事另一套開源的軟件定時器框架MultiTimer來實現的,這裏就不貼出來了,後面直接分享工程實踐測試源代碼。
菜單處理函數的實現:
/*菜單處理*/ void Menu_Handler(struct Menu *handle) { /*當前是菜單的哪一個頁面*/ switch(handle->Current_Page) { case MAIN_PAGE : /*針對註冊的鍵值作相應的處理*/ main_page_process(handle->KeyEvent); break ; case LOG_PAGE: /*針對註冊的鍵值作相應的處理*/ log_page_process(handle->KeyEvent); break ; default: break ; } /*及時將事件清除,防止重複觸發*/ Set_Event_Code(handle, NULL_KEY_EVENT); }
相應的菜單處理函數:
void main_page_process(uint8_t Event_Code) { switch(Event_Code) { /*當發生事件時,須要的時候作狀態切換*/ case ENTER_KEY_SHORT: printf("發生單擊,進入頁面1\n"); Set_Menu(&menu, LOG_PAGE); break ; case ENTER_KEY_LONG: printf("在頁面0發生長按\n"); break ; } } void log_page_process(uint8_t Event_Code) { switch(Event_Code) { case ENTER_KEY_SHORT: printf("在頁面1發生單擊\n"); break ; /*當發生事件時,須要的時候作狀態切換*/ case ENTER_KEY_LONG: printf("發生長按,返回頁面0\n"); Set_Menu(&menu, MAIN_PAGE); break ; } }
測試運行結果:
測試平臺:stm32f103c8t6
測試工程:
連接:https://pan.baidu.com/s/124jks9I9uVXmKN3SXHQXvg 提取碼:hv3g 複製這段內容後打開百度網盤手機App,操做更方便哦
本文同步分享在 博客「Engineer-Bruce_Yang」(CSDN)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。