​想了解更多内容,请访问:​

​51CTO和华为官方战略合作共建的鸿蒙技术社区​

​https://harmonyos.51cto.com/#bkwz​


本次在3.helloworld的基础上,新增点亮LED灯、按键操作、蜂鸣器功能。本次需要用到红黄绿灯扩展板。

添加这三个功能,主要是因为这几个功能都是比较简单的功能,而且,这三个功能配合起来,可以实现比较有意思的功能,。

实现功能:按下扩展板上的按键,蜂鸣器发声,并且红黄绿灯会按照红、黄、绿、全灭的顺序进行发光,按键抬起,蜂鸣器停止发声。

本代码借鉴了唐佐林老师的教程:​​实现按键“按下事件”和“释放事件”的通用框架(V0.0.1)​

WiFi IoT智能家居套件 - LED灯、按键、蜂鸣器的实现_GPIO

1、点亮LED灯,使用了GPIO的输出功能,高电平点亮,低电平熄灭。

主要调用wifiiot_gpio.c中的函数以下函数,实现GPIO初始化为输出功能,且控制该IO输出高、低电平

unsigned int IoSetFunc(WifiIotIoName id, unsigned char val)  //选择IO的功能(GPIO、I2C、SPI、PWM等等)

unsigned int GpioSetDir(WifiIotGpioIdx id, WifiIotGpioDir dir) //设置为输出或输入

unsigned int GpioSetOutputVal(WifiIotGpioIdx id, WifiIotGpioValue val) //设置输出值


示例:

IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, 0 WIFI_IOT_IO_FUNC_GPIO_10_GPIO);//IO10设置为GPIO

GpioSetDir(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_DIR_OUT);//IO10设置为输出

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、按键响应,使用的GPIO的输入中断功能,并且识别了按键按下(下降沿)和按键抬起(上升沿)

对中断不熟悉的朋友,请参考唐佐林老师的教程:​​实现按键“按下事件”和“释放事件”的通用框架(V0.0.1)​​ 此处仅将用到几个函数列出

    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);//IO复用为GPIO功能

    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_IN);//设置为输入

    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);//注册中断服务函数,边沿触发,下降沿触发,按键按下后,会调用中断服务函数 OnButtonPressed_isr

3、蜂鸣器,主要使用了PWM功能,也就是脉冲宽度调制,通过调节占空比,可以控制输出的电平,使得蜂鸣器发出不同的响声,PWM还用于电机的控制。

注意,为了能使用PWM功能,需要使能PWM功能:将vendor\hisi\hi3861\hi3861\build\config\usr_config.mk文件中的CONFIG_PWM_SUPPORT行:# CONFIG_PWM_SUPPORT is not set修改为CONFIG_PWM_SUPPORT=y , 否则会编译失败

    IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT);//IO复用为PWM功能

    GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT);//设置为输出

    PwmInit(WIFI_IOT_PWM_PORT_PWM0);//初始化PWM

    PwmStart(WIFI_IOT_PWM_PORT_PWM0, 5 * 1000, 40 * 1000);//启动PWM功能,此处不做详细解释,会单独开一个帖子讲解参数的含义

    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

链接:

实现功能:

使用红绿灯扩展板,按一下按键,点亮一个灯,按键按下时,蜂鸣器发声,按键抬起,蜂鸣器停止

主要功能点:

1. GPIO 输出 -> LED灯

2. GPIO 输入 中断 -> 按键

3. PWM功能 -> 蜂鸣器

*/


//红黄绿灯扩展板上,对应的GPIO10,11,12,高电平点灯,低电平灭灯

static WifiIotIoName LightGPIO[] =

{

    WIFI_IOT_IO_NAME_GPIO_10,//红灯

    WIFI_IOT_IO_NAME_GPIO_12,//黄灯

    WIFI_IOT_IO_NAME_GPIO_11//绿灯

};



//红黄绿灯扩展板上的按键

static int volatile BtnPressed = 0;//1表示按下,0表示抬起

static int volatile BtnPressed_idx = 0;//

static void OnButtonPressed_isr(char* arg);//按键按下中断处理函数

static void OnButtonReleased_isr(char* arg);//按键抬起中断处理函数


/*此处借鉴唐佐林老师的代码

有两个中断服务程序是因为在鸿蒙框架中,IO中断只能注册为上升沿触发或者下降沿触发,不能注册为任意边沿触发

我们为了识别按键按下和抬起,在按键按下的中断服务程序中,注册上升沿中断服务程序,以检测按键抬起

在按键抬起的中断服务程序中,注册下降沿中断服务程序,以检测按键按下,如此就可以实现及检测按键的抬起和按下

*/

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.任务处理函数

static void* HelloWorld_Task(const char* arg)

{

    int i = 0;

    (void)arg;

    printf("[HelloWorld] HelloWorld_Task()\n");


    GpioInit();//使用GPIO,都需要调用该接口


    //红黄绿灯扩展板上,对应的LED GPIO10,11,12初始化

    printf("LED GPIO init...\r\n");

    for(i=0; i<3; i++)

    {

        //复用引脚为 GPIO

        IoSetFunc(LightGPIO[i], 0);

        //设置为输出

        GpioSetDir(LightGPIO[i], WIFI_IOT_GPIO_DIR_OUT);

    }


    //红黄绿灯扩展板上,对应的按键 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);//设置为输入

    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);


    //红黄绿灯扩展板上,对应的蜂鸣器 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);//设置为输出

    PwmInit(WIFI_IOT_PWM_PORT_PWM0);//初始化PWM


    while(1)

    {

        //logic code for task


        //按一次按键,顺序点亮一个灯      

        int j = 0;

        for(j = 0; j < 3; j++)

        {

            if(BtnPressed_idx == j)

            {

                GpioSetOutputVal(LightGPIO[j],WIFI_IOT_GPIO_VALUE1);//高电平,点亮灯

            }

            else

            {

                 GpioSetOutputVal(LightGPIO[j],WIFI_IOT_GPIO_VALUE0);//关闭灯

            }

        }


#if 0

        //流水灯点亮

        for(j = 0; j< 3; j++)

        {

             GpioSetOutputVal(LightGPIO[j],WIFI_IOT_GPIO_VALUE0);//关闭所有灯

        }


        i = (i + 1) % 3;

        GpioSetOutputVal(LightGPIO[i], WIFI_IOT_GPIO_VALUE1);//高电平,点亮灯

        sleep(1);//延时1秒

#endif


        //按键触发的处理

        if(BtnPressed)

        {

            PwmStart(WIFI_IOT_PWM_PORT_PWM0, 5 * 1000, 40 * 1000);//按键按下,蜂鸣器发声

        }else{

            PwmStop(WIFI_IOT_PWM_PORT_PWM0);//按键抬起,蜂鸣器停止

        }


        //usleep(500000);

        usleep(100000);

    }


    return NULL;

}


//2.任务入口函数

static void HelloWorld_Entry(void)

{

    osThreadAttr_t attr = {0};


    printf("[HelloWorld] HelloWorld_Entry()\n");


    = "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;//优先级


    if (osThreadNew((osThreadFunc_t)HelloWorld_Task, NULL, &attr) == NULL)

    {

        printf("[HelloWorld] Falied to create LedTask!\n");

    }

}


//3.注册模块

SYS_RUN(HelloWorld_Entry);


5.业务代码的编译脚本 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和华为官方合作共建的鸿蒙技术社区​

​https://harmonyos.51cto.com/#bkwz​


WiFi IoT智能家居套件 - LED灯、按键、蜂鸣器的实现_Hi3861_02