? ? ? ? ?在嵌入式系統開發中,按鍵輸入處理是一個常見且重要的環節。然而,許多開發者在處理按鍵時,往往會遇到按鍵消抖、組合按鍵、長按/短按等功能實現的復雜性。如何在保證系統高效運行的同時,簡化按鍵事件的處理呢?
? ? ? ? ?今天,我們向大家介紹一個小巧而靈活的按鍵處理庫——FlexibleButton。它基于標準 C 語言,簡單易用,卻具備強大的功能,可以讓你輕松實現按鍵事件的各種處理需求。
一、FlexibleButton的核心特性
-
單擊、連擊、短按、長按、自動消抖:
FlexibleButton 支持多種常見的按鍵事件:單擊、連擊、短按、長按,甚至自動消抖機制。無論你的按鍵設計復雜還是簡單,它都能幫你高效處理。 -
靈活的按鍵組合:
如果你的系統需要支持多個按鍵的組合,FlexibleButton 提供了靈活的組合按鍵設置。用戶可以自由配置按鍵組合并通過回調函數處理事件,非常方便。 -
解耦硬件設計:
FlexibleButton 的設計解耦了具體的按鍵硬件結構,使得它可以支持各種類型的按鍵,包括輕觸按鍵和自鎖按鍵。無論你采用什么硬件架構,FlexibleButton 都能輕松適配。 -
按鍵數量的無限擴展:
FlexibleButton 的架構支持按鍵數量的擴展,理論上,你可以根據需求無限增加按鍵數量,而不需要擔心性能下降或庫的復雜性增加。 -
低功耗和中斷支持:
在低功耗和中斷場景下,FlexibleButton 也能發揮重要作用。它支持通過中斷方式來處理按鍵事件,保證系統在低功耗狀態下也能高效工作。 -
簡單的按鍵掃描:
FlexibleButton 的按鍵掃描機制非常簡潔,僅需三行代碼就能完成所有按鍵狀態的讀取。無論你使用的是哪種平臺,三行按鍵掃描算法都能讓你迅速上手。
二、核心設計:三行按鍵掃描
FlexibleButton 的高效性源于其簡潔的設計:三行按鍵掃描算法。這一設計使得按鍵狀態的讀取和事件處理變得異常簡潔和高效。
for (int i = 0; i < BUTTON_COUNT; i++) {button_state[i] = read_button_state(i); // 讀取當前按鍵狀態if (button_state[i] != previous_state[i]) {handle_button_event(i, button_state[i]); // 處理按鍵事件}
}
這三行代碼簡潔明了,充分體現了FlexibleButton的高效性和簡易性。通過這種掃描方式,我們可以一次性讀取所有按鍵的狀態,并通過回調機制處理每個按鍵的狀態變化。
(1)確定用戶按鍵
typedef enum
{USER_BUTTON_0 = 0, // 對應 IoT Board 開發板的 PIN_KEY0USER_BUTTON_1, // 對應 IoT Board 開發板的 PIN_KEY1USER_BUTTON_2, // 對應 IoT Board 開發板的 PIN_KEY2USER_BUTTON_3, // 對應 IoT Board 開發板的 PIN_WK_UPUSER_BUTTON_MAX
} user_button_t;static flex_button_t user_button[USER_BUTTON_MAX];
上述代碼定義了 4 個按鍵,數據結構存儲在?user_button
?數組中。
(2)程序入口
int flex_button_main(void)
{rt_thread_t tid = RT_NULL;user_button_init();/* 創建按鍵掃描線程 flex_btn,線程棧 1024 byte,優先級 10 */tid = rt_thread_create("flex_btn", button_scan, RT_NULL, 1024, 10, 10);if(tid != RT_NULL){rt_thread_startup(tid);}return 0;
}
/* 使用 RT-Thread 的自動初始化 */
INIT_APP_EXPORT(flex_button_main);
如上代碼所示,首先使用user_button_init();
?初始化用戶按鍵硬件,該步驟將用戶按鍵綁定到FlexibleButton 庫。然后,使用 RT-Thread 的?INIT_APP_EXPORT
?接口導出為上電自動初始化,創建了一個“flex_btn” 名字的按鍵掃描線程,線程里掃描檢查按鍵事件。
(3)按鍵初始化代碼
? ?user_button_init();
?初始化代碼如下所示:
static void user_button_init(void)
{int i;/* 初始化按鍵數據結構 */rt_memset(&user_button[0], 0x0, sizeof(user_button));/* 初始化 IoT Board 按鍵引腳,使用 rt-thread PIN 設備框架 */rt_pin_mode(PIN_KEY0, PIN_MODE_INPUT_PULLUP); /* 設置 GPIO 為上拉輸入模式 */rt_pin_mode(PIN_KEY1, PIN_MODE_INPUT_PULLUP); /* 設置 GPIO 為上拉輸入模式 */rt_pin_mode(PIN_KEY2, PIN_MODE_INPUT_PULLUP); /* 設置 GPIO 為上拉輸入模式 */rt_pin_mode(PIN_WK_UP, PIN_MODE_INPUT_PULLDOWN); /* 設置 GPIO 為下拉輸入模式 */for (i = 0; i < USER_BUTTON_MAX; i ++){user_button[i].id = i;user_button[i].usr_button_read = common_btn_read;user_button[i].cb = common_btn_evt_cb;user_button[i].pressed_logic_level = 0;user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500);user_button[i].long_press_start_tick = FLEX_MS_TO_SCAN_CNT(3000);user_button[i].long_hold_start_tick = FLEX_MS_TO_SCAN_CNT(4500);if (i == USER_BUTTON_3){user_button[USER_BUTTON_3].pressed_logic_level = 1;}flex_button_register(&user_button[i]);}
}
核心的配置如下:
配置項 | 說明 |
---|---|
id | 按鍵編號 |
usr_button_read | 設置按鍵讀值回調函數 |
cb | 設置按鍵事件回調函數 |
pressed_logic_level | 設置按鍵按下時的邏輯電平 |
short_press_start_tick | 短按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏轉化為掃描次數 |
long_press_start_tick | 長按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏轉化為掃描次數 |
long_hold_start_tick | 超長按起始 tick,使用 FLEX_MS_TO_SCAN_CNT 宏轉化為掃描次數 |
注意,short_press_start_tick、long_press_start_tick 和 long_hold_start_tick 必須使用?FLEX_MS_TO_SCAN_CNT
?將毫秒時間轉化為掃描次數。
user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500);
?表示按鍵按下開始計時,1500 ms 后按鍵依舊是按下狀態的話,就斷定為短按開始。
(4)事件處理代碼
static void common_btn_evt_cb(void *arg)
{flex_button_t *btn = (flex_button_t *)arg;rt_kprintf("id: [%d - %s] event: [%d - %30s] repeat: %d\n", btn->id, enum_btn_id_string[btn->id],btn->event, enum_event_string[btn->event],btn->click_cnt);if (flex_button_event_read(&user_button[USER_BUTTON_0]) == flex_button_event_read(&user_button[USER_BUTTON_1]) == FLEX_BTN_PRESS_CLICK){rt_kprintf("[combination]: button 0 and button 1\n");}
}
示例代碼中,將所有的按鍵事件回調均綁定到?common_btn_evt_cb
?函數,在該函數中打印了按鍵 ID 和按鍵事件,以及按鍵連擊次數,并演示了如何使用組合按鍵。
三、適用場景
FlexibleButton 的適用場景非常廣泛,特別適合以下幾類項目:
- 低功耗嵌入式系統:
?通過中斷和按鍵消抖機制,能夠在低功耗模式下高效工作。
- 復雜按鍵輸入場景:
?支持組合按鍵、長按/短按等多種按鍵事件。
- 跨平臺開發:
?基于標準 C 語言,支持各種硬件平臺和操作系統,甚至是裸機系統。
- 實時按鍵響應需求:
?通過事件回調機制,保證按鍵事件能夠快速響應并處理。
四、為何選擇FlexibleButton?
- 小巧而高效:
?相較于其他按鍵處理庫,FlexibleButton 不僅小巧,還具有極高的處理效率,非常適合嵌入式系統中的資源受限場景。
- 易于集成:
?由于使用了標準 C 語言 API,FlexibleButton 可以無縫集成到各種處理器平臺和操作系統中,不需要額外的依賴。
- 可擴展性強:
?它的架構設計讓你可以根據需求自由添加更多按鍵,且不會增加過多的復雜度。
- 支持事件回調:
?靈活的事件回調機制可以讓你更直觀地處理各種按鍵事件,增強系統的響應速度和可維護性。
? ? 無論是簡單的按鍵控制,還是復雜的多按鍵組合,FlexibleButton?都能幫助你輕松應對。它的高效性、靈活性和易用性使得它在嵌入式開發中成為理想的按鍵處理方案。通過FlexibleButton,你可以專注于業務邏輯的實現,而不必為按鍵處理的復雜性煩惱。
立即嘗試 FlexibleButton,讓你的按鍵輸入處理更簡單、更高效!https://github.com/murphyzhao/FlexibleButton