ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于ADS122U04和STM32L4的多类型温度采集与标定实战

基于ADS122U04和STM32L4的多类型温度采集与标定实战

做工业现场和HVAC项目的人应该都有体会,温度测量看着简单,真正做起来却全是细节。我最近完成的一套方案,核心就是TI的ADS122U04IPWR这颗24位Delta-Sigma ADC,配合ST的STM32L4A6RG低功耗MCU,把PT100、热电偶、NTC三类温度传感器的采集都跑通了。这套方案最终用在了空压机排气温度和中央空调冷冻水温度的监测上,实验室标定后的实测偏差稳定在±0.15°C以内,现场连续运行两周没有出现过通信故障。这篇文章从选型逻辑讲起,一路写到底层驱动、温度换算、标定过程和现场踩坑,适合正在做温度采集模块、仪表变送器或HVAC控制器的人参考,也适合想了解ADS122U04这颗少见的UART接口ADC怎么玩的朋友。

1. 方案选型与整体设计思路

1.1 为什么选ADS122U04:一颗自带UART的24位ADC

工业仪表和HVAC控制器里,温度采集芯片的选型通常逃不开两个方向:要么用MCU集成的ADC,要么用专门的高精度ADC。ADS122U04属于后者,而且它很有特点——绝大多数ADC都走SPI或I2C,这颗芯片偏偏集成了UART接口。

它本身是TI ADS1220系列的兄弟型号,24位Delta-Sigma架构,内部有PGA(增益从1到128可调)、两个可编程恒流源IDAC、2.048V内部基准和一颗温度传感器。UART接口带来的好处有两个:第一是布线少,MCU和ADC之间只用RX、TX两根线就能完成寄存器配置和数据读取,传感器节点做主从分离时非常省线;第二是长距离传输方便,UART加个隔离器就能把模拟前端的信号送出去,不用像SPI那样担心时钟线边沿和长线反射。

我选它的另一个原因是集成度。PT100这类RTD传感器最麻烦的就是激励电流源和精密基准,用普通ADC做的话,这两个部分都要自己搭,基准温漂稍有失控,整个系统的温度指标就跟着崩。ADS122U04把IDAC和内部基准都放进去了,外围只需要按手册放几个去耦电容和滤波电阻就行。对了,后缀IPWR也值得解释一下:I指工业温度等级,工作范围在-40到125°C;PWR代表TSSOP封装,体积不大,手工焊接也没有压力。

类似的方案其实还有个选择是ADS1220,它和ADS122U04的模拟部分几乎一样,但接口是SPI。SPI本身没有问题,不过在分布式传感器节点这种场景里,UART天然和RS485、无线模块这些长距离通信方式更搭,所以最终选了UART版本。

1.2 STM32L4A6RG的角色定位:低功耗主控与数据处理

STM32L4A6RG是一颗Cortex-M4F内核的MCU,主频最高80MHz,配置是1MB Flash和320KB SRAM,在L4系列里属于大资源版本。为什么选它而不是更便宜的F103或者G0系列?核心考虑有两个:一个是低功耗属性,L4系列有多个Stop模式,HVAC控制器常年通电,但很多子系统有休眠需求,如果ADC节点由MCU通过UART轮询,MCU可以只在采集时刻醒来,其余时间睡在Stop模式下;另一个是计算能力,温度换算看起来简单,但PT100用Callendar-Van Dusen公式、热电偶用多项式拟合、NTC用指数公式,里面涉及浮点运算。Cortex-M4F带硬件单精度FPU,做这些换算基本不占CPU时间。

L4A6的UART外设数量也够用。在这个项目里,一个UART拨给ADS122U04做数据采集,另一个UART接RS485收发器,第三个接调试串口,外设资源刚好铺开。开发时用STM32CubeMX做初始化,HAL库的UART收发用中断方式,并没有复杂到需要自己写寄存器操作的地方。

1.3 系统架构与分工

整体架构很直白:传感器信号进ADS122U04的模拟输入引脚,ADC完成转换后,数据经UART发给STM32L4A6RG,主控负责配置ADC寄存器、接收数据、做温度换算,然后再通过RS485或现场总线把结果上传。

这个分工让模拟和数字两个领域完全解耦。模拟前端的噪声、漂移问题全部收敛在ADC这一颗芯片和它周围的几个元件上,主控代码里不需要关心模拟细节;反过来,通信协议、人机交互、报警判断这些数字逻辑全部放在STM32侧,也不会被ADC的寄存器细节拖住。实际开发时,我先把ADC驱动封装成独立模块,对外只留初始化和读温度两个接口,后面换传感器型号或者改量程时,主控侧代码基本不用动。

