ADC设备是实现模拟量转换为数字量的器件,即Analog-to-Digital Converter,模拟/数字转换器。相应地,还有DAC设备,即Digital-to-Analog Converter,数字/模拟转换器,用于实现数字量向模拟量的转化。
指的是模数转换器所能表示的最大数是多少,即ADC的位数,如果ADC是10位ADC,那么分辨率是2的10次方,即1024的分辨率,如果模拟量是温度,测量范围是0~100度,那么可以把100度分成1024份,每一份你都能感知,当温度有100/1024度的变化时,能测量出来。
指ADC每秒钟会进行多少次的模拟量转数字量的操作,如10K/s就是说ADC每秒钟,就采集了10K个模拟量,并将模拟量转换为数字量。
即ADC输入引脚,通常一个ADC控制器控制多个通道,如果需要多通道的话,就得进行通道扫描了。
单次转换:一次只转换一个通道;
连续转换:转换完成一个通道后立即自动执行下一个通道的转换;
扫描模式:开启一次后,自动的连续读取多个通道。
阻塞模式(查询模式)、中断模式、DMA模式
用户在访问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 | 设备驱动层 (由函数接口访问具体的硬件) |
在访问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 | 设备管理层 (把设备结点添加到设备链表) |
接下来对注册的过程作简单说明。
位置:drivers\hal\st\drivers\drv_adc.c
从“stm32_adc_probe()”函数开始,下面为局部截图。
位置:drivers\bus\bus.h
位置:drivers\misc\adc.c
由上述的设备驱动层调用下面的os_hw_adc_register()函数。
在该函数中继续往上调用设备管理层的os_device_register()接口。
位置:drivers\device.c
由上述的设备框架层调用下面的os_device_register()函数。下图为局部截图。
其中相关定义:
①位置drivers\device.c
②位置kernel\include\os_list.h
③os_list_add函数的定义:
位置:kernel\include\os_list.h
④链表结点的定义:
位置:kernel\include\os_list.h
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()的次数 |
|