按鍵做爲經常使用的輸入系統,如何準確並高效的獲取按鍵值,是一個常常要面對的問題,今天咱們看看在鴻蒙系統中,如何獲得獨立按鍵的按鍵值。python
實現目標
咱們此次以Hi3861核心板左下角的USER按鍵S2爲例,當按鍵按下時,經過USB Type-c對應的串口輸出信息。程序員
按鍵S2在實物中的對應關係以下圖黃線所示:微信
按鍵原理圖
核心板左下角的按鍵S2的原理圖以下:ide
當S2被按下以後,GPIO05與GND相連,此時GPIO05輸入爲低電平。函數
代碼實現
實現方式一:讀取輸入IO的狀態
#include <stdio.h> #include <unistd.h> #include "ohos_init.h" #include "cmsis_os2.h" #include "wifiiot_gpio.h" #include "wifiiot_gpio_ex.h" #include "wifiiot_errno.h" static void Key_Task(const char* arg) { (void)arg; printf("Enter the Key_Task ... \n"); while (1) { WifiIotGpioValue wigv; GpioGetInputVal(WIFI_IOT_IO_NAME_GPIO_5,&wigv); if (wigv == WIFI_IOT_GPIO_VALUE0) { usleep(10*1000); //10ms while(1) { GpioGetInputVal(WIFI_IOT_IO_NAME_GPIO_5,&wigv); if (wigv == WIFI_IOT_GPIO_VALUE1){ printf("[DEMO] GPIO05 Low level.\n"); break; } } } } return; } static void KeyExampleEntry(void) { unsigned int ret = 0; GpioInit(); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_IO_FUNC_GPIO_5_GPIO); GpioSetDir(WIFI_IOT_GPIO_IDX_5, WIFI_IOT_GPIO_DIR_IN); if (ret != WIFI_IOT_SUCCESS) { printf("===== ERROR ======gpio -> GpioSetDir ret:%d\r\n", ret); return; } osThreadAttr_t attr = {0}; attr.name = "Key_Task"; attr.attr_bits = 0U; attr.cb_mem = NULL; attr.cb_size = 0U; attr.stack_mem = NULL; attr.stack_size = 1024; attr.priority = osPriorityNormal; if(osThreadNew((osThreadFunc_t)Key_Task,NULL,&attr) == NULL) { printf("Failed to create Key_Task !\n"); } } SYS_RUN(KeyExampleEntry);
編譯代碼:學習
python build.py wifiiot
更新固件以後重啓最小系統板,打開串口助手,點擊核心板上的USER按鍵S2,串口助手輸出信息以下:ui
注意:
此實例新建了一個任務用於循環讀取按鍵的狀態,KeyExampleEntry做爲應用程序的入口函數,不能隨意使用while(1)這種耗時的操做,必須快速返回,不然會妨礙鴻蒙OS中其餘應用程序的運行,所以,在這個入口函數中建立一個按鍵狀態監測的專屬任務(線程)用於判斷按鍵的狀態。
spa
GPIO中斷
經過上面的原理圖咱們可知,當按鍵S2沒有被按下的時候,GPIO05爲默認狀態高電平,當按鍵S2被按下時,GPIO05與GND相連,GPIO05被拉低,當鬆開按鍵S2的時候,GPIO05又恢復高電平。操作系統
在此過程當中,當按鍵S2被按下時,GPIO05會收到一個由高到低的電平變化,咱們稱這個過程爲降低沿;當按鍵S2被鬆開時,GPIO05會收到一個由低到高的電平變化,咱們稱這個過程爲上升沿。線程
綜上所述,在不考慮抖動影響的前提下,每次按鍵被按下,GPIO05將會收到一個降低沿;按鍵被釋放,GPIO05會收到一個上升沿。
咱們在GPIO05這個引腳上註冊一個邊沿觸發函數(上升沿或者降低沿觸發均可以),那麼這個註冊的邊沿觸發回調函數被調用一次,理論上就是有一次按鍵的動做發生。
#include <stdio.h> #include <unistd.h> #include "ohos_init.h" #include "cmsis_os2.h" #include "wifiiot_gpio.h" #include "wifiiot_gpio_ex.h" #include "wifiiot_errno.h" /* gpio callback func */ void gpio5_isr_func(char *arg) { (void)arg; printf("----- gpio05 isr success -----\r\n"); } static void KeyExampleEntry(void) { unsigned int ret = 0; GpioInit(); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_IO_FUNC_GPIO_5_GPIO); GpioSetDir(WIFI_IOT_GPIO_IDX_5, WIFI_IOT_GPIO_DIR_IN); //IoSetPull(WIFI_IOT_GPIO_IDX_5,WIFI_IOT_IO_PULL_UP); if (ret != WIFI_IOT_SUCCESS) { printf("===== ERROR ======gpio -> GpioSetDir ret:%d\r\n", ret); return; } ret = GpioRegisterIsrFunc(WIFI_IOT_GPIO_IDX_5,WIFI_IOT_INT_TYPE_EDGE,WIFI_IOT_GPIO_EDGE_RISE_LEVEL_HIGH, gpio5_isr_func, NULL); if (ret != WIFI_IOT_SUCCESS) { printf("===== ERROR ======gpio -> hi_gpio_register_isr_function ret:%d\r\n", ret); } } SYS_RUN(KeyExampleEntry);
代碼說明:
-
WIFI_IOT_IO_NAME_GPIO_5是與按鍵S2相連的GPIO,要實現按鍵中斷捕獲,須要先使用IoSetFunc() 函數進行端口功能重定義;
-
調用GpioSetDir()函數,設置GPIO05爲輸入,並經過IoSetPull() 函數將端口設置爲上拉輸入(Pull Up);
- 調用GpioRegisterIsrFunc()函數,完成GPIO05和回調函數gpio5_isr_func()的註冊綁定,設置觸發模式爲上升沿觸發:WIFI_IOT_GPIO_EDGE_RISE_LEVEL_HIGH,當按鍵S2被擡起的時候,產生上升沿,觸發回調函數gpio5_isr_func()工做。
經過上面兩種方式,咱們學會了獨立按鍵狀態的獲取、鴻蒙系統中如何建立任務和外部中斷的使用,利用此代碼,咱們還能夠用於識別熱釋紅外傳感器的響應信號。
資料獲取
公衆號留言區置頂留言獲取本文相關代碼。
ps: 文章首發於電子發燒友。
小哈有話說
最近在鴻蒙交流羣中看到下面一大批開發板要移植鴻蒙操做系統了,等到這些廠商將板卡移植好了,那麼鴻蒙就真的成氣候了,做爲一個嵌入式開發者,學習一個實時操做系統是必不可少的,學什麼都是學,爲何不學一個有前途的呢?
歡迎關注
程序員小哈帶你玩轉嵌入式,微信搜索:嵌入式從0到1,更多幹貨等着你。