2. 硬件电路设计与传感器架构

2.1 三类温度传感器的测量方案对比

这个方案为什么说覆盖工业和HVAC?因为这两类场景的温度传感器几乎就三种类型:PT100和PT1000铂电阻,工业过程的标配,HVAC中PT1000也越来越常见;K型热电偶,高温应用绕不开;NTC热敏电阻,HVAC风机盘管、回风温度计大量使用,成本极低。

三种传感器特性差异很大,但用ADS122U04都能测,只是前端电路和软件处理不一样。我把对比列成一个表:

传感器典型量程灵敏度激励方式主要难点
PT100-200~850°C约0.385Ω/°CIDAC恒流源引线电阻补偿、换算复杂
PT1000-50~500°C约3.85Ω/°CIDAC恒流源信号小但PGA可解决
K型热电偶-200~1300°C约41μV/°C无激励冷端补偿、非线性严重
NTC 10k-40~150°C约-4%/°CIDAC或分压非线性,需查表

选型逻辑上,工业现场优先PT100,HVAC如果是控制器内部采集,用NTC成本最低,要精度和长距离传输就上PT1000。一个项目里如果同时有几种传感器需求,ADS122U04这颗4通道ADC的优势就体现出来了,通道切换在寄存器里改MUX配置就能完成,不用动硬件。

2.2 RTD模拟前端设计细节

RTD测量最关键的三个问题:激励电流从哪来、引线电阻怎么消除、噪声怎么抑制。

激励电流由IDAC提供。我实测下来500μA是比较舒服的档位,电流太小信号幅度低,对噪声容忍度差;电流太大,RTD自热效应会把电阻加热,导致读数偏高。以PT100为例,0°C时100Ω,500μA激励下只有50mV差分电压;100°C时约138.5Ω,电压69.25mV。用PGA=16档、内部基准2.048V,对应的满量程是128mV,整个温度段覆盖得比较充裕。温度分辨率理论上等于0.385Ω/°C乘以500μA,也就是192.5μV/°C,而24位ADC的LSB远小于这个值,实际限制来自系统噪声而不是位数。所以PGA的选择原则是让信号幅度尽量接近满量程的三分之一到三分之二,太小浪费分辨率,太大则提前饱和。

引线电阻是RTD误差的主要来源。四线制最准,激励和感应分开,感应线上没有电流,引线电阻完全不产生压降误差;三线制用两个同值IDAC分别从两根引线注入电流,当两根引线电阻一致时,压降被对称抵消。我的HVAC项目里传感器到主板的线长接近5米,用了三线制,实测两根引线电阻相加约0.8Ω,如果没有补偿,这个误差在PT100上相当于2°C多;三线补偿做好后,误差回到±0.05°C以内。

前端滤波方面,在每个AIN引脚对地加RC低通,电阻选100Ω到1kΩ,电容根据截止频率选,比如1kΩ配100nF,截止频率约1.6kHz,足够滤掉变频器产生的高频共模干扰。RTD引线的走线要避免形成大的环路面积,两根引线尽量绞合,否则磁场干扰会在环路上感应出电压,直接影响测量结果。

如果同一个板子上要塞热电偶通道,电源处理就更要仔细。热电偶输出信号只有几十微伏每摄氏度,即使PGA拉到32或64,电源上的纹波稍微大一点,转换结果里就会带出明显的周期成分。我给热电偶通道单独加了一路LC滤波,并在布局上让它的输入走线远离数字信号线,实测效果不错。

2.3 电源、接地与长线隔离

ADS122U04正常单3.3V供电,AVDD和DVDD之间串联磁珠,模拟电源和数字电源各放一个10μF和0.1μF去耦电容。电源质量直接影响转换结果的稳定度,尤其是内部基准,上电后要等基准稳定后再启动转换,否则前几帧数据会偏。

这个项目里ADC节点和MCU主板距离远,UART走线超过1米后偶尔出错。解决方法是两端加数字隔离器,用隔离电源模块把ADC侧的供电也隔离开。HVAC箱体内有变频器驱动,继电器切换频繁,加了隔离之后,数据错误率从偶尔一次降到几乎没有。如果项目对成本敏感,也可以先把UART速率降一档,比如从115200降到38400,出错概率会明显下降,但终究不如隔离彻底。

3. 软件框架与UART驱动实现

3.1 ADS122U04的UART通信机制

ADS122U04用标准UART帧通信,8个数据位、无校验、1个停止位,也就是常见的8N1格式。主机发命令,从机回数据。这条链路我按半双工轮询方式用:软件严格遵循先发命令、再等待响应、再发下一条的顺序,不能像SPI那样同时收发。

