赞
踩
AD很复杂,其实也不复杂,因为我们用的不多。
AD:模拟量转换数字量(模拟信号转换数字信号)。
ADC:模拟量转数字量的转换器。
为什么需要AD呢?
自然界宏观的物理量都是连续的。而机器识别的信号0与1是离散的。为了让机器能够采集、分析、储存这些连续的量,所以要把需要被模拟的量转换为数字量。
主要的参数:采样精度与转换速度。
采样精度,也叫作分辨率。如果0-100摄氏度用8位AD来储存的话,精度计算?
0000 0000 —— 0摄氏度
1111 1111 —— 100摄氏度
100/256 = 0.39摄氏度,0.39就是最小份的分辨率,也就是采样精度.没有办法表现出0.2度
100/65536 = 0.0015,16位的AD,精度就很高了。
转换速度
从启动到出结果用的时间,一般来说越快越好。与精度不可兼得。被单位时间采样数量影响。采样多,速度不会很快。
STM32F4使用的AD是逐次逼近型ADC,它产生一系列比较电压VR,但它是逐个产生比较电压,逐次与输入电压分别比较,以逐渐逼近的方式进行模数转换的。它比并联比较型ADC的转换速度慢,比双分积型ADC要快得多,属于中速ADC器件。
在STM32的手册中,我们发现,不论是单次采集还是多次采集,转换完成的数据都会放在同一个地方。
由于DR寄存器不是一个数组,而是一个字节,所以只能保存最新的转换结果。例如,通道1和通道2都使用,通道1的转换结果放在DR寄存器。通道2转换完毕以后,就会覆盖通道1的结果。
程序里,当然可以通过一些处理,让通道1的结果在被覆盖之前就保存好。不过,运用STM32的DMA功能,可以更好地解决结果被覆盖的问题。
重点:用于高速搬运数据,还无需CPU干预。 因此在多通道采集模拟量是,我们可以建立一个数组,用于储存AD转换的数据。一旦ADC_DR寄存器里有了新的数据,就把新数据放在数组里。一会儿ADC_DR有了一个新的数据,就放在数组下一位。数组装满以后?根据需求来。我们设置的是循环模式,也就是再来一遍,覆盖之前的数据。
我使用的板子,有两路NTC热敏电阻分别接在PC0与PC1上,我们把这两个引脚用作ADC1的通道10与11。
新建AD.c与AD.h文件,设置全局的接收数组与计数器。
//AD.c
uint32_t AD_Buf[ADC_CHANNEL_CNT];
uint32_t DMA_CNT = 0;
//AD.h
#define ADC_CHANNEL_CNT 2
extern uint32_t AD_Buf[ADC_CHANNEL_CNT];
extern uint32_t DMA_CNT;
在主函数中可以借助HAL库提供的HAL_ADC_Start_DMA()函数,开启ADC的DMA功能,指定接收数组为AD_Buf,并指定接收的字符数为ADC_CHANNEL_CNT。
DMA通常用于处理大量数据,但是目前,每秒发送两个数据,数据量很小,没有体现出DMA的特点。虽然只打印了两个数据,但是DMA到底采集了多少数据?已知DMA在AD转换完成以后“搬运”数据,所以我们可以在ADC转化完成的中断函数里做计数。
//AD.c void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if(hadc==(&hadc1)) { DMA_CNT++; } } //main.c main() while (1) { HAL_Delay(1000); for(int i=0;i<ADC_CHANNEL_CNT;i++) printf("CH%d value = %d \n",i,AD_Buf[i]&0xFFF); printf("DMA采集数据的次数是 %d",DMA_CNT); DMA_CNT=0; }
我看到的现象是,DMA_CNT大约是15W,每次两个数据,也就是DMA1秒钟搬运了30W个字节。可以想象,如果不是AD转换速度限制,DMA还可以更快一点.
至于采集过来的AD值到底怎么用,那就是另一个问题了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。