1. 工业温度测量方案的整体设计思路
工业现场和HVAC系统里的温度测量,跟消费电子完全是两码事。消费电子测个环境温度,±1℃的误差没人跟你计较;但工业场景下,锅炉出水温度、冷库库温、管道介质温度,往往要求±0.1℃甚至更高的精度,而且传感器可能离主控板十几米远,现场电磁环境还特别脏——变频器、接触器、大功率电机全在附近。这种条件下,用MCU自带的12位ADC直接采,基本等于开玩笑。
我这次做的方案,核心就是ADS122U04IPWR这颗24位ΔΣ ADC + STM32F407VGT6主控的组合。ADS122U04是TI的一款低功耗、四通道、24位ΔΣ型ADC,内置PGA、基准电压源和激励电流源,UART接口通信,特别适合RTD、热电偶、热敏电阻这类温度传感器的精密采集。STM32F407VGT6则是ST的经典F4系列MCU,168MHz主频、1MB Flash、192KB SRAM,资源足够跑协议栈、做数据处理和显示交互。
为什么选这个组合?先说ADC。工业温度测量最常用的传感器是PT100/PT1000铂电阻(RTD),它的阻值随温度变化,0℃时PT100是100Ω,每升高1℃阻值增加约0.385Ω。要分辨0.1℃的变化,就得分辨0.0385Ω的阻值变化。如果用1mA激励电流,对应电压变化只有38.5μV。12位ADC在3.3V量程下,1LSB约0.8mV,根本分辨不出来。24位ΔΣ ADC在同样量程下,理论分辨率可以到0.2μV级别,配合PGA放大,轻松覆盖这个需求。
再说MCU。STM32F407VGT6的UART外设丰富,跟ADS122U04对接很方便;同时它有足够的运算能力做数字滤波、线性化查表、温度补偿。如果换成低端MCU,光一个多阶FIR滤波就能把CPU吃满,更别说还要跑Modbus、驱动LCD了。
整个方案的信号链是这样的:PT100传感器 → 三线制或四线制接法 → ADS122U04的激励电流源和模拟输入 → 内部PGA放大 → 24位ΔΣ调制 → 数字滤波 → UART输出 → STM32F407解析 → 温度换算 → 显示/上传。
注意:ADS122U04是UART接口,不是SPI。很多同行第一次用会习惯性找SPI引脚,结果发现对不上。它的UART是标准异步串口,波特率最高支持到1Mbps,实际用115200或230400就够。
这个方案适合谁?做工业仪表、HVAC控制器、PLC模拟量模块、温度变送器的嵌入式工程师,以及需要高精度温度采集但不想外挂独立变送器的项目。如果你只是测个室温做风扇调速,那用NTC加热敏电阻分压进MCU的ADC就够了,没必要上这套。
2. ADS122U04IPWR的核心细节与配置要点
2.1 芯片内部结构决定了外围电路怎么搭
ADS122U04的内部框图值得仔细看一遍。它有两个差分输入通道(或者四个单端输入),一个低噪声PGA(增益1到128可调),一个24位ΔΣ调制器,一个数字滤波器,还有两个可编程激励电流源(10μA到1.5mA)。基准电压可以选择内部2.048V,也可以外接。
对于PT100测量,我通常用比例式测量法:让激励电流流过PT100和一颗精密参考电阻串联,ADC测量PT100两端电压,同时用参考电阻两端电压作为基准。这样激励电流的温漂和长期漂移会被抵消掉,因为它是比值关系。具体接法是:ADS122U04的IDAC1输出激励电流,先流过PT100,再流过参考电阻RREF到地。ADC的差分输入接PT100两端,基准输入接RREF两端。
RREF怎么选?假设用1mA激励电流,PT100在0℃时100Ω,在最高测量温度比如200℃时约175.86Ω。RREF上的电压要满足ADC基准输入范围。ADS122U04的基准输入范围是0.75V到VREF(VREF为模拟电源)。如果模拟电源用3.3V,RREF选1.5kΩ,1mA电流下压降1.5V,在合理范围内。同时PT100上最大压降175.86mV,经过PGA增益8倍后是1.4V,也接近基准电压,能充分利用ADC量程。
提示:RREF必须用低温漂的精密电阻,至少0.1%精度、25ppm/℃温漂。普通1%厚膜电阻的温漂能到200ppm/℃,直接毁掉测量精度。
2.2 寄存器配置不是随便写几个值就行
ADS122U04有四个配置寄存器,通过UART命令读写。上电后第一件事是发RESET命令(0x06),然后发START/SYNC命令(0x08)让它开始转换。配置寄存器0控制多路复用器、增益、数据速率;寄存器1控制工作模式、转换模式、基准选择、滤波器;寄存器2控制IDAC电流大小、IDAC路由、温度传感器选择;寄存器3控制IDAC使能、DRDY模式等。
我常用的配置组合是这样的:MUX选AIN0和AIN1作为差分输入,增益8,数据速率20SPS(每秒20次采样),连续转换模式,内部基准关闭(用外部RREF),IDAC电流1mA,IDAC1路由到AIN0对应的引脚。20SPS配合内置的50/60Hz陷波滤波器,能有效抑制工频干扰,这在工业现场特别重要。
数据速率的选择有个权衡:速率越高,噪声越大。ADS122U04在20SPS、增益8时的有效位数(ENOB)能到21位左右,折算到电压分辨率约0.5μV。如果提到2000SPS,ENOB会掉到17位左右,分辨率降到约8μV。对于温度测量,20SPS完全够用,因为温度本身变化就慢,没必要追求高速。
2.3 三线制和四线制接法的取舍
PT100的引线电阻是个绕不开的问题。假设传感器离主控板10米,用0.5mm²铜线,单根线电阻约0.35Ω。两线制接法下,这个电阻直接叠加到PT100阻值上,引入约0.9℃的误差。三线制能补偿掉大部分引线电阻,前提是三根线材质长度一致。四线制最准,完全消除引线电阻影响,但多一根线,成本高一点。
我的做法是:短距离(<5米)用三线制,长距离或高精度场合用四线制。ADS122U04支持四线制,因为它的IDAC可以路由到单独的引脚,激励电流走一对线,测量走另一对线。三线制的话,需要两个IDAC分别给两根引线提供电流,然后测量第三根线和其中一根激励线的电压差。
实际接线时有个坑:ADS122U04的模拟输入引脚有ESD保护二极管,输入电压不能超过模拟电源或低于地。如果传感器接线松动或者断线,输入可能浮空到不确定电平,导致读数乱跳。我在每个模拟输入引脚对地加了一颗100nF电容,对模拟电源加了一颗1nF电容,既滤波又提供一定的电荷缓冲。
3. STM32F407VGT6与ADS122U04的对接实操
3.1 硬件连接与电平匹配
ADS122U04的UART引脚是TX和RX,直接跟STM32F407的UART引脚交叉连接即可。ADS122U04的IO电压范围是2.0V到5.5V,STM32F407的IO是3.3V,直接对接没问题。但要注意:ADS122U04的UART是TTL电平,不是RS232电平,别接错。
我用的STM32F407VGT6的UART2,PA2是TX,PA3是RX。ADS122U04的TX接PA3,RX接PA2。波特率设115200,8位数据,无校验,1位停止位。ADS122U04的UART是标准异步串口,不需要流控。
电源方面,ADS122U04的模拟电源AVDD和数字电源DVDD可以都接3.3V,但最好用磁珠或电感隔离一下,避免数字噪声串到模拟部分。我在AVDD引脚旁边放了10μF钽电容和100nF陶瓷电容,DVDD旁边放了1μF和100nF。基准输入REF0和REF1之间也放了100nF电容。
注意:ADS122U04的DRDY引脚在连续转换模式下会周期性拉低,表示新数据就绪。我把它接到STM32F407的PB0,配置为外部中断下降沿触发。这样MCU不用轮询,收到中断再去读数据,效率高很多。
3.2 STM32端UART驱动与命令封装
STM32F407的HAL库用起来很方便,但UART接收ADS122U04的数据时有个细节:ADS122U04的数据是24位,分3个字节发送,高位在前。读数据命令是0x10,发完之后它会连续输出3个字节。如果用HAL_UART_Receive,要确保接收缓冲区够3个字节,并且超时时间设合理。
我封装了几个基本函数:ads122u04_send_command(uint8_t cmd)负责发单字节命令;ads122u04_read_data(int32_t *data)负责发0x10然后读3字节并拼成24位有符号数;ads122u04_write_register(uint8_t reg, uint8_t value)负责写配置寄存器。写寄存器命令是0x40 | (reg << 2),后面跟要写的值。
24位数据的符号扩展要注意:ADS122U04输出的是二进制补码,最高位是符号位。如果读到的24位数据最高位是1,表示负数,需要扩展到32位。代码里这样处理:
int32_t raw = (buf[0] << 16) | (buf[1] << 8) | buf[2]; if (raw & 0x800000) { raw |= 0xFF000000; }这个细节看起来简单,但我在早期调试时忘了符号扩展,结果负温度全部读成很大的正数,排查了半天。
3.3 数据读取时序与DRDY中断处理
ADS122U04在连续转换模式下,每次转换完成会拉低DRDY,持续约一个时钟周期后释放。STM32F407的外部中断配置为下降沿触发,在中断服务函数里置一个标志位,主循环检测到标志位后去读数据。不要在中断里直接读UART,因为UART读取可能耗时较长,阻塞其他中断。
主循环里读数据的流程是:检测标志位 → 发0x10命令 → 读3字节 → 拼成24位 → 清除标志位。整个过程在115200波特率下大约耗时300μs,20SPS的转换周期是50ms,时间绰绰有余。
如果DRDY一直不拉低,说明ADC没在转换。检查START/SYNC命令是否发了,或者配置寄存器里的转换模式是否设成了连续模式。我遇到过一种情况:配置寄存器写完之后忘了发START命令,结果DRDY一直高,读不到数据。后来在初始化流程里固定加上START命令就好了。
4. 温度换算与精度保障的实操细节
4.1 从ADC码值到电阻值再到温度
拿到24位ADC码值后,第一步是换算成电压。公式是:V = (code / 2^23) × VREF / PGA。注意ADS122U04是24位,但满量程是2^23-1(正半轴)和-2^23(负半轴),所以除以2^23。VREF是参考电阻上的电压,PGA是增益。
然后算PT100阻值:RPT = V / IIDAC。IIDAC是激励电流,我设的1mA。但实际电流有误差,所以更准的做法是用参考电阻来反推:RPT = RREF × (code_PT / code_REF)。不过ADS122U04的基准输入就是RREF两端,所以code_REF对应满量程,code_PT对应PT100电压,直接比值就行。
得到阻值后,用Callendar-Van Dusen公式换算温度。0℃以上时:R(T) = R0 × (1 + A×T + B×T²),其中R0=100Ω,A=3.9083e-3,B=-5.775e-7。反解T需要用二次方程求根公式。0℃以下时公式更复杂,多一个C项,一般工业场合很少测到零下,我就没实现。
实际代码里,我建了一个阻值到温度的查找表,每隔1Ω存一个温度值,然后用线性插值。这样比实时算二次方程快,精度也够。查找表覆盖80Ω到200Ω,对应约-50℃到266℃,步长1Ω,表大小121个条目,放Flash里占不了多少空间。
4.2 噪声抑制与数字滤波
ADS122U04内置的50/60Hz陷波滤波器在20SPS时自动生效,能抑制工频干扰。但工业现场还有变频器产生的高频噪声,光靠ADC内部滤波不够。我在STM32端加了一级滑动平均滤波,窗口大小16,相当于把20SPS降到1.25SPS的有效输出速率。温度变化慢,这个速率完全够。
滑动平均的实现很简单:维护一个16元素的环形缓冲区,每次新数据进来替换最老的数据,然后求平均。注意用int32_t累加,避免16位溢出。我试过用中值滤波,但中值滤波对脉冲噪声好,对连续噪声不如平均滤波,而且计算量大,F407跑起来虽然没问题,但没必要。
提示:如果现场噪声特别大,可以在ADS122U04的模拟输入前端加RC低通滤波。R用10Ω,C用1μF,截止频率约16kHz,对工频和高频噪声都有抑制。但R不能太大,否则会影响激励电流的稳定性。
4.3 校准:两点校准比单点校准靠谱
任何高精度测量都离不开校准。我的做法是两点校准:用一个高精度电阻箱或者标准PT100,分别在0℃(冰水混合物)和100℃(沸水)两个点读取ADC码值,然后计算增益误差和偏移误差。
具体操作:先把传感器放进冰水混合物,等读数稳定后记录码值code0;再放进沸水,记录code100。理想情况下code0对应100Ω,code100对应138.51Ω。实际码值和理想值有偏差,用线性拟合求出实际增益和偏移。校准系数存在STM32的Flash里,每次上电读取。
单点校准只能修正偏移,不能修正增益。如果PGA增益或RREF有误差,单点校准后其他温度点还是不准。两点校准能同时修正偏移和增益,精度提升明显。我实测下来,两点校准后0到100℃范围内误差能控制在±0.05℃以内。
校准周期方面,建议每半年或一年做一次。如果RREF用的是低温漂电阻,校准周期可以放长。但传感器本身会老化,PT100的长期漂移虽然小,但工业场合用几年后还是会有变化,定期校准是必要的。
5. 常见问题排查与避坑经验
5.1 读数跳动大、不稳定
这是最常见的问题。原因可能有几个:一是激励电流太小,PT100上的电压信号弱,容易被噪声淹没。1mA已经算比较大了,再大功耗和自热效应会明显。二是模拟输入前端没有滤波,高频噪声直接进ADC。三是接地没处理好,模拟地和数字地混在一起。
我的排查顺序是:先用示波器看ADS122U04模拟输入引脚上的波形,如果有明显的高频毛刺,加RC滤波。然后检查地平面,模拟部分和数字部分用0Ω电阻或磁珠单点连接。最后看电源纹波,AVDD上如果有超过10mV的纹波,加LC滤波。
还有一个容易被忽略的点:ADS122U04的基准输入引脚REF0和REF1之间必须接电容,我用的100nF。如果不接,基准电压会随转换过程波动,导致读数不稳。
5.2 温度值偏差大、线性度差
如果读数稳定但温度值整体偏了,先检查RREF的精度和温漂。普通电阻的温漂能到几百ppm,在温度变化的环境里,RREF阻值变了,基准就变了,所有读数都偏。换成25ppm/℃的精密电阻,问题基本解决。
如果线性度差,比如低温段准高温段不准,检查PT100的接线方式。两线制接法下,引线电阻在低温段占比大,高温段占比小,导致非线性。改成三线制或四线制就能解决。
还有一种情况:PGA增益设得太高,输入信号接近满量程,非线性误差增大。ADS122U04在增益8时的非线性约10ppm,增益128时能到50ppm。如果精度要求高,增益别设太大,留足余量。
5.3 UART通信失败或数据错位
UART通信问题通常出在波特率不匹配或时序不对。ADS122U04上电后需要一段时间稳定,我一般延时100ms再发命令。如果上电就发,它可能还没准备好,命令丢了。
数据错位的话,检查读数据命令后是否等了足够时间。ADS122U04收到0x10命令后,需要几个时钟周期才开始输出数据。如果STM32的接收超时设太短,可能只收到部分字节。我把超时设成10ms,足够覆盖3字节的传输时间。
还有一种情况:DRDY中断和UART读取冲突。如果DRDY中断触发太频繁,主循环来不及读,数据会覆盖。20SPS下50ms一次中断,F407跑168MHz,处理时间完全够。但如果数据速率设到2000SPS,0.5ms一次中断,就要考虑用DMA接收UART数据了。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查方法 | 解决措施 |
|---|---|---|---|
| 读数跳动大 | 前端无滤波、地处理不当 | 示波器看输入波形 | 加RC滤波、单点接地 |
| 温度整体偏差 | RREF精度差、温漂大 | 测量RREF实际阻值 | 换0.1% 25ppm电阻 |
| 线性度差 | 两线制引线电阻影响 | 测量引线电阻 | 改三线制或四线制 |
| UART无响应 | 上电延时不够、波特率错 | 示波器看TX波形 | 延时100ms、核对波特率 |
| 数据错位 | 超时太短、DRDY冲突 | 逻辑分析仪抓时序 | 加大超时、用DMA |
| DRDY不拉低 | 未发START命令、配置错 | 读配置寄存器 | 补发START、检查配置 |
6. 工业现场部署的几点个人体会
这套方案我在几个HVAC项目和工业温度变送器上实际用过,说几点文档里不会写的体会。
第一,ADS122U04的UART接口在长距离传输时不如SPI可靠。UART是异步的,没有时钟线,长距离传输时如果地电位有差异,容易误码。如果ADS122U04离STM32超过30cm,建议用SPI版本的ADS122S04,或者把UART转成差分信号。我有个项目里ADS122U04和STM32在同一块板上,距离5cm,115200波特率跑得很稳,没出过误码。
第二,激励电流的自热效应要算一下。1mA流过PT100,功耗是I²R = 0.001² × 100 = 0.1mW。PT100的热阻大概在10℃/W到50℃/W之间,0.1mW对应0.001℃到0.005℃的温升,可以忽略。但如果用1.5mA,功耗翻倍到0.225mW,温升0.002℃到0.01℃,还是很小。不过如果测的是很小的温度传感器,比如薄膜PT100,热阻可能更大,就要考虑降低激励电流或者用脉冲激励。
第三,STM32F407的UART中断优先级要设对。如果DRDY中断优先级比UART高,DRDY触发后主循环去读UART,但UART中断可能被DRDY中断打断,导致接收不完整。我把UART中断优先级设得比DRDY高,确保接收不被打断。这个细节在HAL库的默认配置里不会帮你处理好,得自己调。
第四,校准用的冰水混合物和沸水有讲究。冰水混合物要是冰和水共存的状态,不能只有冰或只有水。沸水的温度跟气压有关,高原地区沸点不到100℃,要用标准温度计修正。我一般用高精度温度计做参考,而不是依赖冰点和沸点。
第五,ADS122U04的配置寄存器写完要回读验证。UART通信偶尔会受干扰,写进去的值可能不对。我在初始化流程里加了回读验证,如果读回来的值跟写进去的不一样,重新写一遍。这个习惯帮我避免了好几次莫名其妙的故障。
最后分享一个小技巧:如果现场调试时没有高精度电阻箱,可以用几个0.1%精度的固定电阻代替PT100,比如100Ω、120Ω、138.5Ω,分别对应0℃、约52℃、100℃。用这些电阻校准,精度虽然不如电阻箱,但比不校准强得多。我出差时就带几个这样的电阻,轻便又实用。