当前位置: 首页 > news >正文

OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序

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

一、案例简介

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

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

详细资料请参考OpenHarmony官网:

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

二、基础知识

1、ADC简介

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

2、ADC平台驱动

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

OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序-开源基础软件社区

OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序-开源基础软件社区

ADC模块各分层的作用为:

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

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

3、ADC应用程序

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

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

接口名

接口描述

DevHandle AdcOpen(uint32_t number)

打开ADC设备

void AdcClose(DevHandle handle)

关闭ADC设备

int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t *val)

读取AD转换结果值

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

OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序-开源基础软件社区

OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序-开源基础软件社区

三、程序解析

1、准备工作

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

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_adapterdeviceMatchAttr = "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匹配。
(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)参与配置树编译

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

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

3、HDF驱动

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

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

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;
}
(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)参与应用程序编译

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

"b04_platform_device_adc/app:rk3568_adc_test",

四、程序编译

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

hb set -root .
hb set
# 选择lockzhiner下的rk3568编译分支。
hb build -f

五、运行结果

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

# 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: 5
Adc Device(0), Channel(5) read successful and value = 955
#

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

最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。 

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

鸿蒙(HarmonyOS NEXT)最新学习路线

  •  HarmonOS基础技能

  • HarmonOS就业必备技能 
  •  HarmonOS多媒体技术

  • 鸿蒙NaPi组件进阶

  • HarmonOS高级技能

  • 初识HarmonOS内核 
  • 实战就业级设备开发

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

《鸿蒙 (OpenHarmony)开发入门教学视频》

《鸿蒙生态应用开发V2.0白皮书》

图片

《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

图片

 《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

图片

 《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

图片

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

图片

 获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结

总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

相关文章:

OpenHarmony:全流程讲解如何编写ADC平台驱动以及应用程序

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

计算机学生求职简历的一些想法

面试真的是一件非常难的事情,因为在短短的半小时到一个小时,来判断一个同学行不行,其实是很不全面的。作为一个求职的同学应该怎么办呢?求职的同学可以提前做一些准备,其中比较重要的要数简历的编写。 简历的作用 简…...

网工内推 | 售前专场,需熟悉云计算技术,上市公司,提成高

01 神州数码 招聘岗位:售前工程师 职责描述: 1.负责所在区域华为IT产品线(服务器、存储、云、虚拟化)的售前技术支持工作,包括客户交流、方案编写、配置报价、投标支持、测试等; 2.与厂商相关人员建立和保…...

excel匹配替换脱敏身份证等数据

假如excel sheet1中有脱敏的身份证号码和姓名,如: sheet2中有未脱敏的数据数据 做法如下: 1、在sheet2的C列用公式 LEFT(A2,6)&REPT("*",8)&RIGHT(A2,4) 做出脱敏数据,用来与sheet1的脱敏数据匹配 2、在sheet…...

[技术笔记] Flash选型之基础知识芯片分类

1、按照接口分类 分为 Serial串口Flash 和 Parallel并口Flash; 市场大量使用Serial Flash;价格便宜;已满足系统对数据读写速度的要求; Serial Flash已经可以代表 NOR Flash; 小知识: 1)在…...

Jenkins常用插件安装及全局配置

Jenkins常用插件安装及全局配置 前言 ​ Jenkins是一个流行的持续集成工具,通过安装适用的插件,可以扩展Jenkins的功能,并与其他工具和系统集成。本文将介绍一些常用的Jenkins插件以及安装和配置的步骤。通过安装和配置这些常用插件&#xf…...

C++初学者:如何优雅地写程序

我喜欢C语言的功能强大,简洁,我也喜欢C#的语法简单,清晰,写起来又方便好用。 一、为什么不用C语言写程序。 C语言用来做题目,考试研究是很方便的,但是用来写程序做软件,你就会发现&#xff0c…...

图论- 最小生成树

