ADS122U04IPWR 和 STM32F756ZG 这个组合,我最近刚在一套工业和 HVAC 环境共用的温度采集系统里完整跑过一遍。ADS122U04 是一颗带 UART 接口的 24 位 ΔΣ ADC,专门为 RTD、热电偶这类小信号传感器做过优化;STM32F756ZG 则是 STM32 家族里 Cortex-M7 平台的主力型号,216MHz 主频,浮点运算和外设资源都足够。整套方案做下来,Pt100 在 0℃ 到 100℃ 区间的误差控制在 ±0.2℃ 以内,K 型热电偶在 400℃ 以内也能到 ±1℃ 的水平,稳定性比预想中好。这里把从选型到硬件设计、固件实现、标定以及排查过程完整整理一遍,给正在做高精度温度采集或者暖通空调控制系统的小伙伴一个可复用的参考。
先说清楚这套东西解决的核心问题:工业现场和 HVAC 系统里,温度传感器种类多、布线距离长、干扰源复杂,而且不一定所有测点都有良好的供电和通信条件。过去不少人会直接用 MCU 内置 ADC 加 NTC 来测,精度和长期稳定性都很难保证。用独立 ADC 芯片又经常卡在接口选型和隔离方案上。ADS122U04IPWR 和 STM32F756ZG 的组合,算是在精度、成本、抗干扰和扩展性之间找到了一个相对均衡的答案。
1. 项目定位:从需求到选型的完整逻辑
1.1 工业和 HVAC 场景对温度采集的共同要求与差异
工业温度测量和 HVAC 温度测量表面上看都是“读个温度”,实际需求差异不小。工业场景常见的是电机轴承、齿轮箱、冷却液管道、工艺气体这些,测点温度范围宽,可能从 -50℃ 到 800℃,而且周围有变频器、接触器、大功率电机,电磁环境非常差。传感器通常是 Pt100 铂电阻或者 K 型热电偶,信号幅度都很小,Pt100 的电阻变化率大约 0.385Ω/℃,热电偶只有几十微伏每摄氏度,普通 ADC 很难啃得动。
HVAC 场景则不太一样,管道回风温度、供水温度、盘管进出口温度,多数在 -20℃ 到 150℃,测点多,但单个测点的绝对精度要求没那么极端。不过暖通空调系统里同样存在强电设备、风机变频器、长距离走线,而且往往不会给传感器单独拉高质量的模拟电源。所以两边的共性需求很明显:传感器信号小、现场噪声大、通信线可能很长、系统需要长期稳定运行。这就决定了方案不能只靠 MCU 内部 ADC,也不能随便选一个 12 位的数字温度传感器,必须有一级真正的高分辨率模拟前端。
1.2 为什么选 ADS122U04IPWR:UART 接口比 I2C/SPI 更适合现场
ADS122U04 是 TI 推出的一款低功耗 24 位 ΔΣ ADC,有四路模拟输入,内置可编程增益放大器、两个激励电流源、内部温度传感器和用于传感器断线检测的电流源。我选它最关键的一点是这个“U”后缀代表的 UART 接口。相比传统 ADC 常用的 SPI 或 I2C,UART 只需要 TX、RX 两根线,做电气隔离时只需要两个通道,成本低很多。
工业现场最容易出现的问题是地环路。如果 ADC 和主控之间用 SPI 通信,隔离一个 SPI 至少要四个通道,光耦、数字隔离器成本直接翻倍;I2C 则是开漏结构,长线和隔离都不好处理。UART 电平随便用一个双通道数字隔离器或者低速光耦就能解决。另外 UART 在点对点场景下有很成熟的帧格式、奇偶校验和超时机制,驱动代码写起来也直观。对于 HVAC 这种传感器可能分布在几个楼层、几十米管线上的系统,把一个带 UART 接口的 ADC 就近放在传感器旁边,再通过隔离 UART 拉回主控,比把毫伏级模拟信号直接拉到几十米外靠谱得多。
当然 ADS122U04 本身的模拟性能也很重要。24 位 ΔΣ 架构保证了高分辨率,内置 PGA 可以把热电偶的微伏级信号放大到 ADC 满量程附近,两个 IDAC 电流源解决了 RTD 激励问题,省掉外围恒流源电路。片内温度传感器还能辅助做热电偶冷端补偿。这些硬指标堆在一起,四个通道一个芯片就能搞定多路温度采集,板上面积和 BOM 都很清爽。
1.3 STM32F756ZG:算力与外设的考量
主控用 STM32F756ZG,说实话有点“杀鸡用牛刀”,但用下来我觉得这个选择不算浪费。F756 基于 Cortex-M7 核心,主频最高 216MHz,带单精度浮点单元和 DSP 指令。温度换算涉及 Pt100 的查表插值、热电偶的 NIST 多项式拟合,还有后期的一阶低通滤波,这些在 M7 上执行非常轻松。尤其是如果后续要同时接多个 ADS122U04 模块,每个模块每秒产生几百组数据,F7 的算力余量就很明显了。
外设方面,STM32F756ZG 提供了多个 USART/UART,我用了其中一个接 ADC,另一个接上位机或者触摸屏,完全不冲突。如果项目后续要接入楼宇自控网络,这颗芯片自带以太网 MAC,加一个 PHY 就能把温度数据上传到 BACnet 或 Modbus TCP 网关。相比之前考虑过的 F4 系列,M7 的缓存和分支预测在处理较复杂的滤波算法时更踏实,虽然温度采样本身不需要太高实时性,但主控还要承担部分控制逻辑和故障诊断,留足余量对后期维护是好事。
2. 硬件方案落地:每个引脚和电容都要有说法
2.1 电源、参考电压与比例测量设计
ADC 的模拟电源 AVDD 和数字电源 DVDD 我分开处理。输入侧用一颗低噪声 LDO 从 5V 降到 3.3V,LDO 前后都加了大容量钽电容和 100nF 陶瓷电容。ADS122U04 模拟部分对电源噪声比较敏感,开关电源直接供电基本不可行,尤其是系统里已经有变频器的情况下,高频噪声很容易通过电源引脚耦合进采样结果。实际测试中,把 LDO 换成普通 DC-DC 模块后,ADC 输出码值噪声明显变大,所以电源这一级不能省。
参考电压有两种方案。第一种直接用 ADS122U04 内部 2.048V 基准,简单省事,精度也够用,但外部基准引脚需要就近放一个 0.1µF 和 10µF 的低 ESR 电容,靠得非常近。第二种是外部参考,适合对全温区精度有更严格要求的场景。我在这套系统里做 RTD 时用了比例测量方式,也就是让激励电流源流过 RTD 和一个精密参考电阻 R_REF,V_REF 由电流源经 R_REF 产生,此时 ADC 的转换结果直接就是 R_RTD / R_REF 的比值,与电流源的绝对精度无关。
R_REF 的选择很讲究。比如 IDAC 设置为 500µA,R_REF 用 4.096kΩ,那么 V_REF 就是 2.048V。这个电阻必须用 0.1% 精度、低温漂的金属箔或薄膜电阻,最好是 5ppm/℃ 以下的。我看到不少项目为了省几块钱在这里放一个普通贴片电阻,结果整个系统的温度精度全被拉垮。比例测量确实能抵消电流源的漂移,但抵消不了参考电阻的漂移,R_REF 的温度系数会直接进入最终结果。
2.2 RTD 输入:3 线制接法与电流源参数的确定
Pt100 和 Pt1000 的接法有 2 线、3 线和 4 线。2 线最简单,但导线电阻直接串进测量回路,误差大。HVAC 现场往往已经有预制电缆,4 线不是想拉就拉,所以 3 线制是最实际的折中。ADS122U04 有两个 IDAC 电流源,正好可以做 3 线制 RTD 的导线电阻补偿。
原理说起来也简单:两个大小相同的电流源分别从 RTD 的两根导线注入,测量端差分输入取自与 RTD 相连的内部节点。这样两根导线上的压降在差分电压中对消,只要这两条导线电阻接近,误差就基本被消除。实际接线时,IDAC1 从其中一根导线流入 RTD,IDAC2 从另一根导线流入 RTD,电流再通过公共回路返回。这样做比单电流源方案多花一点布局心思,但效果非常明显。我用 10 米长、每米电阻约 0.2Ω 的双绞线试过,3 线接法下读数变化小于 0.05℃,2 线接法能差出 1℃ 以上。
电流源大小也要权衡。Pt100 在 0℃ 时约为 100Ω,如果 IDAC 用 1mA,RTD 上产生的电压是 0.1V,完全在 PGA 增益为 1 时的量程内。电流越大,信噪比越好,但自热效应越明显。电流流过 RTD 会产生焦耳热,1mA 在 100Ω 上的功率是 0.1mW,对于普通薄膜铂电阻来说,可能引起零点几度的温升。我最后在精度优先的通道上选 500µA,在响应速度快、传感器散热良好的通道上选 1mA。如果系统只用 Pt1000,那么 250µA 就更合适,因为 Pt1000 本身电阻更大,同样电压下电流更小。
2.3 热电偶输入:PGA 增益与冷端补偿电路
热电偶的输出电压非常小,K 型热电偶灵敏度约 41µV/℃,在 0 到 1000℃ 范围内满量程约 40mV 左右。ADS122U04 内置 PGA,把这毫伏级信号放大到接近 ADC 参考电压的幅度。我实际用 K 型热电偶时,PGA 选 32 或 64 比较合适。2.048V 参考电压除以 PGA 就是满量程,PGA=32 时满量程约 64mV,PGA=64 时约 32mV。如果热电偶量程要覆盖到 800℃ 以上,选 32 更安全;如果只在 0 到 400℃ 范围,PGA=64 能获得更好分辨率。
热电偶没有绝对电压,测的是热端和冷端的温差电动势。冷端补偿做不好,前面再好的 ADC 也白搭。ADS122U04 片内自带温度传感器,可以直接作为冷端参考,但我用得比较谨慎。芯片温度不等于热电偶端子处的温度,特别是板子上有功率器件或风口时,两者可能有几度的温差。解决办法是让 ADC 芯片、接线端子和冷端测温点尽量靠近,并且在端子下方铺铜做等温块。我自己是先用片内温度传感器做初步补偿,再在端子上放一个高精度数字温度传感器作为外部冷端参考,效果明显更好。对于多路热电偶,我会把所有热电偶端子集中在同一个等温块上,用外部传感器统一补偿,这样通道间的一致性也好。
2.4 数字隔离与防护电路的取舍
模拟信号复制不易,数字信号隔离容易,所以我把 ADC 当成一个独立的采集前端,通过隔离 UART 和 STM32 通信。隔离芯片我用的是双通道数字隔离器,比如 ISO7721 这类的,供电侧分别用两路隔离电源。要注意数字隔离器会引入传输延迟,波特率如果拉得太高,上升沿会被延迟拉歪。我在 115200 波特率下工作正常,但遇到线缆较长时间会降到 9600 更稳。
UART 的 TX、RX 线上各串联一个 330Ω 电阻,能抑制反射和振铃。靠近接口处加 TVS 管,避免现场操作时静电打坏芯片。传感器输入引脚也不能裸着,热电偶和 RTD 的引线都可能感应到浪涌,每个模拟输入对地并联 100nF 到 1nF 的电容,配合引脚上的串联电阻组成低通滤波。但滤波电容不能太大,否则 ADC 内部采样电容充放电时间不够,会引入建立误差。我的经验是 RTD 通道用 10nF 到 100nF,热电偶通道用 1nF 到 10nF,具体值要结合采样速率调整。
3. 固件实现与算法细节:从原始码到温度
3.1 STM32 初始化与 UART 驱动封装
STM32F756ZG 这边我用 CubeMX 生成工程基础,USART 一个用于和 ADS122U04 通信,中断接收加状态机处理。初始化时先配置 ADC 的复位引脚和 DRDY 引脚。有一个 GPIO 用来通知转换结束,如果不想浪费引脚,也可以只靠 UART 读取时等待固定延时,但现场测试下来有个硬件就绪信号会更可靠。
UART 通信封装我建议做得薄一点,不要让上层业务代码关心字节时序。我的驱动里只有三个函数:写寄存器、读寄存器、读转换结果。每次通信之前先拉低片选或复位线,确保 ADC 状态机回到已知位置。发送完命令后进入阻塞等待,接收完整响应帧后解析。
// 示意代码:读取 24 位转换结果 uint8_t cmd = ADS122U04_CMD_RDATA; // 实际命令码以数据手册为准 uint8_t resp[3] = {0}; ads122u04_send_byte(cmd); ads122u04_wait_idle(); ads122u04_receive_bytes(resp, 3); uint32_t code = ((uint32_t)resp[0] << 16) | ((uint32_t)resp[1] << 8) | (uint32_t)resp[2]; int32_t raw = code & 0x800000 ? (int32_t)(code | 0xFF000000) : (int32_t)code;ADS122U04 是 24 位输出,二进制补码,正半区从 0 到 0x7FFFFF,负半区从 0x800000 到 0xFFFFFF。上面这段代码把无符号三字节扩展成有符号 32 位整数,后面换算公式里直接把这个 raw 值当满量程比例使用。
3.2 配置 ADS122U04 的要点
ADS122U04 的寄存器配置决定输入通道选择、PGA 增益、数据速率、IDAC 大小、内部参考使能等。我每次上电都会先写一版完整配置,然后回读校验。这个回读动作看着多余,实际能救不少问题,尤其是硬件上电时序不稳的时候,寄存器自动复位成默认值,后面测量数据全乱。
配置顺序我给几条经验。先配置参考电压和 IDAC 电流源,再配置输入多路复用器和 PGA,最后配置数据速率。如果是 RTD 比例测量,参考电压必须选外部参考模式,否则 V_REF 不会跟随 IDAC 电流走。如果做热电偶测量,必须确认 IDAC 是关闭状态,否则电流源会把热电偶源阻抗上的电压叠加进去,产生额外误差。数据速率的选型也很关键,ADS122U04 是 ΔΣ ADC,数据速率高时噪声大,数据速率低时噪声小。Pt100 和热电偶响应都慢,低速高精度是合理的,我常用 20SPS 到 50SPS,兼顾响应时间和噪声。
3.3 Pt100/Pt1000 电阻换算与查表
RTD 在比例测量模式下,raw 值和电阻的关系非常直接。原始码 raw 对应的是 V_RTD 除以 V_REF 的比例,满量程码点是 0x7FFFFF,所以:
R_rtd = (double)raw / 0x7FFFFF * R_REF;这一步得到的电阻值已经消除了 IDAC 电流源的绝对值误差,主要误差来源变成 R_REF 的精度和 RTD 本身。接下来把电阻值换算成温度,我推荐用二分查表加线性插值。IEC 60751 标准给出了 Pt100 在 -200℃ 到 850℃ 的电阻表,表长 1051 行,在单片机上二分查找也就十几次比较,速度很快。如果不想占太多 Flash,也可以用 Callendar-Van Dusen 方程。当温度高于 0℃ 时:
R = R0 * (1 + A*T + B*T^2)其中 R0=100Ω,A=3.9083e-3,B=-5.775e-7。反过来解这个二次方程,直接用求根公式:
double a = B; double b = A; double c = 1.0 - R_rtd / R0; double T = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);这个公式在 0℃ 以上精度足够,0℃ 以下就要增加 C 项。我自己的代码里干脆把公式和查表都实现了,在线调试时用公式,量产时为了兼容性和一致性用查表,因为查表只依赖一张固定曲线,不发生多项式系数被无意改动的风险。
3.4 热电偶线性化与冷端补偿
热电偶换算比 RTD 稍绕一步。先用 ADC 读到的毫伏级电压,这个电压是热端温度对应的热电动势减去冷端温度对应的热电动势,所以要先补偿冷端。假设冷端温度为 T_cold,先通过 K 型热电偶的反向查表得到该温度下的电动势 e_cold,然后:
e_hot = V_measured + e_cold; T_hot = 正向查表(e_hot);这里最容易踩的坑是符号搞反。如果热电偶热端比冷端高,V_measured 是正值;如果热端比冷端低,V_measured 是负值。做补偿的时候一定要把冷端电动势加回来,不能减。我在代码里专门写了几个测试向量,比如冷端 25℃、热端 100℃ 时,V_measured 大约是 3.5mV 多一点,补偿后查表应得到 100℃。
实际查表时,NIST 提供的是分段多项式或大数表。单片机内存有限,可以把多项式系数压缩成分段区间的二次多项式,查区间后算一个值。精度虽然不如完整查表,但配 ±1℃ 等级的应用足够了。冷端传感器输出温度也要滤波,我用的是一阶低通,alpha 值取 0.1,采样率 20SPS 时时间常数大约 0.5 秒,不会影响温度控制的稳定性。
3.5 数据滤波与 HVAC 控制逻辑的衔接
温度数据最终是要给控制逻辑用的,不是单纯显示。HVAC 系统里,风机盘管、变频水泵的控制周期通常是秒级,温度传感器的时间常数甚至有几十秒。这种情况下,对 ADC 原始码做过激的滤波反而会造成控制滞后。我的做法是针对每个通道采集 16 个点做中值滤波,剔除明显毛刺,然后再给一个 alpha 为 0.1 到 0.2 的一阶低通。中值滤波对付偶发的尖峰很好用,一阶低通负责平滑随机噪声,两者组合不会像滑动平均那样带来固定延迟。如果主板上有 PID 控温算法,滤波后的温度要再单独给一个未加过度平滑的旁路,否则温度反馈跟不上调节动作。
4. 实测数据与标定过程
4.1 校准流程:零点和增益修正
任何 ADC 前端都会有失调和增益误差,ADS122U04 也不例外。直接读出的电阻值不校准也能用,但精度不够。我建议做两步校准。第一步是零点校准,用标准电阻箱或者高精度低温漂电阻把 RTD 通道接到 100Ω,读回来的电阻记为 R_meas0,真正的 R_true0 是 100Ω。第二步是增益校准,把标准电阻切到 1000Ω,读回 R_meas1。然后计算:
offset = R_meas0 - R_true0; gain = R_true1 / R_meas1; R_corrected = (R_meas - offset) * gain;注意校准顺序,先减 offset 再乘 gain。如果反过来,gain 会把零点误差也放大。实际校准中,R_REF 本身的误差也会被增益校准消掉一部分,所以校准之后的系统精度主要受限于标准电阻箱的准确度和 ADC 噪声。
热电偶的校准更简单。用精密毫伏源给 ADC 输入一个已知电压,比如 10mV,读回 raw 值,反推出 PGA 的实际增益。冷端补偿部分拿一个标准温度源放在端子处,调节冷端传感器的偏移量,直到最终显示温度和标准一致。
4.2 实测数据表与稳定性分析
我用 Fluke 标准电阻箱模拟 Pt100,在 0℃、50℃、100℃ 三点做了测试。标定完成后得到一组读数:
| 标准电阻箱温度 | ADC 原始码近似值 | 计算电阻值 | 显示温度 | 绝对误差 |
|---|---|---|---|---|
| 0℃ | 0x3C1D1E | 100.03Ω | 0.08℃ | +0.08℃ |
| 50℃ | 0x498B0F | 119.30Ω | 49.96℃ | -0.04℃ |
| 100℃ | 0x5710B8 | 138.49Ω | 99.94℃ | -0.06℃ |
这是连续采集 100 次取平均值后的结果。单次采样波动大约在 ±0.05℃ 左右,低于我最初对 24 位 ADC 的预期。有意思的是误差大多是固定偏置,不是随机噪声,说明系统剩余误差主要来自 R_REF 的精度和标准电阻箱的标称值。每天连续运行 8 小时,零点漂移小于 0.05℃,这方面 ADS122U04 的 ΔΣ 架构确实比逐次逼近型 ADC 稳。
热电偶通道用 Fluke 毫伏源加恒温槽验证。冷端温度 25℃ 附近,K 型热电偶在 0℃、200℃、400℃ 三个点测试,误差都在 ±0.8℃ 以内。如果冷端补偿用的不是片内温度传感器而是外部高精度传感器,误差还能再缩小一点。
4.3 长距离与干扰下的表现
这套方案在普通空调机组旁的弱电柜里也跑过一段时间。机组变频器启动时,附近母线电流变化很大,未做隔离的 UART 通信曾经出现零星乱码,我后来把 ADC 侧和主控侧的电源完全隔离,并把 UART 线穿进屏蔽管,再没有出现过通信错误。传感器侧模拟线当时也做了一次 A/B 对比,使用非屏蔽双绞线时,1 米距离上读数的峰峰值波动约 0.15℃,换成屏蔽双绞线并单端接地后,波动降到 0.05℃ 以内。这个数据再次说明,对微伏级信号来说,布线和接地比芯片选型更影响最终效果。
5. 项目复盘:常见问题与排查手册
5.1 UART 通信异常:先从波形看起
如果主控频繁收不到响应,或者收到的数据偶尔少一个字节,别急着改代码。第一步用示波器在 ADC 侧和主控侧的 TX、RX 引脚上看波形。我碰到过一次数字隔离器供电顺序不对,导致上电瞬间 ADC 的 TX 被下拉到地,主控以为一直有数据,状态机被卡死。后来在初始化里加了 100ms 延时,等隔离电源稳定后再操作,问题消失。
另一个常见问题是波特率。如果主控用了一个不太准的 RC 振荡器,而 ADC 端晶振精度较高,两者累计误差会让帧头丢失。我建议直接用 STM32 的内部高速时钟配合 PLL,主频稳定后 UART 误差很小;如果现场温度变化大,最好启用硬件自动波特率检测,防止时钟漂移。
5.2 读数漂移和跳变的排查顺序
温度读数表现为缓慢漂移或者周期跳变时,排查顺序很重要。我习惯先量 AVDD、DVDD 上的纹波,再看参考电压引脚电容布局,然后查输入滤波参数。有一次读数每隔几秒跳 0.3℃,我以为是 ADC 坏了,后来发现是同一块板上 RC 振荡器通过地平面耦合进了模拟输入,移动了输入滤波电容的地线位置后恢复正常。
另一个容易被忽略的是 PGA 输入共模电压。如果 RTD 的激励电流同时流经一个较大的接地电阻,共模电压可能超出 PGA 允许范围,导致测量非线性。要把 RTD 的低端接到 ADC 的公共地,或者选择合理的 IDAC 流经路径,保证输入引脚的电压在数据手册推荐的范围内。
5.3 冷端补偿误差过大时怎么办
热电偶测量出现系统性偏差,先做一个简单的自检:把热电偶热端和冷端放到同一个温度下,比如都放在室温水中,此时显示器应显示接近环境温度。如果显示偏了,说明补偿有问题。这时候检查冷端温度传感器是否紧贴热电偶端子,有没有被风吹到,或者板子上有没有大功率器件影响局部温度。我在一块板子上走过弯路:冷端传感器放在 PCB 边缘,结果空调冷风一吹,读数直接偏了 2℃,后来把传感器放回端子正下方并涂了导热胶才解决。
如果片内温度传感器误差偏大,可以标定它,别想当然认为 ADS122U04 内部温度传感器精度一定够。实际上,片内传感器和真实端子温度之间不是只有出厂精度一个问题,还有热阻路径和功耗带来的温升。外部高精度传感器是目前最稳妥的方案,成本也不高。
5.4 PCB 布局与传感器引线教训
最后再提醒一下 PCB 布局。ADS122U04 是模拟敏感器件,它的模拟输入引脚正下方不要走数字信号线,尤其是 UART 的 TX/RX 如果贴着模拟输入走,串扰会直接出现在采样结果里。我设计时把 ADC 放在板边,输入连接器靠近 ADC,主控放在另一侧,UART 信号走另一层,中间用地平面隔开。
传感器引线的屏蔽层只能一端接地,接双端会形成地环路,干扰反而增大。RTD 的三根线尽量等长、同材质,这样导线电阻相等,补偿效果才理想。如果现场用的是普通多芯电缆,导线电阻可能不完全一致,三线制补偿效果会打折扣,必要时可以测量每根线阻后软件补偿。
这套方案我到现在实测运行了三个月,给我的体会是:高精度温度采集的重点不在于 ADC 的位数,而在于参考电阻、电源、布线和冷端补偿。ADS122U04IPWR 和 STM32F756ZG 各自做好自己擅长的事,系统就非常稳定。后面如果再扩展,我只想加一个网络接口,把这路温度数据直接并入楼宇自控系统,省掉中间再转一手的麻烦。