4

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

 11 months ago
source link: https://www.51cto.com/article/755874.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

作者:stackor 2023-05-26 16:01:32
​ 驱动开发是指为操作系统或硬件设备编写软件驱动程序的过程。驱动程序是一种特殊的软件,它与操作系统或硬件设备进行交互,以使它们能够有效地通信和协同工作。
754d3f334e3ce1315c03973dd1de53dd520c15.png

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

51CTO 开源基础软件社区

https://ost.51cto.com

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

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

驱动开发简介

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

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

硬件设备介绍

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

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

硬件详细介绍

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

oled屏幕

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

RGB灯板

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

环境检测板

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

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的状态。

除了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 开源基础软件社区

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK