有点郁闷,可能是实验太基础了,写的文章没啥人看。。。这就很尴尬了。那么就当作自己的实验记录吧,以后忘了方便回顾~
还是阿波罗板子,用cubemx实现ADC采集实验,为了系统的学习ADC采集,我打算除了最简单的单通道不扫描的实验,再拓展几个,比如多通道扫描的、MDA的、外部触发的。
单次扫描 | 连续扫描 | |
单通道 | 采样后停止 | 循环采样 |
多通道 | 采集多个通道后停止 | 循环依次采样多个通道 |
实验一:单通道不扫描,在板子上引出的ADC功能是PA5,是ADC1_CH5的管脚,我们开始配置cubemx
我们是用软件控制采集的,生成代码后,我们无需初始化了,直接写操作代码即可。
/*
段落说明 /
/
该部分为ADC转换的软件控制部分,当前实验的是单通道非连续的采样模式。 /
由软件控制开启,采样一次后获取数值,并在下一次采样前开启。 /
/
*/
//获得单通道非连续的ADC值
//u8ADCx: ADC1/ADC2/ADC3
//返回值:转换结果
uint16_t ADC_GetValue(uint8_t u8ADCx)
{
uint16_t _u16Value = 0;
switch(u8ADCx)
{
case 0:
HAL_ADC_Start(&hadc1); //开启ADC转换
HAL_ADC_PollForConversion(&hadc1,50); //表示等待转换完成,第二个参数表示超时时间,单位ms.
//HAL_ADC_GetState(&hadc1) 为换取ADC状态,HAL_ADC_STATE_REG_EOC表示转换完成标志位,转换数据可用。
//HAL_IS_BIT_SET 就是判断转换完成标志位是否设置。
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
_u16Value = (uint16_t)HAL_ADC_GetValue(&hadc1); //读取ADC转换数据,数据为12位。查看数据手册可知,寄存器为16位存储转换数据,
//数据右对齐,则转换的数据范围为0~2^12-1,即0~4095.
}
break;
default:
break;
}
return _u16Value;
}
//获取单通道非连续的转换值,取times次,然后平均
//times:获取次数
//返回值:通道ch的times次转换结果平均值
uint16_t ADC_GetAverage(uint8_t u8ADCx, uint8_t times)
{
uint32_t _u32Value=0;
uint8_t t;
for(t=0;t<times;t++) //求平均值
{
_u32Value += ADC_GetValue(u8ADCx);
}
_u32Value /= times;
printf("ADC1_CH5: %d\r\n", _u32Value);
return (uint16_t)_u32Value;
}
实际上,单通道不连续采样非常简单,只需几步:
1.开始ADC转换,HAL_ADC_Start(&hadc1);
2.等待一段时间完成采样,HAL_ADC_PollForConversion(&hadc1,50);
3.判断标志,采样是否完成,if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
4.获取ADC的值,HAL_ADC_GetValue(&hadc1);
在main函数中循环采集平均值,并且用RGB屏实时刷新电压值。
因为我们采用12位精度采集,那么满量程AD值是2^12=4096.并且基准电压为3.3V,故公式为:
当前电压值(V)=(采集的AD值/4096)*3.3f;
实验结果:随着电压源的动态调整,电压值在0.00~3.30动态浮动,响应速度很快,但是由于我加上了平均值计算,所以从改变0.1V到显示屏的显示值跟上大概需要500ms吧。
结论:跟16位精度的ADC芯片比肯定是不行的,但是对于我当前用到的采集温度值、浓度值的传感器而言是够的。