上电后有一个必需的动作:UART总线复位。数据手册里定义了复位时序,简单说就是让RX线保持低电平一段时间,让ADC重新同步UART通信状态。第一次用这颗芯片时我忽略了这一步,结果怎么发命令都没响应,查了半天才发现是协议没复位。正确做法是在初始化时把连接RX的MCU引脚临时配置为推挽输出,拉低足够时间,再释放回UART复用模式。

UART波特率方面,我建议从9600或19200起步。ADS122U04的最高波特率由内部时钟决定,具体数值手册里有表。工业现场干扰多的时候,波特率越高,误码率越高,温度采集本身数据量不大,20SPS下每秒只有几十字节,9600波特率完全够用。

3.2 寄存器配置与初始化流程

ADS122U04的寄存器和ADS1220基本同源,核心配置项包括输入MUX选择、PGA增益、基准源选择、IDAC电流大小与路由、数据速率。下面是我实际项目里的一个初始配置表:

寄存器关键配置值说明
MUX输入通道AIN1/AIN0差分接PT100差分信号
系统控制PGA增益16放大RTD差分电压
ADC配置基准与数据率内部2.048V,20SPS稳定优先
IDAC配置电流与路由500μA,路由到AIN1提供RTD激励

提示:寄存器偏移地址和位字段的准确定义以ADS122U04最新数据手册为准。不同手册版本细节有差异,但配置逻辑一致。

初始化流程我是这么写的:先做UART复位,等待约50ms;然后发WREG命令,把寄存器值按地址逐个写入;接着用RREG读回来校验一遍;最后配置连续转换模式。工业现场我习惯用连续转换加主控轮询,ADC自己维持转换周期,主控按固定间隔取最新结果,逻辑最简单,也好排查。

主控侧的驱动我是用HAL库的UART收发接口封装的。发送命令时用HAL_UART_Transmit,接收结果用HAL_UART_Receive,都带超时重试。读结果的关键代码大概长这样:

/* 伪代码:读取ADS122U04的转换结果 */ int32_t read_adc_raw(void) { uint8_t cmd[1] = {0x10}; /* RDATA 命令,具体值以手册为准 */ uint8_t buf[3]; int32_t raw; HAL_UART_Transmit(&huart1, cmd, 1, 10); HAL_UART_Receive(&huart1, buf, 3, 10); raw = (buf[0] << 16) | (buf[1] << 8) | buf[2]; if (raw & 0x800000) { raw |= 0xFF000000; /* 24位有符号数扩展 */ } return raw; }

3.3 温度换算与实现细节

ADC输出是24位二进制补码,换算电压的公式是:

电压 = 原始码 / 8388608 × (VREF / PGA)

以VREF=2.048V、PGA=16为例,满量程电压128mV,理论LSB约15nV。不过实际有效位数没那么高,20SPS下有效分辨率大概在几十nV到几百nV量级,做产品时不要按15nV去算温度分辨率,那是理论极限,不是工程指标。

拿到电压以后,PT100的电阻就是电压除以IDAC电流。温度换算我推荐用IEC 60751里的Callendar-Van Dusen公式。0°C以上的简化公式是:

R(t) = R0 × (1 + A×t + B×t²)

其中R0=100Ω,A=3.9083e-3,B=-5.775e-7。解一元二次方程就能得到温度。0°C以下要加C项,用迭代法逼近。Python验证时我这么写:

def pt100_res_to_temp(R): R0 = 100.0 A = 3.9083e-3 B = -5.775e-7 C = -4.183e-12 b = R0 * A a = R0 * B c = R0 - R # 0°C以上:解二次方程 import math t = (-b + math.sqrt(b*b - 4*a*c)) / (2*a) if t >= 0: return t # 0°C以下:需要C项,用牛顿迭代 t = 0.0 for _ in range(20): r_t = R0 * (1 + A*t + B*t*t + C*(t-100)*t*t*t) f = r_t - R dt = R0 * (A + 2*B*t + C*(4*t*t*t - 300*t*t)) t -= f / dt return t

实际工程里我更推荐查表法,把PT100的电阻-温度表存成数组,二分查找加线性插值,速度和精度都好控制。热电偶则需要叠加冷端温度,可以用ADC内部温度传感器实时读冷端,再通过NIST多项式把热电偶电压换算成温度。NTC最简单,用B参数公式估算后查表微调即可。

4. 系统标定与现场实测

4.1 为什么必须做系统级标定

