经过几天的反复测试,基于STM32F030Disco核心板的ADC实验终于基本成功,为什么说基本成功呢,是因为我在实验中开通了四个通道(1~4),不知为何第4个通道却读不到正确的数据。
通过这次实验,我对STM32的ADC转换有了初步的了解,实验了轮询和DMA模式,鉴于时间关系,中断模式暂未实验。
首先是在STM32CubeMX下配置了ADC,开通了IN1~IN4通道,开始还不知道要添加DMA,是在实验完轮询模式之后才知道多通道必须通过DMA模式来获得数据。
通过STM32CubeMX生成代码,然后就找如何读取数据的代码,从网上搜索了不少代码,反复摸索测试并观看结果,最后才知道要先用HAL_ADC_Start()函数开始转换、然后用HAL_ADC_PollForConversion()函数等待转换完成、之后再用HAL_ADC_GetValue()函数获得结果,最后用HAL_ADC_Stop()函数停止转换。弄清楚这些步骤花费了不少时间,然而在后面我将固件库文件拷贝出来,并逐段翻译阅读后才清楚的,如果早点做这步工作肯定可以节省不少时间。
我是通过一个连接在3.3V电源上的10K电位器给通道IN1信号的,通过每隔0.1V读取一次转换数据,然后将这些数据填在EXCEL表格中,生成折线图来观察电压值与转换数据的关系。下表是手工测量记录的数据,由于数据跳动厉害,记录的数据会有一些误差。
制成折线图之后可以发现转换数据与电压值在接近两端时不是直线。
开始我先配置了一条直线,试图找到其数学模型,以便从获得的转换数据计算出实际电压(见下图)。
反复试验了多次,最后还是通过分段计算的办法来获得比较接近实际的电压值。下面是读取和转换数据的代码:
void Get_ADC_Val(uint8_t id){uint8_t i;HAL_ADC_Start_DMA(&hadc,(uint32_t *) ADC_ConvertedValueLocal,4); HAL_ADC_ConvHalfCpltCallback(&hadc); for ( i=0; i<4; i++ ) //分别处理四路ADC{ if(ADC_ConvertedValueLocal<600) adc_val[id] = ADC_ConvertedValueLocal*10/214; else if(ADC_ConvertedValueLocal<1200) adc_val[id] = (ADC_ConvertedValueLocal-600)*10/122+28; else if(ADC_ConvertedValueLocal>3400) adc_val[id] = (ADC_ConvertedValueLocal-3400)*10/199+265; else adc_val[id] = (ADC_ConvertedValueLocal-1200)*10/117+77; } HAL_ADC_Stop_DMA(&hadc); }
下图是实验过程。
通过上网搜索才知道要添加硬件滤波和软件滤波才能平滑数据的抖动,由于是简单的实验,硬件滤波就暂时未加,先通过软件滤波来消抖,办法是每隔0.1秒读取一次转换数据并存放在数组中,每秒将10次数据的平均值显示出来,这样抖动就稍微好一点。
此帖出自开发板测评专版论坛