OpenHarmony:如何使用HDF驱动控制LED灯

一、程序简介

该程序是基于OpenHarmony标准系统编写的基础外设类:RGB LED。

目前已在凌蒙派-RK3568开发板跑通。详细资料请参考官网:https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk3568-openharmony/tree/master/samples/b02_hdf_rgb_led。

详细资料请参考OpenHarmony官网:

  • GPIO平台驱动开发
  • GPIO应用程序开发

二、硬件设计

RGB LED灯整体硬件电路如下图所示,硬件电路中包含了三个GPIO控制管脚控制RGB LED灯,低电平点亮LED灯,高电平熄灭LED灯。电路简单,这边不对此进行多余的说明。

三、程序解析

1、目录结构

复制代码
b02_hdf_rgb_led
├── config              # HDF资源配置文件目录
    ├── config.hcs      # 接口IO配置文件
    ├── device_info.hcs # 设备信息配置文件
├── drivers             # 内核HDF驱动程序目录
    ├── rgb_led_drv.c   # 内核HDF驱动程序
    ├── Makefile        # 内核HDF驱动编译脚本
├── figures             # MD文档图片
├── BUILD.gn            # GN文件
├── rgb_led.c           # 应用层控制程序

2、内核HDF驱动程序

(1)接口函数

  • 函数名:HdfRgbLedDriverInit.

  • 功能说明:HDF初始化注册,读取HDF资源配置文件,获取三色灯控制GPIO管脚。

    int32_t HdfRgbLedDriverInit(struct HdfDeviceObject *deviceObject)
    {
    if (deviceObject == NULL) {
    HDF_LOGE("g_rgbLedDriverEntry: %s failed", func);
    return HDF_ERR_INVALID_OBJECT;
    }
    struct DeviceResourceIface *CfgOps = NULL;
    CfgOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
    if (CfgOps == NULL || CfgOps->GetUint32 == NULL) {
    HDF_LOGE("%s: DeviceResourceGetIfaceInstance failed", func);
    return HDF_FAILURE;
    }
    if (CfgOps->GetUint32(deviceObject->property, "rgb_led_version", &g_rgbLedCfg.rgb_led_version, 0) != HDF_SUCCESS) {
    HDF_LOGE("%s: read rgb_led_version failed", func);
    return HDF_FAILURE;
    }
    if (CfgOps->GetUint32(deviceObject->property, "rgb_led_red", &g_rgbLedCfg.rgb_led_red, 0) != HDF_SUCCESS) {
    g_rgbLedCfg.rgb_led_version = 0;
    HDF_LOGE("%s: read rgb_led_red failed", func);
    return HDF_FAILURE;
    }
    if (CfgOps->GetUint32(deviceObject->property, "rgb_led_green", &g_rgbLedCfg.rgb_led_green, 0) != HDF_SUCCESS) {
    g_rgbLedCfg.rgb_led_version = 0;
    HDF_LOGE("%s: read rgb_led_green failed", func);
    return HDF_FAILURE;
    }
    if (CfgOps->GetUint32(deviceObject->property, "rgb_led_blue", &g_rgbLedCfg.rgb_led_blue, 0) != HDF_SUCCESS) {
    g_rgbLedCfg.rgb_led_version = 0;
    HDF_LOGE("%s: read rgb_led_blue failed", func);
    return HDF_FAILURE;
    }
    HDF_LOGI("g_rgbLedDriverEntry: %s success", func);
    return HDF_SUCCESS;
    }

  • 函数名:HdfRgbLedDriverRelease。

  • 功能说明:HDF去注册。

    void HdfRgbLedDriverRelease(struct HdfDeviceObject *deviceObject)
    {
    if (deviceObject == NULL) {
    HDF_LOGE("g_rgbLedDriverEntry: %s failed", func);
    return;
    }
    HDF_LOGI("g_rgbLedDriverEntry: %s success", func);
    return;
    }

  • 函数名:HdfRgbLedDriverBind。

  • 功能说明:HDF绑定解析函数。

    int32_t HdfRgbLedDriverBind(struct HdfDeviceObject *deviceObject)
    {
    if (deviceObject == NULL) {
    HDF_LOGE("g_rgbLedDriverEntry: %s failed", func);
    return HDF_ERR_INVALID_OBJECT;
    }
    static struct IDeviceIoService ledDriverServ = {
    .Dispatch = rgbLedDriverDispatch,
    };
    deviceObject->service = (struct IDeviceIoService *)(&ledDriverServ);
    HDF_LOGI("g_rgbLedDriverEntry: %s success NodeName[%s]", func,
    deviceObject->property->name);
    return HDF_SUCCESS;
    }

  • 函数名:rgbLedDriverDispatch。

  • 功能说明:解析函数,解析应用层下发的命令,执行命令对应操作,RGB_LED_WRITE控制三色灯亮灭。

    int32_t rgbLedDriverDispatch(struct HdfDeviceIoClient *client, int32_t cmdId,
    struct HdfSBuf *dataBuf, struct HdfSBuf *replyBuf)
    {
    int32_t result = HDF_FAILURE;
    int32_t rgbLedMode = 0;

    复制代码
      if (client == NULL || client->device == NULL) {
          HDF_LOGE("driver device is NULL");
          return HDF_ERR_INVALID_OBJECT;
      }
      if (g_rgbLedCfg.rgb_led_version != RGB_LED_VERSION) {
          HDF_LOGE("driver rgb_led_version not match");
          return HDF_FAILURE;
      }
      switch (cmdId) {
          case RGB_LED_WRITE:
              result = HdfSbufReadInt32(dataBuf, &rgbLedMode);
              if (result) {
                  HDF_LOGI("%s: mode:[0x%X][%s%s%s]", __func__, rgbLedMode,
                      (rgbLedMode&RGB_LED_RED_BIT)?"R":"-",
                      (rgbLedMode&RGB_LED_GREEN_BIT)?"G":"-",
                      (rgbLedMode&RGB_LED_BLUE_BIT)?"B":"-");
    
                  LedGpioCtrl(g_rgbLedCfg.rgb_led_red, (rgbLedMode&RGB_LED_RED_BIT)?LED_ON:LED_OFF);
                  LedGpioCtrl(g_rgbLedCfg.rgb_led_green, (rgbLedMode&RGB_LED_GREEN_BIT)?LED_ON:LED_OFF);
                  LedGpioCtrl(g_rgbLedCfg.rgb_led_blue, (rgbLedMode&RGB_LED_BLUE_BIT)?LED_ON:LED_OFF);
              }
              break;
          default:
              HDF_LOGE("%s: receiving unknown command", __func__);
              break;
      }
      return result;

    }

  • 函数名:LedGpioCtrl。

  • 功能说明:LED GPIO控制函数,低电平点亮LED,高电平熄灭LED。

    static int32_t LedGpioCtrl(uint16_t gpio, int32_t mode)
    {
    uint16_t level = GPIO_VAL_HIGH;

    复制代码
      if (HDF_SUCCESS != GpioSetDir(gpio, GPIO_DIR_OUT)) {
          HDF_LOGE("%s: GpioSetDir failed", __func__);
          return HDF_FAILURE;
      }
    
      if (mode == LED_ON) {
          level = GPIO_VAL_LOW;
      } else if (mode == LED_OFF) {
          level = GPIO_VAL_HIGH;
      }
    
      if (HDF_SUCCESS != GpioWrite(gpio, level)) {
          HDF_LOGE("%s: GpioWrite failed", __func__);
          return HDF_FAILURE;
      }
      return HDF_SUCCESS;

    }

