1. 从一次“诡异”的ADC读数漂移说起
最近在调一个基于STM32H743的项目,需要用到它的ADC采集一个高精度的电压信号。硬件设计上该做的都做了,基准电压用的是外部的精密基准源,信号调理电路也中规中矩。软件上,我按照以往在F1/F4系列上的习惯,初始化ADC,配置好通道和采样时间,然后调用 HAL_ADC_Start() 启动转换,在需要读数的时候调用 HAL_ADC_PollForConversion() 等待并获取结果。一开始跑起来,数据看起来挺正常的,我也就没多想。
但是,问题在设备运行了几个小时,甚至隔夜上电后再测试时,开始浮现了。我发现ADC的读数会出现一个缓慢的、系统性的漂移。比如,我输入一个固定的1.000V电压,刚上电时读数是1.001V,还算准确;运行几个小时后,可能就变成了1.010V;第二天冷启动,可能又回到了1.002V。这个误差虽然不大,但对于我这个要求高精度测量的应用来说,是完全不可接受的。我一开始怀疑是温漂,但用手摸芯片温度变化并不大,而且漂移的方向和幅度似乎没有严格的温度相关性。我又检查了电源、基准源,甚至怀疑是PCB布局的问题,折腾了一圈,硬件上都没找到确凿的证据。
直到我把目光投向了软件,特别是ADC的校准环节。STM32H7系列的ADC内部有一个校准机制,用于修正ADC内核的偏移和增益误差,这个校准值对精度至关重要。我翻看代码,发现我确实在初始化流程里调用了 HAL_ADCEx_Calibration_Start() 这个函数。但仔细一看调用位置,我心里“咯噔”一下:我把它放在了 HAL_ADC_Start() 之后,也就是在ADC已经启动工作的状态下,试图去执行校准。这就是一切问题的根源。HAL_ADCEx_Calibration_Start() 这个函数有个非常严格的前提条件,而我在匆忙中忽略了它,结果就是校准非但没有成功,反而可能引入了不确定的误差,导致了后续读数诡异的漂移。今天,我就把这个坑从头到尾刨开,把 HAL_ADCEx_Calibration_Start() 的正确调用时机和背后的原理讲透,让你彻底避开这个陷阱。
2. 刨根问底:为什么校准必须在ADC禁用状态下进行?
要理解为什么不能在工作时校准,我们得先看看 HAL_ADCEx_Calibration_Start() 这个函数内部到底干了什么。虽然原始文章里贴了一部分代码,但我们结合数据手册和库函数的逻辑,可以更形象地理解这个过程。
你可以把STM32H743的ADC模块想象成一个非常精密的电子秤。这个秤出厂时,它的“零位”(偏移)和“刻度”(增益)可能有一点点微小的偏差。校准过程,就是给这个秤一个已知的“标准砝码”(内部产生的基准电压),让它自己测量一下,然后计算出偏差值,并把这个修正值存起来。以后每次称重(转换)时,都自动用这个修正值来补偿,从而得到更准确的结果。
那么,校准这个精密操作,需要一个绝对稳定、安静的环境。试想一下,如果这个电子秤正在不停地称东西(ADC正在进行转换),你突然把标准砝码放上去让它自校准,会怎样?首先,秤的传感器和电路都处于动态工作状态,不是静止的基准状态,这时候测出来的“零位”和“刻度”本身就是乱的。其次,校准过程需要ADC内核执行一系列特定的内部操作,切换内部开关和参考源,这些操作如果和正常的采样转换时序冲突,轻则校准无效,重则可能扰乱ADC的正常工作,甚至导致硬件错误或锁死。
所以,ST的工程师在函数说明里第一句就加粗强调:“Calibration prerequisite: ADC must be disabled.” 这不是一个建议,而是一个硬件强制要求。我们来看函数内部的执行步骤,它首先会尝试调用 ADC_Disable(hadc) 来禁用ADC。如果ADC当前是使能状态(比如你已经调用了 HAL_ADC_Start),这个禁用操作会失败,函数会直接返回 HAL_ERROR,校准流程根本不会开始。这就是最直接的失败情况。但更隐蔽的危险是,如果你在ADC启动后、转换间歇期某个“巧合”的时间点调用,可能禁用成功了,但此时ADC的内部状态可能并不干净,残留的电荷或未完成的时序会导致校准结果不可靠,这就是我遇到的读数漂移问题的潜在原因。
3. 典型错误场景与你的代码可能正踩中的坑
明白了原理,我们来看看在实际编程中,哪些地方容易出错。我把自己和身边朋友常犯的几种错误整理出来,你看看有没有中招。
场景一:“初始化包”里的顺序错误 这是最常见的一种。我
332




被折叠的 条评论
为什么被折叠?



