[文章]OpenHarmony:如何使用HDF驱动控制LED灯

阅读量0
1
1


1、程序简介
该程序是基于OpenHarmony标准系统编写的基础外设类:RGB LED。
目前已在凌蒙派-RK3568开发板跑通。详细资料请参考官网:https://gitee.com/Lockzhiner-Ele ... les/b02_hdf_rgb_led
详细资料请参考OpenHarmony官网:

  • GPIO平台驱动开发
  • GPIO应用程序开发
2、硬件设计
RGB LED灯整体硬件电路如下图所示,硬件电路中包含了三个GPIO控制管脚控制RGB LED灯,低电平点亮LED灯,高电平熄灭LED灯。电路简单,这边不对此进行多余的说明。
lz_rgb_led_sch.jpg
3、程序解析
3.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           # 应用层控制程序
复制代码
3.2 内核HDF驱动程序
3.2.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.3 应用层程序
3.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. }
复制代码
4、运行程序
系统启动后,命令行运行命令:
  1. rgb_led
复制代码
5、运行结果
运行结果:
  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]
复制代码



回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友