3、应用层程序

(1)应用层代码分析

程序启动后获取命令行参数,如果命令行不带参数,RGB三色灯运行跑马灯;如果命令行带参数,根据传入的参数的低三位映射点亮对应的红灯、绿灯和蓝灯;通过HdfIoServiceBind绑定RGB三色灯HDF服务,获取HDF空间缓冲区,向缓冲区写入需要控制的RGB三色灯低三位数据,通过RGB_LED_WRITE命令下发到HDF驱动中,从而控制RGB三色灯亮灭。程序运行结束,回收HDF空间缓冲区和HDF服务。

复制代码
int main(int argc, char* argv[])
{
    int ret = HDF_SUCCESS;
    int32_t mode = -1;
    if (argc == ARGS_NUM) {
        mode = atoi(argv[1]);
        /*low-3bits*/
        mode &= 0x7;
        HILOG_INFO(LOG_APP, "[%s] main enter: mode[%s%s%s][0x%X]",
            LOG_TAG,
            (mode&RGB_LED_BLUE_BIT)?"B":"-",
            (mode&RGB_LED_GREEN_BIT)?"G":"-",
            (mode&RGB_LED_RED_BIT)?"R":"-",
            mode);
        printf("RGB mode[%s%s%s][0x%X]\n",
            (mode&RGB_LED_BLUE_BIT)?"B":"-",
            (mode&RGB_LED_GREEN_BIT)?"G":"-",
            (mode&RGB_LED_RED_BIT)?"R":"-",
            mode);
    } else {
        HILOG_INFO(LOG_APP, "[%s] main enter: auto test RGB LED", LOG_TAG);
        printf("auto test RGB LED\n");
    }

    struct HdfIoService *serv = HdfIoServiceBind(RGB_LED_SERVICE_NAME);
    if (serv == NULL) {
        HILOG_ERROR(LOG_APP, "get service %s failed", RGB_LED_SERVICE_NAME);
        return -1;
    }
    struct HdfSBuf *data = HdfSbufObtainDefaultSize();
    if (data == NULL) {
        HILOG_ERROR(LOG_APP, "obtain data failed");
        return -1;
    }

    if (mode == -1) {
        mode = 0x8;
        while (mode) {
            HdfSbufFlush(data);
            if (!HdfSbufWriteInt32(data, --mode)) {
                HILOG_ERROR(LOG_APP, "write data failed");
                return -1;
            }
            ret = serv->dispatcher->Dispatch(&serv->object, RGB_LED_WRITE, data, NULL);
            sleep(1);
        }
    } else {
        if (!HdfSbufWriteInt32(data, mode)) {
            HILOG_ERROR(LOG_APP, "write data failed");
            return -1;
        }
        ret = serv->dispatcher->Dispatch(&serv->object, RGB_LED_WRITE, data, NULL);
    }

    HdfSbufRecycle(data);
    HdfIoServiceRecycle(serv);
    HILOG_INFO(LOG_APP, "[%s] main exit.", LOG_TAG);

    return ret;
}

