樂鑫Esp32學習之旅⑦ esp32上利用GPIO中斷做一個按鍵的短按和長按的回撥事件,再也無須擔心觸發源。(附帶Demo)
阿新 • • 發佈:2019-02-02
一. 前言;
- 說到按鍵的短按和長按,很多人都是直接用
while(1)
死迴圈不斷去讀取按鍵和消抖,通過讀取時間的間隔來確定是長按還是短按!這種方法比較常用,今天的話,小徐給大家帶來的是:esp32上利用GPIO中斷做一個按鍵的短按和長按的回撥事件!更高階,更深入去了解esp32
。
二.程式碼思維圖;
上圖看的邏輯也是比較清晰了,那麼我這裡用的是中斷和
freeRtos
任務切換來實現:
二.程式碼;
- 第一步:先初始化
GPIO
,注意配置為下降沿和上升沿觸發中斷,這樣就可以在按下和擡起之間來發送訊息給訊息隊列了!
//配置GPIO,下降沿和上升沿觸發中斷
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_ANYEDGE;
io_conf.pin_bit_mask = 1 << key_gpio_pin;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
gpio_set_intr_type(key_gpio_pin, GPIO_INTR_ANYEDGE);
gpio_evt_queue = xQueueCreate(2 , sizeof(uint32_t));
//註冊中斷服務
gpio_install_isr_service(0);
gpio_isr_handler_add(key_gpio_pin, gpio_isr_handler, (void *) key_gpio_pin);
- 第二步:新建一個任務不斷去接收任務送來的中斷回撥資訊,其程式碼如下!
uint32_t io_num;
BaseType_t press_key = pdFALSE;
BaseType_t lift_key = pdFALSE;
int backup_time = 0 ;
while (1) {
//接收從訊息佇列發來的訊息
xQueueReceive(gpio_evt_queue, &io_num, ticks_to_wait);
//記錄下使用者按下按鍵的時間點
if (gpio_get_level(io_num) == 0) {
press_key = pdTRUE;
backup_time = system_get_time();
//如果當前GPIO口的電平已經記錄為按下,則開始減去上次按下按鍵的時間點
} else if (press_key) {
//記錄擡升時間點
lift_key = pdTRUE;
backup_time = system_get_time() - backup_time;
}
//僅僅當按下標誌位和按鍵彈起標誌位都為1時候,才執行回撥
if (press_key & lift_key) {
press_key = pdFALSE;
lift_key = pdFALSE;
//如果大於1s則回撥長按,否則就短按回調
if (backup_time > 1000000) {
return KEY_LONG_PRESS;
} else {
return KEY_SHORT_PRESS;
}
}
}
- 第三步:看看我們的回撥事件,其程式碼如下!
esp_err_t ret = 0;
KeyInit(KEY_GPIO);
while (1) {
ret = alink_key_scan(portMAX_DELAY);
//如果錯誤則跳出任務
if (ret == -1)
vTaskDelete(NULL);
switch (ret) {
case KEY_SHORT_PRESS:
printf("短按觸發回撥 ... \r\n");
break;
case KEY_LONG_PRESS:
printf("長按觸發回撥 ... \r\n");
break;
default:
break;
}
}
三.其他;
上面程式碼的
1000000
是指1s,如果您要改變長按2秒以上才算長按,那麼可以修改這個數值!
串列埠列印: