从模拟到数字,一文读懂OneOS驱动ADC

从模拟到数字,一文读懂OneOS驱动ADC

  1. ADC设备

1.1 简介

ADC设备是实现模拟量转换为数字量的器件,即Analog-to-Digital Converter,模拟/数字转换器。相应地,还有DAC设备,即Digital-to-Analog Converter,数字/模拟转换器,用于实现数字量向模拟量的转化。

1.2 ADC参数分析

  1. ADC的分辨率

指的是模数转换器所能表示的最大数是多少,即ADC的位数,如果ADC是10位ADC,那么分辨率是2的10次方,即1024的分辨率,如果模拟量是温度,测量范围是0~100度,那么可以把100度分成1024份,每一份你都能感知,当温度有100/1024度的变化时,能测量出来。

  1. ADC的采样率

指ADC每秒钟会进行多少次的模拟量转数字量的操作,如10K/s就是说ADC每秒钟,就采集了10K个模拟量,并将模拟量转换为数字量。

  1. 通道

即ADC输入引脚,通常一个ADC控制器控制多个通道,如果需要多通道的话,就得进行通道扫描了。

  1. ADC的转换方式 

单次转换:一次只转换一个通道;

连续转换:转换完成一个通道后立即自动执行下一个通道的转换;

扫描模式:开启一次后,自动的连续读取多个通道。

  1. ADC的三种工作方式 

阻塞模式(查询模式)、中断模式、DMA模式

  1. ADC设备访问和注册

2.1 ADC设备访问

用户在访问ADC设备时,会调用设备管理层的接口,如os_device_find()、os_device_open()、os_device_control()、os_device_read_nonblock()、os_device_close()等,来实现对ADC的访问。设备管理层的接口往下调用设备框架层的接口,再往下调用设备驱动层的接口,最终实现对ADC硬件的相关操作。

取“os_device_control()”函数为例。

函数

路径

所属层

由上往下执行

os_device_control()

drivers\device.c

设备管理层

(所有设备通用的函数接口)

_adc_control()

drivers\misc\adc.c

设备框架层

(同类设备的抽象)

stm32_adc_enabled()

drivers\hal\st\drivers\drv_adc.c

设备驱动层

(由函数接口访问具体的硬件)

2.2 ADC设备注册

在访问ADC设备的过程中,从设备管理层往下调用至设备驱动层,那系统是如何确定要往下调用哪个接口呢?这就是ADC设备注册时指定的。设备注册的过程和设备访问的过程刚好是相反的,注册时从设备驱动层往上,直至设备管理层,如下表所示。

函数

路径

所属层

由上往下执行

stm32_adc_probe()

drivers\hal\st\drivers\drv_adc.c

设备驱动层

os_hw_adc_register()

drivers\misc\adc.c

设备框架层

os_device_register()

drivers\device.c

设备管理层

(把设备结点添加到设备链表)

 

接下来对注册的过程作简单说明。

2.2.1 设备驱动层

位置:drivers\hal\st\drivers\drv_adc.c

从“stm32_adc_probe()”函数开始,下面为局部截图。

  1. 此函数中下面的语句确定了访问设备时调用的接口函数:

  1. 此函数中由下面的语句调用设备框架层的os_hw_adc_register()函数:

  1. 此函数中涉及的两个结构体

位置:drivers\bus\bus.h

2.2.2 设备框架层

位置:drivers\misc\adc.c

由上述的设备驱动层调用下面的os_hw_adc_register()函数。

在该函数中继续往上调用设备管理层的os_device_register()接口。

2.2.3 设备管理层

位置:drivers\device.c

由上述的设备框架层调用下面的os_device_register()函数。下图为局部截图。

  1. 此函数中下面语句实现了把设备结点添加到系统的设备链表里:

其中相关定义:

①位置drivers\device.c

位置kernel\include\os_list.h

os_list_add函数的定义:

位置:kernel\include\os_list.h

链表结点的定义:

位置:kernel\include\os_list.h

  1. ADC demo运行流程

demo文件位置:demos\driver\adc_test.c

由上往下

