OpenHarmony智能开发套件[驱动开发篇(上)

系统 OpenHarmony
​ 驱动开发是指为操作系统或硬件设备编写软件驱动程序的过程。驱动程序是一种特殊的软件,它与操作系统或硬件设备进行交互,以使它们能够有效地通信和协同工作。

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

前言

下面我们继续跟着架构图去学习另一个板块——驱动,本片将介绍。

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

驱动开发简介

什么是驱动开发呢,回想我们之前介绍内核的时候,内核的作用是帮助我们完成对硬件的操控的,我们已经通过KAL内核抽象层提供的规范接口,实现了对内核的一些基本控制,但是并没有涉及到硬件设备,那么驱动开发的含意就呼之欲出了。

驱动开发是指为操作系统或硬件设备编写软件驱动程序的过程。驱动程序是一种特殊的软件,它与操作系统或硬件设备进行交互,以使它们能够有效地通信和协同工作。通俗点讲就是IO控制硬件设备。IO流在读写文件时大家都会用到,我们的驱动也像IO流,只不过操作的对象不在是虚拟的文件,而是你手中的开发板,实实在在摸得到的硬件设备。

硬件设备介绍

硬件总览

笔者使用的是智能家居开发套件:Hi3861

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

硬件详细介绍

底板

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

核心板

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

oled屏幕

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

交通灯

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

RGB灯板

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

环境检测板

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

NFC

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

驱动开发

GPIO

GPIO可以理解为数字I/O,是一种电平控制,由0和1表示,0表示低电平,1表示高电平。Hi3861芯片一共有15各个GPIO引脚,芯片内部集成了GPIO模块,方便我们去使用。

Hi3861 GPIO 引脚分布

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

IoT接口

OprnHarmony提供了操作物联网各种外接设备的一组API,方便我们去控制与外接设备的交互。一共有三类IoT接口。

  • HAL硬件抽象层接口。
  • HDF硬件驱动框架接口。
  • 海思SDK接口。

其中HDF接口是主推接口,在上面的架构图中也能看到,海思的SDK是原厂商提供的底层接口。

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

GPIO控制流程

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

IoT编程工作环境补充

在源码目录生成的 .vscode的目录下的 c_cpp_properties.json 文件中做出如下添加。

[注:目录可能因为源码版本不同而不一致,这里可以手动搜索文件来确定库的存放位置]。

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

打开 usr_config.mk 文件 修改如下配置,防止后续的操作中出现编译错误,笔者报错时,也是在这卡了很久。这个配置项默认是关闭的,就会导致某些库中的方法无法被识别,编译就会出问题,主要是pwm模块的使用,这里提前说一下。

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

GPIO-API

  1. GPIO初始化。
unsigned int IoTGpioInit(unsigned int id);

参数解释:

  • id: GPIO的引脚编号。

返回值:

  • IOT_SUCCESS:如果GPIO设备成功初始化,则返回该值。
  • IOT_FAILURE:如果GPIO设备初始化失败,则返回该值。
  1. GPIO参数设置。
unsigned int IoTGpioSetDir(unsigned int id, IotGpioDir dir);

参数解释:

  • id: GPIO的引脚编号。
  • dir: 设置GPIO为输入/输出。

返回值:

  • IOT_SUCCESS:如果GPIO设备成功设置,则返回该值。
  • IOT_FAILURE:如果GPIO设备设置失败,则返回该值。

其中,IotGPIODir 的定义如下的枚举类型:

typedef enum {
    /** Input */
    IOT_GPIO_DIR_IN = 0,
    /** Output */
    IOT_GPIO_DIR_OUT
} IotGpioDir;
  1. 设置GPIO输出状态。
unsigned int IoTGpioSetOutputVal(unsigned int id, IotGpioValue val);

参数解释:

  • id: GPIO的引脚编号。
  • val: 输出的电平值。

返回值:

  • IOT_SUCCESS:如果GPIO设备成功设置,则返回该值。
  • IOT_FAILURE:如果GPIO设备设置失败,则返回该值。

其中,IotGPIOValue的定义如下的枚举类型:

typedef enum {
    /** Low GPIO level */
    IOT_GPIO_VALUE0 = 0,
    /** High GPIO level */
    IOT_GPIO_VALUE1
} IotGpioValue;
  1. 解除GPIO。
unsigned int IoTGpioDeinit(unsigned int id);

参数解释:

  • id: GPIO的引脚编号

返回值:

  • IOT_SUCCESS:如果GPIO设备成功解除,则返回该值。
  • IOT_FAILURE:如果GPIO设备解除失败,则返回该值。
  1. 获取GPIO引脚状态。
unsigned int IoTGpioGetOutputVal(unsigned int id, IotGpioValue *val);

参数解释:

  • id: GPIO的引脚编号
  • *val: 获取输出的电平值的指针

返回值:

  • IOT_SUCCESS:如果GPIO设备成功获取,则返回该值。
  • IOT_FAILURE:如果GPIO设备获取失败,则返回该值。

这个API和设置GPIO引脚的API很像,只不过val属性变成了个指针,也就通过这个指针帮我们获取到GPIO的引脚状态的。

  1. 引脚中断函数注册。
unsigned int IoTGpioRegisterIsrFunc(unsigned int id, IotGpioIntType intType, IotGpioIntPolarity intPolarity,
                                    GpioIsrCallbackFunc func, char *arg);

参数解释:

  • id:GPIO引脚的编号。
  • intType:中断类型。
  • intPolarity:中断极性。
  • func:中断回调函数。
  • arg:中断回调函数中使用的参数的指针。

返回值:

  • IOT_SUCCESS:如果成功启用GPIO引脚的中断功能,则返回该值。
  • IOT_FAILURE:如果启用GPIO引脚的中断功能失败,则返回该值。

其中 IotGpioIntType 定义如下的枚举类型。

typedef enum {
    /** Level-sensitive interrupt */
    IOT_INT_TYPE_LEVEL = 0,
    /** Edge-sensitive interrupt */
    IOT_INT_TYPE_EDGE
} IotGpioIntType;

IOT_INT_TYPE_LEVEL:表示电平触发的中断类型。这种中断类型基于GPIO引脚的电平状态进行触发,即当引脚的电平为特定的电平(例如高电平或低电平)时触发中断。

IOT_INT_TYPE_EDGE:表示边沿触发的中断类型。这种中断类型基于GPIO引脚的电平变化进行触发,即当引脚的电平从一个状态变化到另一个状态(例如从低电平到高电平或从高电平到低电平)时触发中断。

IotGpioIntPolarity 定义如下的枚举类型。

typedef enum {
    /** Interrupt at a low level or falling edge */
    IOT_GPIO_EDGE_FALL_LEVEL_LOW = 0,
    /** Interrupt at a high level or rising edge */
    IOT_GPIO_EDGE_RISE_LEVEL_HIGH
} IotGpioIntPolarity;

IOT_GPIO_EDGE_FALL_LEVEL_LOW:表示在低电平或下降沿触发中断。这意味着当GPIO引脚的电平为低电平时或引脚的电平从高电平变为低电平时,触发中断。

IOT_GPIO_EDGE_RISE_LEVEL_HIGH:表示在高电平或上升沿触发中断。这意味着当GPIO引脚的电平为高电平时或引脚的电平从低电平变为高电平时,触发中断。

当我们向外界设备进行输入流操作时,需要处理一些业务逻辑,在中断函数中完成,后面会后案例让大家体会。

  1. 引脚中断函数解除。
unsigned int IoTGpioUnregisterIsrFunc(unsigned int id);

参数解释:

  • id:GPIO引脚的编号。

返回值:

  • IOT_SUCCESS:如果成功解除GPIO引脚的中断功能,则返回该值。
  • IOT_FAILURE:如果解除GPIO引脚的中断功能失败,则返回该值。

解除类型的API都比较简单。

  1. 设置引脚的功能复用。
hi_u32 hi_io_set_func(hi_io_name id, hi_u8 val);

参数解释:

  • id:硬件管脚的枚举类型 hi_io_name,表示要设置复用功能的IO索引。
  • val:复用功能的枚举类型 hi_u8,表示要设置的复用功能。根据待设置的硬件管脚,从给定的枚举值中选择相应的功能。

返回值:

  • 0:成功设置复用功能。
  • HI_ERR_GPIO_INVALID_PARAMETER:设置复用功能失败,输入参数无效或不支持的功能。

其中 hi_io_name 的美剧类型定义如下:

typedef enum {
    HI_IO_NAME_GPIO_0,     /**< GPIO0 */
    HI_IO_NAME_GPIO_1,     /**< GPIO1 */
    HI_IO_NAME_GPIO_2,     /**< GPIO2 */
    HI_IO_NAME_GPIO_3,     /**< GPIO3 */
    HI_IO_NAME_GPIO_4,     /**< GPIO4 */
    HI_IO_NAME_GPIO_5,     /**< GPIO5 */
    HI_IO_NAME_GPIO_6,     /**< GPIO6 */
    HI_IO_NAME_GPIO_7,     /**< GPIO7 */
    HI_IO_NAME_GPIO_8,     /**< GPIO8 */
    HI_IO_NAME_GPIO_9,     /**< GPIO9 */
    HI_IO_NAME_GPIO_10,    /**< GPIO10 */
    HI_IO_NAME_GPIO_11,    /**< GPIO11 */
    HI_IO_NAME_GPIO_12,    /**< GPIO12 */
    HI_IO_NAME_GPIO_13,    /**< GPIO13 */
    HI_IO_NAME_GPIO_14,    /**< GPIO14 */
    HI_IO_NAME_SFC_CSN,    /**< SFC_CSN */
    HI_IO_NAME_SFC_IO1,    /**< SFC_IO1 */
    HI_IO_NAME_SFC_IO2,    /**< SFC_IO2 */
    HI_IO_NAME_SFC_IO0,    /**< SFC_IO0 */
    HI_IO_NAME_SFC_CLK,    /**< SFC_CLK */
    HI_IO_NAME_SFC_IO3,    /**< SFC_IO3 */
    HI_IO_NAME_MAX,
} hi_io_name;

hi_u8 的定义如下:

typedef unsigned char           hi_u8;

Hi3861的引脚数量少,很多功能都是被集成在同一个引脚上的,因此需要我们去选择引脚配置。

  1. 启用某个IO引脚的上下拉功能。
hi_u32 hi_io_set_pull(hi_io_name id, hi_io_pull val);

参数解释:

  • id:硬件管脚的枚举类型 hi_io_name,表示要设置上下拉功能的IO引脚的索引。
  • val:上下拉状态的枚举类型 hi_io_pull,表示要设置的上下拉状态。

返回值:

  • 0:成功设置上下拉功能。
  • HI_ERR_GPIO_INVALID_PARAMETER:设置上下拉功能失败,输入参数无效或不支持的功能。

其中 hi_io_pull 的定义如下的枚举类型:

typedef enum {
    HI_IO_PULL_NONE,    /**< Disabled.CNcomment:无拉CNend */
    HI_IO_PULL_UP,      /**< Pull-up enabled.CNcomment:上拉CNend */
    HI_IO_PULL_DOWN,    /**< Pull-down enabled.CNcomment:下拉CNend */
    HI_IO_PULL_MAX,     /**< Invalid.CNcomment:无效值CNend */
} hi_io_pull;

上下拉功能可用于确定GPIO引脚的输入电平状态。例如,通过启用上拉功能,可以将引脚的输入电平拉高,使其在未连接外部设备时保持为高电平状态。这样,在检测外部设备连接时,可以通过读取引脚的输入电平状态来确定设备的连接状态。

GPIO控制LED案例

能够使用我们的user按键控制可编程led灯的熄灭与点亮。

思路:通过读取按键的电平状态,触发中断回调函数,修改led的电平。

  1. 新建样例目录。
    applications/sample/wifi-iot/app/led_gpio_demo
  2. 新建源文件和gn文件。
    applications/sample/wifi-iot/app/led_gpio_demo/ledGpio.c
    applications/sample/wifi-iot/app/led_gpio_demo/BUILD.gn
  3. 编写源文件,ledGpio.c [笔者加了详细的注释,就直接上代码了]。
// C语言标准库
#include <stdio.h>
// 初始化库
#include "ohos_init.h"
// 内核编程标准接口
#include "cmsis_os2.h"
// IoT接口 GPIO
#include "iot_gpio.h"
// 海思SDK IO
#include "hi_io.h"

// 定义引脚的编号
#define LED_GPIO 9
#define BUTTON_GPIO 5

// 定义ledPin(电平)低电平led点亮,高电平led熄灭,高低电平的定义在之前的api中已经介绍过了,是一个枚举类型。
static IotGpioValue ledPin = IOT_GPIO_VALUE0;

//GPIO5的中断处理函数,当我们点击user按钮时,系统的内核就会暂停手头的工作来执行我们这里的中断函数。
static void ButtonPressed(char* atgs){
    // 我们的业务逻辑是让led熄灭点亮熄灭点亮,因此只需要修改上方我们定义的ledPin值即可
    if(ledPin == IOT_GPIO_VALUE0){
        ledPin = IOT_GPIO_VALUE1;
    } else {
        ledPin = IOT_GPIO_VALUE0;
    }
    /**
     * 当然看过源码的你也可以简写成:
     * ledPin = !ledPin;
    */
}

// 主函数
static void GpioInitMain(void){
    // 在主函数中我们通常完成一些GPIO的注册和设置,主要就是用一些介绍给大家的API即可

    // GPIO初始化 ——> IoTGpioInit 接口
    IoTGpioInit(LED_GPIO);
    IoTGpioInit(BUTTON_GPIO);

    // 设置引脚的功能,因为hi3861的引脚数少,一个引脚上集成了很多功能,需要我们手动设置,选择其中的一项功能
    hi_io_set_func(LED_GPIO, HI_IO_FUNC_GPIO_9_GPIO);
    hi_io_set_func(BUTTON_GPIO, HI_IO_FUNC_GPIO_5_GPIO);

    // 设置GPIO的输入输出模式 led为输出模式,button为输入模式
    IoTGpioSetDir(LED_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(BUTTON_GPIO, IOT_GPIO_DIR_IN);

    // 设置GPIO5为上拉模式
    hi_io_set_pull(BUTTON_GPIO, HI_IO_PULL_UP);

    // 注册中断函数
    IoTGpioRegisterIsrFunc(BUTTON_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW, ButtonPressed, NULL);

    // 循环设置led的电平
    while(1){
        IoTGpioSetOutputVal(LED_GPIO, ledPin);
        osDelay(10);
    }
}

// 测试入口
static void GpioTest(void){
    // 创建线程,大家还记得怎么创建的吗
    osThreadAttr_t attr = {"GpioInitMain", 0, NULL, 0, NULL, 1024, osPriorityNormal, 0, 0};
    osThreadNew((osThreadFunc_t)GpioInitMain, NULL, &attr);
}

APP_FEATURE_INIT(GpioTest);
  1. 编写BIULD.gn文件。
static_library("led_gpio_demo"){
    sources = [
        "ledGpio.c"
    ]
    include_dirs = [
        "//commonlibrary/utils_lite/include/",
        "//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
        "//base/iothardware/peripheral/interfaces/inner_api",
        "//device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
    ]
}
  1. 编写app目录下的BUILD.gn文件。

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

  1. 编译,烧录。
  2. 重启开发板,点击user按钮,观察可编程led的状态。

PWM

除了GPIO外,我们还可以通过PWM进行外部设备的控制,PWM是一种脉冲调制技术,用于控制数字系统中的模拟信号。通过改变信号的占空比,PWM可以模拟出不同的电压或电流值。在PWM信号中,周期固定,但高电平和低电平的持续时间可以不同。例如,一个50%的占空比意味着高电平和低电平各占一个周期的一半时间。当占空比增加时,高电平的持续时间增加,低电平的持续时间减少,平均输出功率也相应增加。因此,我们还可以用PWM控制led的亮度,因为占空比会直接影响输出的功率,功率会影响灯的亮度,算是中学物理了。广泛应用于电机控制、LED调光、音频生成等。

占空比与灯泡亮度

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

总结

PWM有两个重要的参数,第一个是输出频率,频率越高,则模拟的效果越好;第二个是占空比,占空比就是改变输出模拟效果的电压大小,占空比越大则模拟出的电压越大。

PWM-API

很多基础的IoT接口都已经在GPIO-API上讲到了,这里的介绍就相对简单一点。

  1. 初始化PWM。
unsigned int IoTPwmInit(unsigned int port);

通过参数port,指定PWM的端口号。

  1. 启用PWM。
unsigned int IoTPwmStart(unsigned int port, unsigned short duty, unsigned int freq);

参数解释:

  • port:PWM的端口号
  • duty:PWM输出的占空比
  • freq:PWM输出的频率
  1. 停止PWM。
unsigned int IoTPwmStop(unsigned int port);

通过参数port,停止PWM的输出。

结合GPIO和PWM我们已经可以去控制一些板子了,就不单独设计PWM的案例了。

交通灯板的控制

交通灯板上一共有3个小板块,红绿灯,蜂鸣器,按钮。下面逐个为大家讲解如何使用对应的API去控制他们。(涉及 GPIO控制设备和中断函数处理 )

按钮控制蜂鸣器

按一下按钮,蜂鸣器鸣叫3秒。

  1. 新建样例目录。
    applications/sample/wifi-iot/app/pwm_out_demo
  2. 新建源文件和gn文件。
    applications/sample/wifi-iot/app/pwm_out_demo/pwm.c
    applications/sample/wifi-iot/app/pwm_out_demo/BUILD.gn
  3. 编写源文件,pwm.c。
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_io.h"
#include "iot_gpio.h"
// pwm接口
#include "iot_pwm.h"
#include "hi_pwm.h"

#define BUTTON_GPIO 8
#define BEE_GPIO 9

static int flag = 0;

// GPIO8中断函数
static void ButtonPressed(char* atgs){
    // 业务逻辑是让蜂鸣器响三秒
    if(flag == 0){
        flag = 1;
    }
}

// 主线程函数
static void PwmInitMain(void){
    // 初始化GPIO模块
    IoTGpioInit(BUTTON_GPIO);
    IoTGpioInit(BEE_GPIO);

    // 设置引脚功能
    hi_io_set_func(BEE_GPIO, HI_IO_FUNC_GPIO_9_PWM0_OUT);
    hi_io_set_func(BUTTON_GPIO, HI_IO_FUNC_GPIO_8_GPIO);

    // 设置GPIO输出模式
    IoTGpioSetDir(BEE_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(BUTTON_GPIO, IOT_GPIO_DIR_IN);

    // 设置引脚上拉
    hi_io_set_pull(BUTTON_GPIO, HI_IO_PULL_UP);

    // 注册中断函数
    IoTGpioRegisterIsrFunc(BUTTON_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW, ButtonPressed, NULL);

    // 循环监听flag,当按钮被按下时,flag会置为1,蜂鸣器工作3秒
    while(1){

        if(flag){
            // 初始化PWM模块
            IoTPwmInit(HI_PWM_PORT_PWM0);

            // 设置信号输出, 端口,占空比,频率
            IoTPwmStart(HI_PWM_PORT_PWM0, 50, 4000);

            // 鸣3秒
            osDelay(300);

            // 停止信号输出
            IoTPwmStop(HI_PWM_PORT_PWM0);
            flag = 0;
        }
        osDelay(100);
    }
}

// 测试入口
static void PwmTest(void){
    osThreadAttr_t attr = {"GpioInitMain", 0, NULL, 0, NULL, 1024, osPriorityNormal, 0, 0};
    osThreadNew((osThreadFunc_t)PwmInitMain, NULL, &attr);
}

APP_FEATURE_INIT(PwmTest);
  1. 编写BIULD.gn文件。
static_library("pwm_out_demo"){
    sources = [
        "pwm.c"
    ]
    include_dirs = [
        "//commonlibrary/utils_lite/include/",
        "//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
        "//base/iothardware/peripheral/interfaces/inner_api",
        "//device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
    ]
}
  1. 编写app目录下的BUILD.gn文件。

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

  1. 编译,烧录。
  2. 重启开发板,点击s1按钮,可以听到蜂鸣器鸣叫。

按钮切换红绿灯

按一下按钮,红绿灯顺次切换。

  1. 新建样例目录。
    applications/sample/wifi-iot/app/traffic_demo
  2. 新建源文件和gn文件。
    applications/sample/wifi-iot/app/traffic_demo/traffic.c
    applications/sample/wifi-iot/app/traffic_demo/BUILD.gn
  3. 编写源文件,traffic.c。
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_io.h"
#include "iot_gpio.h"

#define BUTTON_GPIO 8
#define RED_GPIO 10
#define GREEN_GPIO 11
#define YELLOW_GPIO 12

// 每个灯的引脚编号
static int lights[3] = {RED_GPIO, GREEN_GPIO, YELLOW_GPIO};
// 每个灯的状态
static int lightsStauts[3] = {0, 0, 0};
// 灯的索引
static int lightsIndex = 0;

// 中断函数
static void ButtonPress(char *args){
    // 点击按钮,要能够切换红绿灯,修改灯的状态数组即可
    for(unsigned int i = 0; i < 3; i++){
        if(i == lightsIndex){
            lightsStauts[i] = 1;
        } else {
            lightsStauts[i] = 0;
        }
    }
    lightsIndex++;
    if(lightsIndex >= 3){
        lightsIndex = 0;
    }
}

// 主函数
static void TrafficInitMain(void){
    // GPIO初始化
    IoTGpioInit(BUTTON_GPIO);
    IoTGpioInit(RED_GPIO);
    IoTGpioInit(GREEN_GPIO);
    IoTGpioInit(YELLOW_GPIO);

    // GPIO功能设置
    hi_io_set_func(BUTTON_GPIO, HI_IO_FUNC_GPIO_8_GPIO);
    hi_io_set_func(RED_GPIO, HI_IO_FUNC_GPIO_10_GPIO);
    hi_io_set_func(GREEN_GPIO, HI_IO_FUNC_GPIO_11_GPIO);
    hi_io_set_func(YELLOW_GPIO, HI_IO_FUNC_GPIO_12_GPIO);
    
    // PGPIO输入输出设置
    IoTGpioSetDir(BUTTON_GPIO, IOT_GPIO_DIR_IN);
    IoTGpioSetDir(RED_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(GREEN_GPIO, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(YELLOW_GPIO, IOT_GPIO_DIR_OUT);

    // 引脚上拉
    hi_io_set_pull(BUTTON_GPIO, HI_IO_PULL_UP);

    // 中断回调函数注册
    IoTGpioRegisterIsrFunc(BUTTON_GPIO, IOT_INT_TYPE_EDGE, IOT_GPIO_EDGE_FALL_LEVEL_LOW, ButtonPress, NULL);
   
   while(1){
        // 设置输出电平,即可控制灯的点亮熄灭,其实和之前控制led一样,只不过这次一下控制3个,用数组而已
        for(unsigned int i = 0; i < 3; i++){
            IoTGpioSetOutputVal(lights[i], lightsStauts[i]);
        }
        osDelay(100);
   }
}

// 测试入口
static void TrafficTest(void){
    osThreadAttr_t attr = {"TrafficInitMain", 0, NULL, 0, NULL, 1024, osPriorityNormal, 0, 0};
    osThreadNew((osThreadFunc_t)TrafficInitMain, NULL, &attr);
}

APP_FEATURE_INIT(TrafficTest);
  1. 编写BIULD.gn文件。
static_library("traffic_demo"){
    sources = [
        "traffic.c"
    ]
    include_dirs = [
        "//commonlibrary/utils_lite/include/",
        "//device/soc/hisilicon/hi3861v100/hi3861_adapter/kal/cmsis",
        "//base/iothardware/peripheral/interfaces/inner_api",
        "//device/soc/hisilicon/hi3861v100/sdk_liteos/include/"
    ]
}
  1. 编写app目录下的BUILD.gn文件。

OpenHarmony智能开发套件[驱动开发篇·上]-开源基础软件社区

  1. 编译,烧录。
  2. 重启开发板,点击s1按钮,可以看到红绿灯正在切换。大家也可以修改代码,实现有红黄绿,绿黄红那样变化。

至此,交通灯板的三个小模块就给大家介绍到这里,这些都是基本操作,仅在如何控制设备,与设备交互,大家可以根据自己的想法,创新一些业务逻辑,使用该功能板完成相应的场景业务。

结束语

本片主要介绍了GPIO,PWM控制驱动的方案,并在交通灯板上进行了实际演示,以及三色灯的使用。后续的开发板硬件设备会在OpenHarmony智能开发套件[驱动开发篇·下]中详细讲解,包括人体红外感应,光敏电阻,RGB灯效,温湿度传感器,oled屏幕的点亮。
[本来每一个案例后面都做了实际效果演示视频的,但是视频好像上传不了,那暂时就没有视频演示了。]

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

责任编辑:jianghua 来源: 51CTO 开源基础软件社区
相关推荐

2023-05-30 14:58:05

智能开发鸿蒙

2023-05-15 15:27:20

鸿蒙智能开发套件

2023-05-12 14:52:11

鸿蒙操作系统

2023-05-17 15:07:42

智能开发鸿蒙

2021-12-06 15:05:41

鸿蒙HarmonyOS应用

2021-11-12 15:58:11

鸿蒙HarmonyOS应用

2022-03-01 15:54:38

智能开发鸿蒙创造性TV

2009-02-27 09:07:09

Linux开发套件100美元

2022-04-01 15:26:06

Harmony操作系统鸿蒙

2010-01-22 09:40:36

Kindle平台亚马逊

2022-03-03 19:21:50

Harmony鸿蒙操作系统

2023-10-27 06:33:14

鸿蒙开发套件

2011-10-25 09:48:07

NFC诺基亚Symbian

2013-08-07 09:45:35

Windows phoWP应用开发套件Stu

2020-10-30 17:57:11

鸿蒙HiSpark

2018-02-27 16:55:38

微软量子开发

2023-10-06 11:09:23

微软C#

2023-04-26 09:37:25

智驾开发

2022-05-30 15:38:02

开箱照片编译环境搭建

2021-01-26 14:27:21

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号