一、最小生成树-prim算法 1.1 最小生成树概念 一幅图可以有很多不同的生成树,比如下面这幅图,红色的边就组成了两棵不同的生成树: 对于加权图,每条边都有权重(用最小生成树算法的现实场景中,图的边权重…...

LeetCode刷题记(一):1~30题

1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以…...

芒果YOLOv5改进89:卷积SPConv篇,即插即用,去除特征图中的冗余,FLOPs 和参数急剧下降,提升小目标检测

芒果专栏 基于 SPConv 的改进结构,改进源码教程 | 详情如下🥇 👉1. SPConv 结构、👉2. CfSPConv 结构 💡本博客 改进源代码改进 适用于 YOLOv5 按步骤操作运行改进后的代码即可 即插即用 结构。博客 包括改进所需的 核心结构代码 文件 YOLOv5改进专栏完整目录链接:…...

Linux:详解TCP报头类型

文章目录 温习序号的意义序号和确认序号报文的类型 TCP报头类型详解ACK: 确认号是否有效SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段FIN: 通知对方, 本端要关闭了PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走RST: 对方要求重新建立连接; 我们把携带RST标识的称…...

【Leetcode】top 100 二分查找

35 搜索插入位置 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。请必须使用时间复杂度为 O(log n) 的算法。 基础写法!!!牢记…...

Redis高级面试题-2024

说说你对Redis的理解 Redis是一个基于Key-Value存储结构的开源内存数据库,也是一种NoSQL数据库。 它支持多种数据类型,包括String、Map、Set、ZSet和List,以满足不同应用场景的需求。 Redis以内存存储和优化的数据结构为基础,提…...

HarmonyOS 应用开发之FA模型与Stage模型应用组件

应用配置文件概述(FA模型) 每个应用项目必须在项目的代码目录下加入配置文件,这些配置文件会向编译工具、操作系统和应用市场提供描述应用的基本信息。 应用配置文件需申明以下内容: 应用的软件Bundle名称,应用的开发…...

6个黑科技网站,永久免费

1、http://mfsc123.com https://www.mfsc123.com 一个非常赞的免费商用素材导航网站。 收集了各种免费、免版权的图片、插画、视频、视频模板、音乐、音效、字体、图标网站。 再也不用担心版权问题,都能免费商用,自媒体作者必备。 而且还在每个网站…...

Linux 内核优化简笔 - 高并发的系统

简介 Linux 服务器在高并发场景下,默认的内核参数无法利用现有硬件,造成软件崩溃、卡顿、性能瓶颈。 当然,修改参数只是让Linux更好软件的去利用已有的硬件资源,如果硬件资源不够也无法解决问题的。而且当硬件资源不足的时候&am…...

整型之韵,数之舞:大小端与浮点数的内存之旅

✨✨欢迎👍👍点赞☕️☕️收藏✍✍评论 个人主页:秋邱’博客 所属栏目:人工智能 (感谢您的光临,您的光临蓬荜生辉) 1.0 整形提升 我们先来看看代码。 int main() {char a 3;char b 127;char …...

变量作用域

变量作用域 标识符的作用域是定义为其声明在程序里的可应用范围, 或者即是我们所说的变量可见性。换句话说,就好像在问你自己,你可以在程序里的哪些部分去访问一个制定的标识符。变量可以是局部域或者全局域。 全局变量与局部变量 定义在函数内的变量有局部作用域,在一个…...

数据结构:链表的双指针技巧

文章目录 一、链表相交问题二、单链表判环问题三、回文链表四、重排链表结点 初学双指针的同学,请先弄懂删除链表的倒数第 N 个结点。 并且在学习这一节时,不要将思维固化,认为只能这样做,这里的做法只是技巧。 一、链表相交问题 …...

用WHERE命令可以在命令行搜索文件

文章目录 用WHERE命令可以在命令行搜索文件概述笔记没用的小程序END 用WHERE命令可以在命令行搜索文件 概述 想确认PATH变量中是否存在某个指定的程序(具体是在PATH环境变量中给出的哪个路径底下?). 开始不知道windows有where这个命令, 还自己花了2个小时写了一个小程序. 后…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子&#xff08…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

生成 Git SSH 证书

🔑 1. ​​生成 SSH 密钥对​​ 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​: -t rsa&#x…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

基于 TAPD 进行项目管理

起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...