四、运行程序

系统启动后,命令行运行命令:

复制代码
rgb_led

五、运行结果

运行结果:

复制代码
# rgb_led
auto test RGB LED

# rgb_led 1
RGB mode[--R][0x1]
# rgb_led 2
RGB mode[-G-][0x2]
# rgb_led 3
RGB mode[-GR][0x3]
# rgb_led 4
RGB mode[B--][0x4]
# rgb_led 5
RGB mode[B-R][0x5]
# rgb_led 6
RGB mode[BG-][0x6]
# rgb_led 7
RGB mode[BGR][0x7]

最后,推荐一款应用开发神器

扯个嗓子!关于目前低代码在技术领域很活跃!

低代码是什么?一组数字技术工具平台,能基于图形化拖拽、参数化配置等更为高效的方式,实现快速构建、数据编排、连接生态、中台服务等。通过少量代码或不用代码实现数字化转型中的场景应用创新。它能缓解甚至解决庞大的市场需求与传统的开发生产力引发的供需关系矛盾问题,是数字化转型过程中降本增效趋势下的产物。

这边介绍一款好用的低代码平台------JNPF快速开发平台。近年在市场表现和产品竞争力方面表现较为突出,采用的是最新主流前后分离框架(SpringBoot+Mybatis-plus+Ant-Design+Vue3)。代码生成器依赖性低,灵活的扩展能力,可灵活实现二次开发。

以JNPF为代表的企业级低代码平台为了支撑更高技术要求的应用开发,从数据库建模、Web API构建到页面设计,与传统软件开发几乎没有差异,只是通过低代码可视化模式,减少了构建"增删改查"功能的重复劳动,还没有了解过低代码的伙伴可以尝试了解一下。

应用:https://www.jnpfsoft.com/?csdn

有了它,开发人员在开发过程中就可以轻松上手,充分利用传统开发模式下积累的经验。所以低代码平台对于程序员来说,有着很大帮助。

相关推荐
码小文8 小时前
Altium Designer 22使用笔记(4)---添加封装、ERC检查、PDF文档与BOM生成
笔记·嵌入式硬件·硬件工程·学习方法·硬件经验
粟米茶9 小时前
三极管三种基本放大电路:共射、共集、共基放大电路
硬件工程·硬件电路·三极管·三极管放大电路
日晨难再3 天前
Design Compiler:Milkyway库的创建与使用
硬件工程·数字ic
卓码软件测评3 天前
软件项目中标需要哪些东西?软件工程投标需要准备什么材料?
人工智能·功能测试·软件构建·开源软件·软件需求
爱思德学术3 天前
中国计算机学会(CCF)推荐学术会议-A(软件工程/系统软件/程序设计语言):FSE 2026
分布式·软件工程·软件构建
nuoxin1143 天前
CY7C68013A-56LTXC -USB2.0控制器芯片-富利威,国产CBM9002A-56ILG可替代
网络·人工智能·单片机·嵌入式硬件·硬件工程
xiaotianyun885 天前
LLC电源原边MOS管DS增加RC吸收对ZVS的影响分析
硬件工程·逆变器
Warren987 天前
Java Stream流的使用
java·开发语言·windows·spring boot·后端·python·硬件工程
Warren988 天前
Java Collections工具类
java·开发语言·笔记·python·学习·oracle·硬件工程
XINVRY-FPGA9 天前
XCZU4EV-1FBVB900E Xilinx FPGA AMD Zynq UltraScale+ MPSoC EV(Embedded Vision)
arm开发·嵌入式硬件·计算机视觉·fpga开发·硬件架构·硬件工程·fpga