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

news2024/9/17 8:23:36

一、程序简介

该程序是基于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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/988832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

十分钟,了解Kafka的Sender线程

〇、前言 在上两篇文章《连Producer端的主线程模块运行原理都不清楚,就敢说自己精通Kafka》和《一文了解Kafka的消息收集器RecordAccumulate》中,我们介绍了Main Thread和RecordAccumulate的工作原理,那么在本篇文章中,我们继续介…

Python之Xlwings操作excel

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、xlwings简介二、安装与使用1.安装2.使用3.xlwings结构说明 二、xlwings对App常见的操作App基础操作工作簿的基础操作工作表的基础操作工作表其他操作 读取单元格…

Android 自定义View之圆形进度条

很多场景下都用到这种进度条,有的还带动画效果, 今天我也来写一个。 写之前先拆解下它的组成: 底层圆形上层弧形中间文字 那我们要做的就是: 绘制底层圆形;在同位置绘制上层弧形,但颜色不同&#xff…

【0908练习】shell脚本使用expr截取网址

题目: 终端输入网址,如:www.hqyj.com, 要求:截取网址每个部分,并放入数组中,不能使用cut,使用expr解决 #!/bin/bash read -p "请输入一个网址" net lenexpr length $net …

协程 VS 线程,Kotlin技术精讲

协程(coroutines)是一种并发设计模式,您可以在Android 平台上使用它来简化异步执行的代码。协程是在版本 1.3 中添加到 Kotlin 的,它基于来自其他语言的既定概念。 在 Android 上,协程有助于管理长时间运行的任务,如果管理不当&a…

无脑014——linux系统,制作coco(json)格式数据集,使用mmdetection训练自己的数据集

电脑,linux,RTX 3090 cuda 11.2 1.制作coco(json)格式数据集 这里我们使用的标注软件是:labelimg 选择voc格式进行标注,标注之后使用以下代码,把voc格式转换成coco格式,注意最后的路…

机房运维管理软件不知道用哪个好?

云顷网络还原系统V7.0是一款专业的机房运维管理产品,基于局域网络环境,针对中高端机房中电脑运维管理需求所设计开发的。网络还原系统软件通过全面的规划和设计,遵从机房部署、使用到维护阶段化使用方式,通过极速网络同传/增量对拷…

TypeScript的函数

ts与js函数区别 tsjs传参需要规定类型无类型箭头函数箭头函数ES6函数类型无函数类型必填和可选参数所有参数都是可选的能设置默认参数能设置默认参数剩余参数剩余参数 函数重载 函数重载 注释 TypeScript 允许您指定函数的输入和输出值的类型。 输入值注释 // 传参必须为字…

如何理解图神经网络的傅里叶变换和图卷积

图神经网络(GNN)代表了一类强大的深度神经网络架构。在一个日益互联的世界里,因为信息的联通性,大部分的信息可以被建模为图。例如,化合物中的原子是节点,它们之间的键是边。图神经网络的美妙之处在于它们能…

【设计模式】二、UML 类图概述

文章目录 常见含义含义依赖关系(Dependence)泛化关系(Generalization)实现关系(Implementation)关联关系(Association)聚合关系(Aggregation)组合关系&#x…

【赠书活动】AI 时代,程序员无需焦虑

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

9.8day59

503. 下一个更大元素 II - 力扣(LeetCode) 知识点:单调栈 42. 接雨水 - 力扣(LeetCode)

初学python爬虫学习笔记——爬取网页中小说标题

初学python爬虫学习笔记——爬取网页中小说标题 一、要爬取的网站小说如下图 二、打开网页的“检查”,查看html页面 发现每个标题是列表下的一个个超链接,从183.html到869.html 可以使用for循环依次得到: x range(183,600) for i in x:pr…

NoSQL数据库入门

一、NoSQL数据库概述 NoSQL 是一种不同于关系数据库的数据库管理系统设计方式,是对非关系型数据库的统称,它所采用的数据模型并非传统关系数据库的关系模型,而是类似键/值、列族、文档等非关系模型。NoSQL 数据库没有固定的表结构&#xff0c…

W25Q16_Flash手册总结

文章目录 前言一、概述&特点1、概述W25Q16BV1、特点2、引脚说明3、内部结构示意图4、操作指令5、操作示例时序图1、写入启用指令:Write Enable(06h)2、读取状态寄存器指令:Read Status Register-1(05h)…

【PowerShell代码】清除掉文件中的非英文字母

如果你尝试从网上下载一些带有非ASCII的文件时候,你在这台机器上会发现没有问题,但是将文件传递到其他的地方或者其他电脑你会发现存在比较大的问题,我如何才能将这些文件中的非英文字母去掉呢? 如何才能将文件中的这些非英文字母…

无涯教程-JavaScript - IMLOG2函数

描述 IMLOG2函数以x yi或x yj文本格式返回复数的以2为底的对数。可以从自然对数计算复数的以2为底的对数,如下所示- $$\log_2(x yi)(log_2e)\ln(x yi)$$ 语法 IMLOG2 (inumber)争论 Argument描述Required/OptionalInumberA complex number for which you want the bas…

为什么零基础选择语言首选python

在众多编程语言中,似乎已经没有什么能够阻挡Python的步伐。本月Python又是第一名,市场份额达到了13.42%,在2023年,Python已经连续7个月蝉联榜首,遥遥领先于其他对手。 每个月榜单发布后,都有小伙伴会好奇&…

Blender中的高级边缘控制和纹理映射

推荐:使用 NSDT场景编辑器 快速搭建3D应用场景 步骤 1 首先,您需要创建一组无阴影材质,每种材质具有不同的颜色,确保您有足够的材质来覆盖模型,而不会有相同的颜色相互重叠。然后,切换到“着色”&#xff…

即拼七人拼团系统开发模式是怎么盈利赚钱的?

即拼七人拼团是市场上最近比较火爆的一款商业模式,它结合了二二复制和拼团两种模式玩法,不仅能让消费者从中获利,还能让平台快速获流裂变,对平台起盘初期和发展中期具有很强的推广能力。那么这个模式是怎么盈利赚钱的呢&#xff1…