ADC
Analog-to-Digital Converter,即模拟/数字转换器
常见ADC类型
分辨率和采样速度相互矛盾,分辨率越高,采样速率越低。
ADC的特性参数
- 分辨率:表示ADC能辨别的最小模拟量,用二进制位数表示,比如8,10,12,16位等。(刻度划分)(3.3V/4096)
- 转换时间:完成一次A/D转换所需的时间,转换时间越短,采样率就可以越高
- 精度:最小刻度基础上叠加各种误差的参数,精度受ADC性能、温度和气压等影响。
- 量化误差:用数字量近似表示模拟量,采用四舍五入原则,此过程产生的误差为量化误差。
STM32各系列ADC主要特性
ADC工作原理
ADC供电电源VSSA、VDDA(2.4V~3.6V)
输入通道
外部16个输入通道,内部2个输入通道
转换序列
触发源
转换时间
数据寄存器
中断
转换序列(F1为例)
A/D转换被组织为两组:规则组(常规转换组)和注入组(注入转换组)
规则组最多可以有16个转换,注入组最多有4个转换。
排A/D转换先后顺序
触发源
触发转换的方法有两种:
-
ADON位触发转换(仅限F1系列)
-
外部事件触发转换
外部事件触发转换分为:规则组外部触发和注入组外部触发
DMA请求(只适用于规则组)
规则组每个通道转换结束后,除了可以产生中断外,还可以产生DMA请求,我们利用DMA及时把转换好的数据传输到指定的内存里,防止数据被覆盖。
单次转换模式和连续转换模式
单次转换模式:只触发一次转换
连续转换模式:自动触发下一次转换
扫描模式
单通道ADC采集实验(战舰为例)
通过ADC1通道1(PA1)采集电位器的电压,并显示ADC转换的数字量以及换算后的电压值。
RTT ADC
ADC(Analog-to-Digital Converter)指模数转换器。
是指将连续变化的模拟信号转换为离散的数字信号的器件。
真实世界的模拟信号,例如温度、压力、声音或者图像等,需要转换成更容易储存、处理和发射的数字形式。
模数转换器可以实现这个功能,在各种不同的产品中都可以找到它的身影。
与之相对应的DAC(Digital-to-Analog Converter),它是ADC模数转换的逆向过程。
ADC最早用于对无线信号箱数字信号转换。如电视信号,长短播电台发射接收等。
转换过程
如下图所示,模数转换一般要经过采样、保持和量化、编码这几个步骤。
在实际电路中,有些过程是合并进行的,如采样和保持,量化和编码在转换过程中是同时实现的。
采样是将时间上连续变化的模拟信号转换为时间上离散的模拟信号。
采样取得的模拟信号转换为数字信号都需要一定时间,为了给后续的量化编程过程提供一个稳定的值,在采样电路后要求将所采样的模拟信号保持一段时间。
将数值连续的模拟量转换为数字量的过程称为量化。
数字信号在数值上是离散的。
采用保持电路的输出电压还需要按照某种近似方式归化到与之相应的离散电平上,任何数字量只能是某个最小数量单位的整数倍。
量化后的数值最后还需要编码过程,也就是AD转换器输出的数字量。
分辨率
分辨率以二进制(或十进制)数的位数来表示,一般有8位、10位、12位、16位等,它说明模数转换器对输入信号的分辨能力,位数越多,表示分辨率越高,恢复模拟信号时会更精确。
精度
精度表示ADC器件在所有的数值点上对应的模拟值和真实值之间的最大误差值,也就是输出数值偏离线性最大的距离。
转换速率
转换速率是指A/D转换器完成一次从模拟到数字的AD转换所需时间的倒数。
例如,某A/D转换器的转换速率为1MHZ,则表示完成一次AD转换时间为1us。
查找ADC设备
应用程序根据ADC设备名称获取设备句柄,进而可以操作ADC设备,查找设备函数如下所示:
c
rt_device_t rt_device_find(const char* name);
一般情况下,注册到系统的ADC设备名称为adc0,adc1等,使用示例如下:
c
#define ADC_DEV_NAME "adc1"
rt_adc_device_t adc_dev;
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
使能ADC通道
在读取ADC设备数据前需要先使能设备,通过如下函数使能设备:
c
rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel);
- dev:ADC设备句柄
- channel:ADC通道
返回
- RT_EOK:成功
- -RT_ENOSYS:失败,设备操作方法为空
c
#define ADC_DEV_NAME "adc1"
#define ADC_DEV_CHANNEL 5
rt_adc_device_t adc_dev;
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
读取ADC通道采样值
c
rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel);
c
#define ADC_DEV_NAME "adc1"
#define ADC_DEV_CHANNEL 5
#define REFER_VOLTAGE 330
#define CONVERT_BITS (1 << 12)
rt_adc_device_t adc_dev; /* ADC 设备句柄 */
rt_uint32_t value;
/* 查找设备 */
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
/* 使能设备 */
rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
/* 读取采样值 */
value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
/* 转换为对应电压值 */
vol = value * REFER_VOLTAGE / CONVERT_BITS
rt_kprintf("the voltage is :%d.%02d\n", vol/100, vol%100);
实际电压值的计算公式为:采样值*参考电压/(1 << 分辨率位数),上面示例代码乘以 100 将数据放大,最后通过 vol / 100 获得电压的整数位值,通过 vol % 100 获得电压的小数位值。
FinSH命令
在使用设备前,需要先查找设备是否存在,可以使用命令adc probe后面跟注册的ADC设备的名称。
c
msh >adc probe adc1
probe adc1 success
使能设备的某个通道可以使用命令adc enable后面跟通道号
c
msh >adc enable 5
adc1 channel 5 enables success