5 ADC采样
5.1 ADC 采样基本与对齐
ADC采样是模拟量转化为数字量,DAC转换是数字量转化为模拟量。DMA可以用来做内存搬运,好处是不会占用CPU内存。使能ADC采样时,其有单信号采样(Single-ended)和差分信号采样(Differential),要根据原理图上的信号线数量来具体决定。ADC有很多通道1,有的通道支持差分信号采样,有的通道并不支持。
一般的ADC采样器是12位的,会把电压分成4096份,常见的数据对齐方式有左对齐和右对齐两种方法。所以:
- 右对齐:是可以直接读取的。
- 左对齐:读取后还需要除以64(2的4次方)才可以。
5.2 常用的采样模式
部分ADC模式:
- **Clock Prescaler:**时钟预分频。配合时钟树调整适合的ADC采样频率,ADC采样频率太高会不稳定,并且从机(例如sht20传感器)的工作频率可能会跟不上。过高的频率没有意义。
- **Resolution:**分辨率,分辨率越高,逐次逼近的转换时间越长。ADC转换时间=采样时间+逐次逼近转化时间。
- **Scan Conversion mode:**是否开启扫描模式,即一个一个轮询每一个通道。多通道ADC采样时,默认使能。
- **Continues Conversion mode:**选择是否使能连续转换模式。不使能相当于单次转换模式,ADC会将通道的所有转换执行一次。使能的话,相当于连续转换模式,该模式用于常规通道。在连续转换模式下,如果发生软件或者硬件触发,ADC会执行所有常规通道的转换,随后会自动重启并继续执行每一个通道的转换。若想使用ADC+DMA的话,必须先使能连续转换模式。
- **Discontinuous Conversion Mode:**不连续序列转换模式,配置ADC规则组转换序列的不连续方式。这里的不连续含义是指每次触发进行一个子组的转换,跟Continuous Conversion Mode的连续含义不一样。例如使能了该配置,该参数的下方就立马出现Number Of Discontinuous Conversions,如果它设为2,且ADC1使能了通道1,2,5,7,10,11的话,那么第一次触发ADC1采样时,就会采样通道1与通道2的值,再一次触发ADC1采样的话,就会采样通道5与通道7值,如此类推。值得注意的是,Continuous Conversion Mode与Discontinuous Conversion Mode不能同时使能,两者不能共存。他会将n个通道分为一组,一次只采样一组。
- **End of Conversion Selection:**结束转换的选择,End of single conversion(EOC) 与 End of sequence of conversion(EOS)两种选择。这两个事件会分别触发中断与DMA。一般选择EOS,等所有通道转换完毕后,产生中断后将全部数据取出来,或者使用DMA将全部数据取出来。
- **Overrun behaviour:**溢出处理行为
- **Low Power Auto Wait:**低功耗自动等待,需要低功耗时候使用。
- **Enable Regular Conversions:**规则转换使能,一般都使能,即使用规则的方式进行ADC转换。
- **Enable Regular Oversamping:**使能规则过采样,过采样的时候无法使用对齐模式。
ps:number of conversion:一定要根据ADC采样的个数来调整,他会决定我们分配几个RANK来存储数据。
5.3 ADC采样声音光强例程
CubeMX的配置:
//添加如下代码到adc.h
extern int adc_sampel_lux_mic(uint32_t *lux, uint32_t *mic);
//添加如下代码到adc.c
enum
{
LIG_ADC,
MIC_ADC,
MAX_ADC,
};
int adc_sampel_lux_mic(uint32_t *lux, uint32_t *mic)
{
uint8_t i;
uint32_t timeout=0xffffff;
for(i=0; i<MAX_ADC; i++)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, timeout);//等待转换完成
if (i == LIG_ADC)
{
*lux = HAL_ADC_GetValue(&hadc1);
}
if (i == MIC_ADC)
{
*mic= HAL_ADC_GetValue(&hadc1);
}
HAL_Delay(10);
}
HAL_ADC_Stop(&hadc1);
return 0;
}
5.4 ADC采样常用函数
//开启adc1的ADC采样
HAL_ADC_Start(&hadc1);
///查询函数,查询EOC标志位。每次采样,CPU在这里都要等待采样完成才能进行下一步,这段时间CUP没有干其他事,所以降低了CUP使用率
HAL_ADC_PollForConversion(&hadc1, timeout);
//获取ADC采样的值
HAL_ADC_GetValue(&hadc1);
//停止ADC采样
HAL_ADC_Stop(&hadc1);