鴻蒙4.WiFi IoT智能家居套件 - LED燈、按鍵、蜂鳴器的實(shí)現(xiàn)
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
https://harmonyos.51cto.com/#zz
本次在3.helloworld的基礎(chǔ)上,新增點(diǎn)亮LED燈、按鍵操作、蜂鳴器功能。本次需要用到紅黃綠燈擴(kuò)展板。
添加這三個(gè)功能,主要是因?yàn)檫@幾個(gè)功能都是比較簡單的功能,而且,這三個(gè)功能配合起來,可以實(shí)現(xiàn)比較有意思的功能,。
實(shí)現(xiàn)功能:按下擴(kuò)展板上的按鍵,蜂鳴器發(fā)聲,并且紅黃綠燈會(huì)按照紅、黃、綠、全滅的順序進(jìn)行發(fā)光,按鍵抬起,蜂鳴器停止發(fā)聲。
本代碼借鑒了唐佐林老師的教程:實(shí)現(xiàn)按鍵“按下事件”和“釋放事件”的通用框架(V0.0.1)
1、點(diǎn)亮LED燈,使用了GPIO的輸出功能,高電平點(diǎn)亮,低電平熄滅。
主要調(diào)用wifiiot_gpio.c中的函數(shù)以下函數(shù),實(shí)現(xiàn)GPIO初始化為輸出功能,且控制該IO輸出高、低電平
- unsigned int IoSetFunc(WifiIotIoName id, unsigned char val) //選擇IO的功能(GPIO、I2C、SPI、PWM等等)
- unsigned int GpioSetDir(WifiIotGpioIdx id, WifiIotGpioDir dir) //設(shè)置為輸出或輸入
- unsigned int GpioSetOutputVal(WifiIotGpioIdx id, WifiIotGpioValue val) //設(shè)置輸出值
- 示例:
- IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, 0 WIFI_IOT_IO_FUNC_GPIO_10_GPIO);//IO10設(shè)置為GPIO
- GpioSetDir(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_DIR_OUT);//IO10設(shè)置為輸出
- GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10,WIFI_IOT_GPIO_VALUE1);//IO10輸出高電平
- GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_10,WIFI_IOT_GPIO_VALUE0);//IO10輸出低電平
2、按鍵響應(yīng),使用的GPIO的輸入中斷功能,并且識(shí)別了按鍵按下(下降沿)和按鍵抬起(上升沿)
對中斷不熟悉的朋友,請參考唐佐林老師的教程:實(shí)現(xiàn)按鍵“按下事件”和“釋放事件”的通用框架(V0.0.1) 此處僅將用到幾個(gè)函數(shù)列出
- IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);//IO復(fù)用為GPIO功能
- GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_IN);//設(shè)置為輸入
- IoSetPull(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_PULL_UP);//輸入帶上拉
- GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_8,
- WIFI_IOT_INT_TYPE_EDGE,
- WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW,
- OnButtonPressed_isr, NULL);//注冊中斷服務(wù)函數(shù),邊沿觸發(fā),下降沿觸發(fā),按鍵按下后,會(huì)調(diào)用中斷服務(wù)函數(shù) OnButtonPressed_isr
3、蜂鳴器,主要使用了PWM功能,也就是脈沖寬度調(diào)制,通過調(diào)節(jié)占空比,可以控制輸出的電平,使得蜂鳴器發(fā)出不同的響聲,PWM還用于電機(jī)的控制。
注意,為了能使用PWM功能,需要使能PWM功能:將vendor\hisi\hi3861\hi3861\build\config\usr_config.mk文件中的CONFIG_PWM_SUPPORT行:# CONFIG_PWM_SUPPORT is not set修改為CONFIG_PWM_SUPPORT=y , 否則會(huì)編譯失敗
- IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT);//IO復(fù)用為PWM功能
- GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT);//設(shè)置為輸出
- PwmInit(WIFI_IOT_PWM_PORT_PWM0);//初始化PWM
- PwmStart(WIFI_IOT_PWM_PORT_PWM0, 5 * 1000, 40 * 1000);//啟動(dòng)PWM功能,此處不做詳細(xì)解釋,會(huì)單獨(dú)開一個(gè)帖子講解參數(shù)的含義
- PwmStop(WIFI_IOT_PWM_PORT_PWM0);//停止PWM
4.代碼 hello_world.c
路徑:code\applications\sample\wifi-iot\app\hello_world\hello_world.c
- /*
- 2020年11月8日
- 作者:hcl0317
- 鏈接:
- 實(shí)現(xiàn)功能:
- 使用紅綠燈擴(kuò)展板,按一下按鍵,點(diǎn)亮一個(gè)燈,按鍵按下時(shí),蜂鳴器發(fā)聲,按鍵抬起,蜂鳴器停止
- 主要功能點(diǎn):
- 1. GPIO 輸出 -> LED燈
- 2. GPIO 輸入 中斷 -> 按鍵
- 3. PWM功能 -> 蜂鳴器
- */
- //紅黃綠燈擴(kuò)展板上,對應(yīng)的GPIO10,11,12,高電平點(diǎn)燈,低電平滅燈
- static WifiIotIoName LightGPIO[] =
- {
- WIFI_IOT_IO_NAME_GPIO_10,//紅燈
- WIFI_IOT_IO_NAME_GPIO_12,//黃燈
- WIFI_IOT_IO_NAME_GPIO_11//綠燈
- };
- //紅黃綠燈擴(kuò)展板上的按鍵
- static int volatile BtnPressed = 0;//1表示按下,0表示抬起
- static int volatile BtnPressed_idx = 0;//
- static void OnButtonPressed_isr(char* arg);//按鍵按下中斷處理函數(shù)
- static void OnButtonReleased_isr(char* arg);//按鍵抬起中斷處理函數(shù)
- /*此處借鑒唐佐林老師的代碼
- 有兩個(gè)中斷服務(wù)程序是因?yàn)樵邙櫭煽蚣苤校琁O中斷只能注冊為上升沿觸發(fā)或者下降沿觸發(fā),不能注冊為任意邊沿觸發(fā)
- 我們?yōu)榱俗R(shí)別按鍵按下和抬起,在按鍵按下的中斷服務(wù)程序中,注冊上升沿中斷服務(wù)程序,以檢測按鍵抬起
- 在按鍵抬起的中斷服務(wù)程序中,注冊下降沿中斷服務(wù)程序,以檢測按鍵按下,如此就可以實(shí)現(xiàn)及檢測按鍵的抬起和按下
- */
- static void OnButtonPressed_isr(char* arg)
- {
- (void)arg;
- printf("[HelloWorld] OnButtonPressed()\n");
- BtnPressed = 1;
- BtnPressed_idx++;
- BtnPressed_idx %= 4;
- GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_8,
- WIFI_IOT_INT_TYPE_EDGE,
- WIFI_IOT_GPIO_EDGE_RISE_LEVEL_HIGH,
- OnButtonReleased_isr, NULL);
- }
- static void OnButtonReleased_isr(char* arg)
- {
- (void)arg;
- printf("[HelloWorld] OnButtonReleased()\n");
- BtnPressed = 0;
- GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_8,
- WIFI_IOT_INT_TYPE_EDGE,
- WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW,
- OnButtonPressed_isr, NULL);
- }
- //1.任務(wù)處理函數(shù)
- static void* HelloWorld_Task(const char* arg)
- {
- int i = 0;
- (void)arg;
- printf("[HelloWorld] HelloWorld_Task()\n");
- GpioInit();//使用GPIO,都需要調(diào)用該接口
- //紅黃綠燈擴(kuò)展板上,對應(yīng)的LED GPIO10,11,12初始化
- printf("LED GPIO init...\r\n");
- for(i=0; i<3; i++)
- {
- //復(fù)用引腳為 GPIO
- IoSetFunc(LightGPIO[i], 0);
- //設(shè)置為輸出
- GpioSetDir(LightGPIO[i], WIFI_IOT_GPIO_DIR_OUT);
- }
- //紅黃綠燈擴(kuò)展板上,對應(yīng)的按鍵 GPIO8 初始化為GPIO,輸入
- printf("KEY GPIO init...\r\n");
- IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);//GPIO
- GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_IN);//設(shè)置為輸入
- IoSetPull(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_PULL_UP);
- GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_8,
- WIFI_IOT_INT_TYPE_EDGE,
- WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW,
- OnButtonPressed_isr, NULL);
- //紅黃綠燈擴(kuò)展板上,對應(yīng)的蜂鳴器 GPIO9 初始化為PWM功能
- printf("PWM GPIO init...\r\n");
- IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT);//PWM
- GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT);//設(shè)置為輸出
- PwmInit(WIFI_IOT_PWM_PORT_PWM0);//初始化PWM
- while(1)
- {
- //logic code for task
- //按一次按鍵,順序點(diǎn)亮一個(gè)燈
- int j = 0;
- for(j = 0; j < 3; j++)
- {
- if(BtnPressed_idx == j)
- {
- GpioSetOutputVal(LightGPIO[j],WIFI_IOT_GPIO_VALUE1);//高電平,點(diǎn)亮燈
- }
- else
- {
- GpioSetOutputVal(LightGPIO[j],WIFI_IOT_GPIO_VALUE0);//關(guān)閉燈
- }
- }
- #if 0
- //流水燈點(diǎn)亮
- for(j = 0; j< 3; j++)
- {
- GpioSetOutputVal(LightGPIO[j],WIFI_IOT_GPIO_VALUE0);//關(guān)閉所有燈
- }
- i = (i + 1) % 3;
- GpioSetOutputVal(LightGPIO[i], WIFI_IOT_GPIO_VALUE1);//高電平,點(diǎn)亮燈
- sleep(1);//延時(shí)1秒
- #endif
- //按鍵觸發(fā)的處理
- if(BtnPressed)
- {
- PwmStart(WIFI_IOT_PWM_PORT_PWM0, 5 * 1000, 40 * 1000);//按鍵按下,蜂鳴器發(fā)聲
- }else{
- PwmStop(WIFI_IOT_PWM_PORT_PWM0);//按鍵抬起,蜂鳴器停止
- }
- //usleep(500000);
- usleep(100000);
- }
- return NULL;
- }
- //2.任務(wù)入口函數(shù)
- static void HelloWorld_Entry(void)
- {
- osThreadAttr_t attr = {0};
- printf("[HelloWorld] HelloWorld_Entry()\n");
- attr.name = "HelloWorld_Task";
- attr.attr_bits = 0U;
- attr.cb_mem = NULL;
- attr.cb_size = 0U;
- attr.stack_mem = NULL;
- attr.stack_size = 1024;//堆棧大小
- attr.priority = osPriorityNormal;//優(yōu)先級
- if (osThreadNew((osThreadFunc_t)HelloWorld_Task, NULL, &attr) == NULL)
- {
- printf("[HelloWorld] Falied to create LedTask!\n");
- }
- }
- //3.注冊模塊
- SYS_RUN(HelloWorld_Entry);
5.業(yè)務(wù)代碼的編譯腳本 BUILD.gn
路徑:code\applications\sample\wifi-iot\app\hello_world\BUILD.gn
- static_library("hello_world_app") {
- sources = [
- "hello_world.c"
- ]
- include_dirs = [
- "//utils/native/lite/include",
- "//kernel/liteos_m/components/cmsis/2.0",
- "//base/iot_hardware/interfaces/kits/wifiiot_lite",
- ]
- }
6.模塊的編譯腳本BUILD.gn
路徑:code\applications\sample\wifi-iot\app\BUILD.gn
- import("//build/lite/config/component/lite_component.gni")
- lite_component("app") {
- features = [
- "startup",
- "hello_world:hello_world_app",
- ]
- }
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
https://harmonyos.51cto.com/#zz