采样是将时间上连续变化的模拟信号转换为时间上离散的模拟信号。采样取得的模拟信号转换为数字信号都需要一定时间,为了给后续的量化编码过程提供一个稳定的值,在采样电路后要求将所采样的模拟信号保持一段时间。
将数值连续的模拟量转换为数字量的过程称为量化。数字信号在数值上是离散的。采样保持电路的输出电压还需要按照某种近似方式归化到与之相应的离散电平上,任何数字量只能是某个最小数量单位的整数倍。量化后的数值最后还需要编码过程,也就是 A/D 转换器输出的数字量。
分辨率与量化误差
分辨率是衡量 A/D 转化器分辨输入模拟量最小变化程度的指标。分辨率以输出二进制(或十进制)数的位数来表示,它说明模数转换器对输入信号的分辨能力,一般有8位、10位、12位、16位等。在最大输入电压(参考电压)一定时,输出位数愈多,分辨率愈高。例如模数转换器输出为 8 位二进制数,输入信号最大值为 5V,那么这个转换器应能区分出输入信号的最小电压为 19.53mV(1 LSB),计算方法为:5/256 = 19.53mV。也就是低于 19.53mV 的输入电压的输出值都为0。如果模数转换器输出为 12 位二进制数,则输入信号最大值为 5V 对应的能区分的最小电压为:5/4096 = 1.22mV(1 LSB)。从 2 个最小电压来看位数越高能采集到更小的电压。
量化误差是由 A/D 转换器有限字长数字量对输入模拟量进行离散取样(量化)引起的误差。其大小在理论上为一个单位(1 LSB)。提高分辨率可以减小量化误差。
转换速率
转换速率是指 A/D 转换器在每秒钟能完成的转换次数。转换时间为 A/D 转换从启动到结束所需的时间,转换时间和转换速率互为倒数。例如,某 A/D 转换器的转换速率为 1MHz,则转换时间为 1 微秒。
访问 ADC 设备
应用程序通过 RT-Thread 提供的 ADC 设备管理接口来访问 ADC 硬件,相关接口如下所示:
[td]函数原型 | 功能简介 |
rt_device_find() | 根据 ADC 设备名称查找设备获取设备句柄 |
rt_adc_enable() | 使能 ADC 设备 |
rt_adc_read() | 读取 ADC 设备数据 |
rt_adc_disable() | 关闭 ADC 设备 |
查找 ADC 设备
应用程序根据 ADC 设备名称获取设备句柄,进而可以操作 ADC 设备,查找设备函数如下所示:
1rt_device_t rt_device_find(const char* name);
[td]
参数 | 描述 |
name | ADC 设备名称 |
返回 | —— |
设备句柄 | 查找到对应设备将返回相应的设备句柄 |
RT_NULL | 没有找到设备 |
一般情况下,注册到系统的 ADC 设备名称为 adc0,adc1等,使用示例如下所示:
1#define ADC_DEV_NAME "adc1" /* ADC 设备名称 */
2rt_adc_device_t adc_dev; /* ADC 设备句柄 */
3/* 查找设备 */
4adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
使能 ADC 通道
在读取 ADC 设备数据前需要先使能设备,通过如下函数使能设备:
1rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_uint32_t channel);
[td]
参数 | 描述 |
dev | ADC 设备句柄 |
channel | ADC 通道 |
返回 | —— |
RT_EOK | 成功 |
-RT_ENOSYS | 失败,设备操作方法为空 |
其他错误码 | 失败 |
使用示例如下所示:
1#define ADC_DEV_NAME "adc1" /* ADC 设备名称 */
2#define ADC_DEV_CHANNEL 5 /* ADC 通道 */
3rt_adc_device_t adc_dev; /* ADC 设备句柄 */
4/* 查找设备 */
5adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
6/* 使能设备 */
7rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
读取 ADC 通道采样值
读取 ADC 通道采样值可通过如下函数完成:
1 rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_uint32_t channel);
[td]
参数 | 描述 |
dev | ADC 设备句柄 |
channel | ADC 通道 |
返回 | —— |
读取的数值 |
|
使用 ADC 采样电压值的使用示例如下所示:
1#define ADC_DEV_NAME "adc1" /* ADC 设备名称 */
2#define ADC_DEV_CHANNEL 5 /* ADC 通道 */
3rt_adc_device_t adc_dev; /* ADC 设备句柄 */
4rt_uint32_t value;
5/* 查找设备 */
6adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
7/* 使能设备 */
8rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
9/* 读取采样值 */
10value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
11/* 转换为对应电压值,3.3V对应12位最大值4096,数据精度乘以100保留2位小数 */
12vol = value * 330 / 4096;
13rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
实际电压值的计算公式为:采样值 * 最大可转换电压 / (1 << 分辨率位数),上面示例代码乘以 100 将数据放大,最后通过 vol / 100 获得电压的整数位值,通过 vol % 100 获得电压的小数位值。
关闭 ADC 通道
关闭 ADC 通道可通过如下函数完成:
1rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_uint32_t channel);
[td]
参数 | 描述 |
dev | ADC 设备句柄 |
channel | ADC 通道 |
返回 | —— |
RT_EOK | 成功 |
-RT_ENOSYS | 失败,设备操作方法为空 |
其他错误码 | 失败 |
使用示例如下所示:
1#define ADC_DEV_NAME "adc1" /* ADC 设备名称 */
2#define ADC_DEV_CHANNEL 5 /* ADC 通道 */
3rt_adc_device_t adc_dev; /* ADC 设备句柄 */
4rt_uint32_t value;
5/* 查找设备 */
6adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
7/* 使能设备 */
8rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
9/* 读取采样值 */
10value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
11/* 转换为对应电压值,3.3V对应12位最大值4096,数据精度乘以100保留2位小数 */
12vol = value * 330 / 4096;
13rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);
14/* 关闭通道 */
15rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
FinSH 命令
在使用设备前,需要先查找设备是否存在,可以使用命令 adc probe 后面跟注册的 ADC 设备的名称。如下所示:
1msh >adc probe adc1
2probe adc1 success
使能设备的某个通道可以使用命令 adc enable 后面跟通道号。
1msh >adc enable 5
2adc1 channel 5 enables success
读取 ADC 设备某个通道的数据可以使用命令 adc read 后面跟通道号。
1msh >adc read 5
2adc1 channel 5 read value is 0x00000FFF
3msh >
关闭设备的某个通道可以使用命令 adc disable 后面跟通道号。
1msh >adc disable 5
2adc1 channel 5 disable success
3msh >
ADC 设备使用示例
ADC 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下: