• 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、目录结构

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

    2、内核HDF驱动程序

    (1)接口函数
    • 函数名:HdfRgbLedDriverInit.
    • 功能说明:HDF初始化注册,读取HDF资源配置文件,获取三色灯控制GPIO管脚。
    1. int32_t HdfRgbLedDriverInit(struct HdfDeviceObject *deviceObject)
    2. {
    3. if (deviceObject == NULL) {
    4. HDF_LOGE("g_rgbLedDriverEntry: %s failed", __func__);
    5. return HDF_ERR_INVALID_OBJECT;
    6. }
    7. struct DeviceResourceIface *CfgOps = NULL;
    8. CfgOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
    9. if (CfgOps == NULL || CfgOps->GetUint32 == NULL) {
    10. HDF_LOGE("%s: DeviceResourceGetIfaceInstance failed", __func__);
    11. return HDF_FAILURE;
    12. }
    13. if (CfgOps->GetUint32(deviceObject->property, "rgb_led_version", &g_rgbLedCfg.rgb_led_version, 0) != HDF_SUCCESS) {
    14. HDF_LOGE("%s: read rgb_led_version failed", __func__);
    15. return HDF_FAILURE;
    16. }
    17. if (CfgOps->GetUint32(deviceObject->property, "rgb_led_red", &g_rgbLedCfg.rgb_led_red, 0) != HDF_SUCCESS) {
    18. g_rgbLedCfg.rgb_led_version = 0;
    19. HDF_LOGE("%s: read rgb_led_red failed", __func__);
    20. return HDF_FAILURE;
    21. }
    22. if (CfgOps->GetUint32(deviceObject->property, "rgb_led_green", &g_rgbLedCfg.rgb_led_green, 0) != HDF_SUCCESS) {
    23. g_rgbLedCfg.rgb_led_version = 0;
    24. HDF_LOGE("%s: read rgb_led_green failed", __func__);
    25. return HDF_FAILURE;
    26. }
    27. if (CfgOps->GetUint32(deviceObject->property, "rgb_led_blue", &g_rgbLedCfg.rgb_led_blue, 0) != HDF_SUCCESS) {
    28. g_rgbLedCfg.rgb_led_version = 0;
    29. HDF_LOGE("%s: read rgb_led_blue failed", __func__);
    30. return HDF_FAILURE;
    31. }
    32. HDF_LOGI("g_rgbLedDriverEntry: %s success", __func__);
    33. return HDF_SUCCESS;
    34. }
    • 函数名:HdfRgbLedDriverRelease。
    • 功能说明:HDF去注册。
    1. void HdfRgbLedDriverRelease(struct HdfDeviceObject *deviceObject)
    2. {
    3. if (deviceObject == NULL) {
    4. HDF_LOGE("g_rgbLedDriverEntry: %s failed", __func__);
    5. return;
    6. }
    7. HDF_LOGI("g_rgbLedDriverEntry: %s success", __func__);
    8. return;
    9. }
    • 函数名:HdfRgbLedDriverBind。
    • 功能说明:HDF绑定解析函数。
    1. int32_t HdfRgbLedDriverBind(struct HdfDeviceObject *deviceObject)
    2. {
    3. if (deviceObject == NULL) {
    4. HDF_LOGE("g_rgbLedDriverEntry: %s failed", __func__);
    5. return HDF_ERR_INVALID_OBJECT;
    6. }
    7. static struct IDeviceIoService ledDriverServ = {
    8. .Dispatch = rgbLedDriverDispatch,
    9. };
    10. deviceObject->service = (struct IDeviceIoService *)(&ledDriverServ);
    11. HDF_LOGI("g_rgbLedDriverEntry: %s success NodeName[%s]", __func__,
    12. deviceObject->property->name);
    13. return HDF_SUCCESS;
    14. }
    • 函数名:rgbLedDriverDispatch。
    • 功能说明:解析函数,解析应用层下发的命令,执行命令对应操作,RGB_LED_WRITE控制三色灯亮灭。
    1. int32_t rgbLedDriverDispatch(struct HdfDeviceIoClient *client, int32_t cmdId,
    2. struct HdfSBuf *dataBuf, struct HdfSBuf *replyBuf)
    3. {
    4. int32_t result = HDF_FAILURE;
    5. int32_t rgbLedMode = 0;
    6. if (client == NULL || client->device == NULL) {
    7. HDF_LOGE("driver device is NULL");
    8. return HDF_ERR_INVALID_OBJECT;
    9. }
    10. if (g_rgbLedCfg.rgb_led_version != RGB_LED_VERSION) {
    11. HDF_LOGE("driver rgb_led_version not match");
    12. return HDF_FAILURE;
    13. }
    14. switch (cmdId) {
    15. case RGB_LED_WRITE:
    16. result = HdfSbufReadInt32(dataBuf, &rgbLedMode);
    17. if (result) {
    18. HDF_LOGI("%s: mode:[0x%X][%s%s%s]", __func__, rgbLedMode,
    19. (rgbLedMode&RGB_LED_RED_BIT)?"R":"-",
    20. (rgbLedMode&RGB_LED_GREEN_BIT)?"G":"-",
    21. (rgbLedMode&RGB_LED_BLUE_BIT)?"B":"-");
    22. LedGpioCtrl(g_rgbLedCfg.rgb_led_red, (rgbLedMode&RGB_LED_RED_BIT)?LED_ON:LED_OFF);
    23. LedGpioCtrl(g_rgbLedCfg.rgb_led_green, (rgbLedMode&RGB_LED_GREEN_BIT)?LED_ON:LED_OFF);
    24. LedGpioCtrl(g_rgbLedCfg.rgb_led_blue, (rgbLedMode&RGB_LED_BLUE_BIT)?LED_ON:LED_OFF);
    25. }
    26. break;
    27. default:
    28. HDF_LOGE("%s: receiving unknown command", __func__);
    29. break;
    30. }
    31. return result;
    32. }
    • 函数名:LedGpioCtrl。
    • 功能说明:LED GPIO控制函数,低电平点亮LED,高电平熄灭LED。
    1. static int32_t LedGpioCtrl(uint16_t gpio, int32_t mode)
    2. {
    3. uint16_t level = GPIO_VAL_HIGH;
    4. if (HDF_SUCCESS != GpioSetDir(gpio, GPIO_DIR_OUT)) {
    5. HDF_LOGE("%s: GpioSetDir failed", __func__);
    6. return HDF_FAILURE;
    7. }
    8. if (mode == LED_ON) {
    9. level = GPIO_VAL_LOW;
    10. } else if (mode == LED_OFF) {
    11. level = GPIO_VAL_HIGH;
    12. }
    13. if (HDF_SUCCESS != GpioWrite(gpio, level)) {
    14. HDF_LOGE("%s: GpioWrite failed", __func__);
    15. return HDF_FAILURE;
    16. }
    17. return HDF_SUCCESS;
    18. }

    3、应用层程序

    (1)应用层代码分析

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

    1. int main(int argc, char* argv[])
    2. {
    3. int ret = HDF_SUCCESS;
    4. int32_t mode = -1;
    5. if (argc == ARGS_NUM) {
    6. mode = atoi(argv[1]);
    7. /*low-3bits*/
    8. mode &= 0x7;
    9. HILOG_INFO(LOG_APP, "[%s] main enter: mode[%s%s%s][0x%X]",
    10. LOG_TAG,
    11. (mode&RGB_LED_BLUE_BIT)?"B":"-",
    12. (mode&RGB_LED_GREEN_BIT)?"G":"-",
    13. (mode&RGB_LED_RED_BIT)?"R":"-",
    14. mode);
    15. printf("RGB mode[%s%s%s][0x%X]\n",
    16. (mode&RGB_LED_BLUE_BIT)?"B":"-",
    17. (mode&RGB_LED_GREEN_BIT)?"G":"-",
    18. (mode&RGB_LED_RED_BIT)?"R":"-",
    19. mode);
    20. } else {
    21. HILOG_INFO(LOG_APP, "[%s] main enter: auto test RGB LED", LOG_TAG);
    22. printf("auto test RGB LED\n");
    23. }
    24. struct HdfIoService *serv = HdfIoServiceBind(RGB_LED_SERVICE_NAME);
    25. if (serv == NULL) {
    26. HILOG_ERROR(LOG_APP, "get service %s failed", RGB_LED_SERVICE_NAME);
    27. return -1;
    28. }
    29. struct HdfSBuf *data = HdfSbufObtainDefaultSize();
    30. if (data == NULL) {
    31. HILOG_ERROR(LOG_APP, "obtain data failed");
    32. return -1;
    33. }
    34. if (mode == -1) {
    35. mode = 0x8;
    36. while (mode) {
    37. HdfSbufFlush(data);
    38. if (!HdfSbufWriteInt32(data, --mode)) {
    39. HILOG_ERROR(LOG_APP, "write data failed");
    40. return -1;
    41. }
    42. ret = serv->dispatcher->Dispatch(&serv->object, RGB_LED_WRITE, data, NULL);
    43. sleep(1);
    44. }
    45. } else {
    46. if (!HdfSbufWriteInt32(data, mode)) {
    47. HILOG_ERROR(LOG_APP, "write data failed");
    48. return -1;
    49. }
    50. ret = serv->dispatcher->Dispatch(&serv->object, RGB_LED_WRITE, data, NULL);
    51. }
    52. HdfSbufRecycle(data);
    53. HdfIoServiceRecycle(serv);
    54. HILOG_INFO(LOG_APP, "[%s] main exit.", LOG_TAG);
    55. return ret;
    56. }

    四、运行程序

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

    rgb_led

    五、运行结果

    运行结果:

    1. # rgb_led
    2. auto test RGB LED
    3. # rgb_led 1
    4. RGB mode[--R][0x1]
    5. # rgb_led 2
    6. RGB mode[-G-][0x2]
    7. # rgb_led 3
    8. RGB mode[-GR][0x3]
    9. # rgb_led 4
    10. RGB mode[B--][0x4]
    11. # rgb_led 5
    12. RGB mode[B-R][0x5]
    13. # rgb_led 6
    14. RGB mode[BG-][0x6]
    15. # rgb_led 7
    16. RGB mode[BGR][0x7]

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

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

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

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

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

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

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

  • 相关阅读:
    制作一个简单HTML校园网页(HTML+CSS)学校网站制作 校园网站设计与实现
    qtdesigner添加菜单栏工具栏及监听事件
    国科大移动互联网考试资料(2023+2020+2018真题+答案)
    10.8c++作业
    【元宇宙欧米说】MetaArks:打造社交+游戏的商业发展模式
    2022-11-21 mysql列存储引擎-架构实现缺陷梳理-P1
    react写一个简单的3d滚轮picker组件
    科技的成就(三十九)
    Hadoop分布式安装
    NC200369 四舍五入(枚举)
  • 原文地址:https://blog.csdn.net/wangonik_l/article/details/132759347