前言
最近是有一个产品用到了ADC,使用的是STM32L051 芯片,使用 STM32CubeMX 生成的代码,本来以为简简单单,但是在调用 HAL ADC校准函数的时候遇到一个问题有点疑问,度娘一下也没有找到解答,还是经过翻阅了一些资料才得到答案,特此来记录一下。
前言
一、ADC 配置说明
1.1 ADC 采样步骤
二、ADC 校准
2.1 什么是ADC校准?
2.2 为什么 ADC 使用需要校准?
2.2 什么时候使用 ADC 校准?
2.3 ADC 采样每次都需要校准吗?
三、HAL 库校准函数
3.1 单端校准和差分校准
3.2 不同系列的校准函数
3.3 更多的校准模式
结语
一、ADC 配置说明
详细的 STM32 ADC 的使用,本文不做过多说明,这个网上一搜一大把。
本文使用的是 HAL 库,直接用 STM32CubeMX 生成的代码,ADC 的配置步骤在我的另外一篇博文:
STM32L051测试 (一、使用CubeMX生成工程文件 — ST系列芯片通用) 中有过介绍:
对于其他不同型号,F1,F4 等,配置大同小异。
1.1 ADC 采样步骤
使用 CubeMX 可以大大简化工程师的使用步骤,这里直接说明一下对于使用 CubeMX 来说的 ADC 采样步骤。
ADC 采样使用步骤简单来说如下几步(以单次采样为例说明):
配置 ADC 工作参数:包括基本配置,和通道相关参数;(STM32BubeMX 自动生成代码 MX_ADC_Init())
ADC_MSP 初始化:包括初始化 ADC 的时钟、GPIO 引脚、 DMA 和 NVIC 相关的设置;(STM32BubeMX 自动生成代码HAL_ADC_MspInit())
校准!使用前务必校准!;(大部分型号需要我们在程序中自己调用代码,某些型号不需要校准,后面会说明HAL_ADCEx_Calibration_Start())
启动 ADC 转换;(我们在程序中自己写代码,调用库函数HAL_ADC_Start())
等待转换完成;(我们在程序中自己写代码,调用库函数HAL_ADC_PollForConversion())
获取结果;(我们在程序中自己写代码,调用库函数HAL_ADC_GetValue())
二、ADC 校准
在上面的步骤中,我把校准用了红色字体强调说明,因为在 ADC 的使用中必须进行校准 ,否者自己设计的电路得到的结果可能与实际的会有不同的偏差。
2.1 什么是ADC校准?
STM32 的 ADC 校准一般有 参考电压校准 和 增益校准。
参考电压校准:
先测量 ADC 参考电压的实际值,然后将该值与预设的参考电压进行比较,得到参考电压的偏差,最终通过校准将其校正的方式叫做 参考电压校准 ,其目的是为了准确测量 ADC 的输入信号。
叫做增益校准:
通过测量内部基准电压和 ADC 输入信号的幅值之间的比例关系,校准 ADC 增益的方式 叫做增益校准,其目的是确保 ADC 输出的数值与输入信号的幅值之间具有良好的线性关系,为了准确的转换 ADC 输入信号。
ADC 校准的目的是为了消除 ADC 的偏移误差和增益误差,从而提高测量精度。
2.2 为什么 ADC 使用需要校准?
这个为什么要用 ADC 校准,我这里也只能简单的说明一下。
这个就像芯片生产过程制造中的差异化一样,ADC部分也存在一些差异化(虽然很小),其参考电压、偏置电压、增益等参数可能存在一些不确定性和漂移,这些参数的变化会导致 ADC 的测量结果产生误差。
就想上面介绍什么是 ADC 校准最后说的,为了提高测量精度,消除 ADC 的偏移误差和增益误差,所以在使用 ADC 采样的时候都需要进行 ADC 校准。
2.2 什么时候使用 ADC 校准?
在我们使用 CubeMX 软件的时候,ADC 的配置,初始化等大部分程序都是由软件给我们生成的,我们都无需过多干预,但是校准是不会给我们自动加入程序的,这就需要我们 手动的添加。
在程序中,我们只需要保证在 ADC 开始使用前(ADC 转换函数调用前),ADC 初始化后,进行校准即可。
2.3 ADC 采样每次都需要校准吗?
这个问题并不能直接回答,我们先来了解一下 调用了 HAL 校准函数以后,STM32 是怎么处理的。
调用 STM32 校准函数以后, 校准的结果会被保存在相应的寄存器中,以供后续的ADC测量使用。
由上面这句话可以知道,校准过后的结果会被保存起来,每次 ADC 使用的时候会从该寄存器中取校准数值,所以说一般来说,只要你上电校准过一次,就行了。
但是!注意,校准过后不用再校准是基于你的 ADC 设置没有改变,产品的工作环境稳定的前提下!
如果采样过程中你改变了 ADC 的环境,比如参考电压,采样时间等一些配置,或者一些低功耗产品,需要进行休眠,那么还是需要进行再次校准的。
还有一点,就是产品的工作环境,比如产品的环境比较恶劣,温度啊,干扰啊之类的,那么还是有必要在 ADC 的使用过程中进行定期校准的。
当然,如果我们本着严谨的作风,在产品上直接使用定期校准那也是没问题的。
三、HAL 库校准函数
上面理论的东西介绍完了,那么我们就来简单做个测试,其实我使用过程中的小疑问也是在使用过程中遇到的。
我们都知道 ADC 的校准函数为:HAL_ADCEx_Calibration_Start()
但是当我使用这个函数时候,居然出错了,如下图:
提示调用的参数太少了(确定出错是我编译过后发现的),提示函数调用参数太少了,这就奇怪了,于是我进入看看函数原型:
这里可以看到,怎么多了一个参数(上面确实有解释说明,应该填写什么),但是当时我第一反应是看一下这个参数在函数中是怎么用的,于是搜索了一下SingleDiff 这个参数,发现在HAL_ADCEx_Calibration_Start 这个函数中根本没用到这个参数?
为了搞清楚,我还去度娘问了下,发现根本没有关于这个参数的说明,所有的 STM32 ADC 有关的帖子文章,都是一样的, ADC 是啥啥啥,什么模式,解释一下,怎么用等等巴拉巴拉的……
3.1 单端校准和差分校准
其实上面的注释说明就是,这个参数就是用来选择使用哪种校准方式:单端校准ADC_SINGLE_ENDED 和 差分校准ADC_DIFFERENTIAL_ENDED。
后来就去翻阅手册资料,下面是查到的说明,这里给大家参考一下:
单端校准:
单端校准是指对 ADC 的单个输入通道进行校准,主要校准项包括偏移误差和增益误差。
单端校准主要针对单端输入的情况,通过比较参考电压和输入信号之间的误差,校准ADC的增益和偏置电压。在单端输入的情况下,参考电压和输入信号之间存在可能的偏差,这会导致ADC采样结果的偏移和误差。为了解决这个问题,可以使用单端校准来校正 ADC 的增益和偏置电压。单端校准的过程是使用一个已知的模拟信号来输入 ADC,然后比较采样结果与该模拟信号的期望值,得到增益和偏置电压的偏差值,然后通过校准将其校正。
单端校准时,ADC将使用内部参考电压作为参考电压,对每个输入通道进行测量,计算出偏移误差和增益误差,并将这些误差保存在相应的寄存器中。
差分校准:
差分校准是指对 ADC 的差分输入通道进行校准,主要校准项也包括偏移误差和增益误差。
差分校准主要针对差分输入的情况,通过比较参考电压和输入信号之间的误差,校准 ADC 的差分增益和偏置电压。在差分输入的情况下,差分增益和偏置电压的偏差也会导致 ADC 采样结果的偏移和误差。为了解决这个问题,可以使用差分校准来校正 ADC 的差分增益和偏置电压。差分校准的过程是使用一个已知的差分输入信号来输入 ADC,然后比较采样结果与该差分输入信号的期望值,得到差分增益和偏置电压的偏差值,然后通过校准将其校正。
差分校准时,ADC 将使用内部参考电压作为参考电压,并将两个输入通道的差值作为输入信号进行测量,计算出偏移误差和增益误差,并将这些误差保存在相应的寄存器中。
3.2 不同系列的校准函数
所以在我们使用不同的系列的 HAL 库的时候,虽然校准函数都是HAL_ADCEx_Calibration_Start ,但是也有着一些参数的区别。
对于我目前使用的 STM32L051 来说,HAL校准函数使用的示例如下:
HAL_ADCEx_Calibration_Start(&hadc1,ADC_SINGLE_ENDED);
大部分情况下直接选择单端校准ADC_SINGLE_ENDED就行了,差分校准还需要外部电路的支持。
对于 STM32F 系列的来说,HAL校准函数使用的示例如下:
HAL_ADCEx_Calibration_Start(&hadc1);
......
3.3 更多的校准模式
对于更多的系列,因为自己目前没有用到,我也没有一个一个去找,但是通过资料了解到,对于有些型号,比如 STM32F4 系列的,ADC的校准由硬件自动执行,不需要额外的调用 ADC 校准函数。
虽然我没有去试,但是这个硬件自动执行校准在 STM32CubeMX 中应该可以选择,因为他需要使能,在程序中的体现为:
hadc1.Init.AutoCalibration = ENABLE;
而且在 STM32 系列中,还有支持额外校准模式(共模校准、差分共模校准)的MCU,具体哪个我也不知道,这样的MCU,在使用校准函数HAL_ADCEx_Calibration_Start的时候又多一个参数。但是这里可以告诉大家在遇到的时候不要慌张,这里给出示例。
共模校准:
/*
使能共模校准
*/
HAL_ADCEx_Calibration_Start(&hadc, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
/* 等待共模校准完成 */
while (HAL_ADCEx_Calibration_GetState(&hadc) != HAL_ADC_CALIBRATION_STATE_COMPLETED);
差分共模校准:
/*
使能差分共模校准
*/
HAL_ADCEx_Calibration_Start(&hadc, ADC_CALIB_OFFSET, ADC_DIFFERENTIAL_ENDED);
/*
等待差分共模校准完成
*/
while (HAL_ADCEx_Calibration_GetState(&hadc) != HAL_ADC_CALIBRATION_STATE_COMPLETED);
上面的 ADC_CALIB_OFFSET 是指定进行偏置校准。
结语
好了,本文是自己在使用过程中遇到的一个小问题,但确实直接度娘找不到我需要的答案,所以自己花费了些功夫查了一下,当然也记录说明一下,希望对大家能够有帮助!