首页 » 软件开发 » OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序(驱动文件系统通道设备控制器)

OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序(驱动文件系统通道设备控制器)

落叶飘零 2024-07-23 23:57:37 0

扫一扫用手机浏览

文章目录 [+]

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

详细资料请参考OpenHarmony官网:

ADC平台驱动开发ADC应用程序开发2、基础知识

2.1、ADC简介

OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序(驱动文件系统通道设备控制器) 软件开发
(图片来自网络侵删)

ADC(Analog to Digital Converter),即模拟-数字转换器,可将模拟信号转换成对应的数字信号,便于存储与计算等操作。
除电源线和地线之外,ADC只需要1根线与被测量的设备进行连接。

2.2、ADC平台驱动

在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),若采用独立服务模式,则需要配置更多的设备节点,且相关服务会占据更多的内存资源。
相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。
ADC模块即采用统一服务模式。
如下图所示:

统一服务模式结构图

ADC模块各分层的作用为:

接口层:提供打开设备,写入数据,关闭设备的能力。
核心层:主要负责服务绑定、初始化以及释放管理器,并提供添加、删除以及获取控制器的能力。
适配层:由驱动适配者实现与硬件相关的具体功能,如控制器的初始化等。

在统一模式下,所有的控制器都被核心层统一管理,并由核心层统一发布一个服务供接口层,因此这种模式下驱动无需再为每个控制器发布服务。

详细资料请参考官网地址:ADC平台驱动

2.3、ADC应用程序

ADC模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/adc_if.h。

ADC驱动API接口功能介绍如下所示:

使用ADC设备的一般流程如下所示:

ADC使用流程图

详细资料请参考官网地址:ADC应用程序

3、程序解析

3.1、准备工作