ADS122U04的内部基准和内部温度传感器出厂前已经校准过了,但系统级误差仍然存在:IDAC电流的绝对精度、外部滤波电阻阻值偏差、PCB走线电阻、连接器接触电阻,都会让最终读数偏离真实温度。所以不要指望光靠芯片指标就能达到整机标称精度,至少要做一次全温区标定。

我的标定流程分三步:第一步,把ADC输入端短接,记录零点偏移码,写入偏移校准寄存器;第二步,用精密电阻箱模拟PT100在0°C和100°C两个点的电阻值,做两点增益校准;第三步,把传感器放入恒温槽,在几个特征温度点验证最终偏差。

4.2 恒温槽实测数据

用同一套电路板、三线PT100传感器,恒温槽实测数据如下:

恒温槽设定方案读数偏差
-10.00°C-9.97°C+0.03°C
25.00°C25.04°C+0.04°C
50.00°C50.09°C+0.09°C
90.00°C89.91°C-0.09°C

在0~100°C范围,偏差控制在±0.1°C以内,满足HVAC仪表常用的A级精度要求。需要说明的是,恒温槽每个点的稳定时间至少30分钟,读数也是取连续50帧的平均,这样测出来的是系统误差,不是瞬时噪声。

4.3 工业场景实测表现

空压机排气温度用K型热电偶测,量程在150~200°C之间。ADS122U04内部温度传感器放在芯片内部,而冷端实际是在接线端子位置,两者之间有1~2°C的温差,直接拿内部温度做冷端补偿会引入误差。我在接线端子处额外贴了一颗NTC,用NTC读到的端子温度做实际冷端温度。加上这个修正后,热电偶读数和设备自带的铂电阻读数对比,差值从原来的4°C缩小到1.5°C以内,对现场监测来说完全够用。

HVAC冷冻水系统的PT100通道表现更稳定,水系统温度变化缓慢,20SPS采样加滑动平均后,控制界面上的读数稳定到小数点后一位不再跳动。这一套设备连续运行两周,室温零点漂移最大约0.02°C,在预期范围内。

5. 常见问题与排查技巧

5.1 UART通信偶发无响应

遇到最多的坑是上电时序。ADC还没完成启动就发命令,大概率收不到响应。解决办法是MCU上电后先延时50到100ms,再做UART复位,然后发首个命令。如果仍然偶发无响应,检查波特率误差:STM32的UART波特率由系统时钟分频而来,系统时钟不是标准整数倍时,实际波特率和目标值会有偏差,两侧累计误差超过5%就会出现随机错帧。调试时可以把ADC的响应和RDATA命令重发逻辑打开,连续三次失败再判定链路故障。

5.2 温度读数整体偏高或偏低

优先怀疑IDAC电流不是标称值。用万用表串一个精密电阻测IDAC实际输出,配置500μA时实测应在495~505μA范围内。偏差大就要在软件换算系数里加修正。另外检查RTD引线连接顺序,三线制的补偿逻辑建立在两路线电阻一致的前提下,如果两根引线长度差很多,补偿会有残余误差。还有一个我犯过的错:IDAC路由方向搞反,激励电流没流过RTD,读回来的电压几乎为零,被当成传感器断线排查了好一阵。

5.3 读数在零位附近来回跳

这类问题几乎都是地环路或干扰。最典型的是ADC节点和主板距离远、隔离没做好,或者模拟地通过长线接到了大功率负载的接地端。排查技巧:把传感器短接,如果噪声明显下降,问题在传感器引线环路;如果短接后噪声依然大,问题在电源或基准。现场变频器干扰严重时,把数据速率降到20SPS,叠加一阶数字滤波,读数跳动能从±5个字压到±1个字。

5.4 避坑清单速查

现象可能原因处理办法
上电后无响应未做UART复位/等待不足严格复位时序,初始化延时
读数恒定不变MUX通道没切对/传感器断线用RREG读回配置,检查差分输入
低温读数偏正IDAC偏大/引线电阻未补偿实测IDAC电流,检查三线接法
开机前10秒漂移内部基准未稳定上电后丢弃前若干帧数据
高温读数偏负热电偶冷端补偿错误核对冷端传感器位置和温度

最后说点个人体会。这套方案最大的价值,是把复杂的模拟前端问题压缩成了一颗芯片加一段协议驱动,主控侧不用再跟运放、基准、滤波电路纠缠,项目后期的维护成本低了一大截。实际开发中我也走了不少弯路,比如最开始迷信24位分辨率,把数据速率调得特别高,结果噪声大得没法看;后来老老实实按20SPS跑,反而稳得一批。如果你手头也要做多类型温度采集的设备,可以优先考虑这种ADC,先把协议和换算逻辑跑通,再去优化精度和成本,这条路走起来会顺畅很多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进