左往右执行

os_device_find()

(device.c)

os_device_open()

(device.c)

os_device_control()

(device.c)

_adc_control()

(adc.c)

stm32_adc_enabled()

(drv_adc.c)

os_device_read_nonblock()

(device.c)

_adc_read()

(adc.c)

os_adc_read()

(adc.c)

stm32_adc_read()

(drv_adc.c)

os_device_control()

(device.c)

_adc_control()

(adc.c)

stm32_adc_enabled()

(drv_adc.c)

os_device_close()

(device.c)

 

路径

drivers\device.c

drivers\misc\adc.c

drivers\hal\st\drivers\drv_adc.c

adc_sample()函数部分运行过程分析:

adc_test.c【int adc_sample(int argc, char **argv)】

函数(由上往下执行)

语句(由上往下执行)

功能

os_device_find(argv[1])

功能:由设备名称“argv[1]”寻找设备

位置:OneOS\drivers\device.c

os_sem_wait(&dev_sem,OS_WAIT_FOREVER);

信号量等待

for循环

在链表“os_device_list”中寻找该设备

os_sem_post(&dev_sem);

return dev;

找到则释放信号量并返回对应设备结构体(类型“os_device_t”)

os_sem_post(&dev_sem);

return OS_NULL;

未找到设备则释放信号量并返回“OS_NULL”

os_device_open(adc_dev);

条件:找到设备后可执行

功能:“打开”设备,可初始化设备

位置:OneOS\drivers\device.c

os_sem_wait(&dev->sem, OS_WAIT_FOREVER);

信号量等待

dev->ops->init(dev);

初始化设备,但本测试中未进行。

涉及结构体:“os_device”“os_device_ops”

os_sem_post(&dev->sem);

释放信号量

os_plug_get("device", dev->name);

return result;

plug->ref_count++;

返回“OS_EOK”

os_device_control(adc_dev, OS_ADC_CMD_ENABLE, OS_NULL);

位置:OneOS\drivers\device.c

switch语句

由输入的cmd:OS_ADC_CMD_ENABLE在switch语句中进行匹配,未匹配到对应指令

os_sem_wait(&dev->sem, OS_WAIT_FOREVER);

信号量等待

dev->ops->control(dev, cmd, arg);

进入“_adc_control()

os_sem_post(&dev->sem);

return ret;

释放信号量;

返回“_adc_control()的返回结果

_adc_control(struct os_device *dev, int cmd, void *args)

os_device_control()函数进入

位置:OneOS\drivers\misc\adc.c

switch语句

由输入的cmd:OS_ADC_CMD_ENABLE在switch语句中进行匹配

adc->ops->adc_enabled(adc, OS_TRUE);

return result;

执行stm32_adc_enabled()然后返回其执行结果

stm32_adc_enabled()

_adc_control()函数进入

位置:OneOS\drivers\hal\st\drivers\drv_adc.c

/

使能设备,返回OS_EOK

os_device_read_nonblock(adc_dev, adc_channel, &adc_databuf, sizeof(adc_databuf));

位置:OneOS\drivers\device.c

dev->ops->read(dev, pos, buffer, size);

进入“_adc_read()”函数

涉及结构体:

 return count;

返回“_adc_read()”执行结果

_adc_read(struct os_device *dev, os_off_t pos, void *buffer, os_size_t size)

for循环

return i;

返回执行os_adc_read()的次数

 

人大毕业生盗取全校学生信息建颜值打分网站,已被刑拘 基于 NT 架构的全新 QQ Windows 版正式发布 美国将限制中国使用亚马逊、微软等提供训练 AI 模型的云服务 资金严重短缺,又一流行开源项目宣布停止功能开发 2023 年收入最高的技术岗位 LeaferJS 发布:开源、性能强悍的 2D 图形库 Visual Studio Code 1.80 发布,支持终端图片功能 Threads 注册量已破三千万,后端基于 CPython 深度“魔改” deepin 采用 Asahi Linux 适配 Apple M1 7 月数据库排行:Oracle 大涨,再度拉开比分
{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/5443273/blog/10086865