查看《凌蒙派-RK3568开发板排针说明表》(即Git仓库的//docs/board/凌蒙派-RK3568开发板排针说明表v1.0.xlsx),选中ADC5(即ADC5)。

3.2、配置文件

3.2.1、device_info.hcs

创建config/device_info.hcs,用于驱动设备描述,具体内容如下:

#include "adc_config.hcs"root { device_info { platform :: host { device_adc :: device { device0 :: deviceNode { // ADC控制器信息描述 policy = 2; // 对外发布服务,必须为2,用于定义ADC管理器的服务 priority = 50; permission = 0644; moduleName = "HDF_PLATFORM_ADC_MANAGER"; // 这与drivers/hdf_core/framework/support/platform/src/adc/adc_core.c的g_adcManagerEntry.moduleName对应,它主要负责ADC的管理 serviceName = "HDF_PLATFORM_ADC_MANAGER"; } device1 :: deviceNode { policy = 0; // 等于0,不需要发布服务 priority = 55; // 驱动驱动优先级 permission = 0644; // 驱动创建设备节点权限 moduleName = "linux_adc_adapter"; // 用于指定驱动名称,必须是linux_adc_adapter deviceMatchAttr = "linux_adc_adapter"; // 用于配置控制器私有数据,必须与adc_config.hcs中对应控制器保持一致 } } } }}

注意:

device0:ADC控制器,为了引入HDF_PLATFORM_ADC_MANAGER驱动,必须要。

device1:ADC实际操作接口。

moduleName:该驱动名称,必须是linux_adc_adapter,//drivers/hdf_core/adapter/khdf/linux/platform/adc/adc_iio_adapter.c已编写好。

deviceMatchAttr:关键字必须与config.hcs的match_attr匹配。

3.2.2、adc_config.hcs

创建config/adc_config.hcs,用于定义私有变量,具体内容如下:

root { platform { adc_config { match_attr = "linux_adc_adapter"; // 与device_info.hcs的deviceMatchAttr的值一致 template adc_device { // 必须与//drivers/hdf_core/adapter/khdf/linux/platform/adc/adc_iio_adapter.c的配置树定义保持一致 deviceNum = 0; // 设备号标识 channelNum = 8; // ADC通道数量 driver_channel0_name = ""; // 通道0在linux文件系统路径 driver_channel1_name = ""; // 通道1在linux文件系统路径 driver_channel2_name = ""; // 通道2在linux文件系统路径 driver_channel3_name = ""; // 通道3在linux文件系统路径 driver_channel4_name = ""; // 通道4在linux文件系统路径 driver_channel5_name = ""; // 通道5在linux文件系统路径 driver_channel6_name = ""; // 通道6在linux文件系统路径 driver_channel7_name = ""; // 通道7在linux文件系统路径 scanMode = 0; // 扫描模式(必要,但无意义) rate = 1000; // 转换速率(必要,但无意义) } device_0 :: adc_device { deviceNum = 0; channelNum = 8; driver_channel0_name = "/sys/bus/iio/devices/iio:device0/in_voltage0_raw"; driver_channel1_name = "/sys/bus/iio/devices/iio:device0/in_voltage1_raw"; driver_channel2_name = "/sys/bus/iio/devices/iio:device0/in_voltage2_raw"; driver_channel3_name = "/sys/bus/iio/devices/iio:device0/in_voltage3_raw"; driver_channel4_name = "/sys/bus/iio/devices/iio:device0/in_voltage4_raw"; driver_channel5_name = "/sys/bus/iio/devices/iio:device0/in_voltage5_raw"; driver_channel6_name = "/sys/bus/iio/devices/iio:device0/in_voltage6_raw"; driver_channel7_name = "/sys/bus/iio/devices/iio:device0/in_voltage7_raw"; } } }}

ADC实际驱动是//drivers/hdf_core/adapter/khdf/linux/platform/adc/adc_iio_adapter.c,template adc_device定义的各项关键变量是由adc_iio_adapter.c决定,不可修改。

adc_iio_adapter.c实际是对Linux IIO子系统进行操作来控制ADC。

注意:

channelNum:表示通道数量driver_channelX_name:必须是从0开始

3.2.3、参与配置树编译

编辑//vendor/lockzhiner/rk3568/hdf_config/khdf/hdf.hcs,将device_info.hcs添加配置树中。
具体内容如下所示:

#include "../../samples/b04_platform_device_adc/config/device_info.hcs"

3.3、HDF驱动

ADC平台驱动是//drivers/hdf_core/adapter/khdf/linux/platform/adc/adc_iio_adapter.c,用户不必编写HDF驱动。

3.4、参与Linux内核编译

编辑//kernel/linux/config/linux-5.10/arch/arm64/configs/rk3568_standard_defconfig,启用CONFIG_DRIVERS_HDF_PLATFORM_ADC,具体内容如下:

CONFIG_DRIVERS_HDF_PLATFORM_ADC=y

3.5、应用程序

3.5.1、adc_test.c

添加平台驱动ADC的头文件,具体内容如下:

#include "adc_if.h" // ADC标准接口头文件

程序可通过,具体内容如下:

int main(int argc, char argv[]){ DevHandle handle = NULL; int32_t ret; uint32_t value; // 解析参数 parse_opt(argc, argv); printf("adc_device: %d\n", m_adc_device); printf("adc_channel: %d\n", m_adc_channel); // 打开ADC设备 handle = AdcOpen(m_adc_device); if (handle == NULL) { PRINT_ERROR("AdcOpen failed\n"); return -1; } // 进行AD转换并读取转换结果 ret = AdcRead(handle, m_adc_channel, &value); if (ret != 0) { PRINT_ERROR("AdcRead failed and ret = %d\n", ret); AdcClose(handle); return -1; } printf("Adc Device(%d), Channel(%d) read successful and value = %d\n", m_adc_device, m_adc_channel, value); // 关闭ADC设备 AdcClose(handle); return 0;}

3.5.2、BUILD.gn

import("//build/ohos.gni")import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni")print("samples: compile rk3568_adc_test")ohos_executable("rk3568_adc_test") { sources = [ "adc_test.c" ] include_dirs = [ "$hdf_framework_path/include", "$hdf_framework_path/include/core", "$hdf_framework_path/include/osal", "$hdf_framework_path/include/platform", "$hdf_framework_path/include/utils", "$hdf_uhdf_path/osal/include", "$hdf_uhdf_path/ipc/include", "//base/hiviewdfx/hilog/interfaces/native/kits/include", "//third_party/bounds_checking_function/include", ] deps = [ "$hdf_uhdf_path/platform:libhdf_platform", "$hdf_uhdf_path/utils:libhdf_utils", "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog", ] cflags = [ "-Wall", "-Wextra", "-Werror", "-Wno-format", "-Wno-format-extra-args", ] subsystem_name = "applications" part_name = "product_rk3568" install_enable = true}

3.5.3、参与应用程序编译

编辑//vendor/lockzhiner/rk3568/samples/BUILD.gn,开启编译选项。
具体如下:

"b04_platform_device_adc/app:rk3568_adc_test",4、程序编译

建议使用docker编译方法,运行如下:

hb set -root .hb set# 选择lockzhiner下的rk3568编译分支。
hb build -f
5、运行结果

该程序运行结果如下所示:

# rk3568_adc_test -d 0 -c 5../../vendor/lockzhiner/rk3568/samples/b21_platform_device_adc/app/adc_test.c, main, 103, info: adc_device: 0../../vendor/lockzhiner/rk3568/samples/b21_platform_device_adc/app/adc_test.c, main, 104, info: adc_channel: 5Adc Device(0), Channel(5) read successful and value = 955#

可以将ADC引脚通过引线接入排针线中的GNU或3V3中,可以查看ADC的变化。

标签:

相关文章

C语言表白代码,编程之美,爱意绵绵

在这个科技飞速发展的时代,编程已经成为了我们生活中不可或缺的一部分。而C语言作为一门经典的编程语言,更是备受青睐。今天,就让我们用...

软件开发 2024-12-04 阅读8 评论0

16倍速生活方式,高效工作与生活的完美融合

随着科技的飞速发展,我们的生活节奏也在不断加快。在这个快节奏的时代,如何高效地平衡工作与生活,成为了许多人关注的焦点。本文将探讨1...

软件开发 2024-12-04 阅读7 评论0

C语言编程猜数游戏,编程与娱乐的完美融合

在科技日新月异的今天,编程已经成为一项重要的技能。作为计算机科学的基础,编程不仅可以锻炼我们的逻辑思维,还能提高我们的动手能力。而...

软件开发 2024-12-04 阅读7 评论0

C语言病毒代码介绍,技术与道德的双重挑战

随着信息技术的飞速发展,网络安全问题日益凸显。病毒作为一种恶意软件,严重威胁着计算机系统的稳定运行。C语言作为一种功能强大的编程语...

软件开发 2024-12-04 阅读5 评论0