搞工业现场温度采集的人都会有同感:体温计好做,工业温度难做。风管里一阵风过来,读数漂好几度;压缩机旁边热浪滚滚,传感器线稍微拉长一点,有用信号就小到让人心里没底。这篇文章聊的是一套我最近一直在用的方案:ADS122U04IPWR 配合 STM32F745ZG,专做工业与 HVAC 应用中的温度测量。前者是一颗带 UART 接口的 24 位 ΔΣ ADC,后者是意法半导体的 Cortex-M7 主控,两者组合起来,热电偶、PT100/PT1000、NTC 都能接,精度和稳定性都相当能打。
如果你正在做风机盘管控制器、楼宇自控面板、冷冻水温传感器、热处理设备温度巡检,这篇内容应该能帮你少踩不少坑。我不打算像数据手册那样把寄存器从头念到尾,重点讲清楚为什么选这两个芯片、硬件怎么接、固件怎么写、现场老出哪些问题,以及我是怎么把读数从“勉强能看”调到“敢写在交付报告上”的。整个链路可以直接照抄,也可以按自己的项目改一改。
1. 为什么是 ADS122U04 + STM32F745ZG:先把选型逻辑盘清楚
1.1 工业与 HVAC 温度测量的真实需求
先说需求,否则没法谈选型。HVAC 系统里的温度点其实比想象中多:新风机组要测送风、回风温度,冷冻水系统要测供水和回水温度,热泵机组要盯压缩机排气温度,数据中心机房还要做多点进风温度监测。这些点的量程一般不大,设计规范里常见要求是 -20℃ 到 85℃ 左右,水管和压缩机侧可能到 150℃,但真正麻烦的不是量程,而是“分辨力”和“稳定”。
0.1℃ 的分辨力,对应 PT100 大约是 0.038Ω 的阻值变化,对应 K 型热电偶大约是 4μV 的电压变化。普通 MCU 自带的 12 位 ADC,配合合适的放大电路不是完全做不到,但温漂、基准误差、噪声叠在一起,量产一致性会很差。而 HVAC 系统一天 24 小时连续运行,信号链条上任何一点轻微漂移,最后都会变成冷冻站主机上那 0.5℃ 的偏差,反映到能耗上就是真金白银。所以在温度采集这种看起来“简单”的环节,我没有选自带 ADC 的省钱路径,而是直接用了一颗独立的 24 位 ADC。
另一个现实约束是传感器类型。一个控制柜里可能既有 NTC 室温传感器,又有 PT1000 水管温度探头,配电柜里还有 K 型热电偶用来做过热保护。专用数字温度芯片遇到这种混合接入场景就尴尬了:DS18B20 只能接 NTC 类电阻,TMP117 精度高但也只适合测单点。ADC 方案的优势在于前端是通用的模拟接口,信号类型可以通过软件配置去适配,这样一块板子就能覆盖多种传感器。
1.2 ADS122U04IPWR 这颗 ADC 到底强在哪里
ADS122U04IPWR 是我看过一圈之后留下的方案。它的第一张王牌是 24 位 ΔΣ 架构,内置可编程增益放大器 PGA,增益可以调得比较高,热电偶那点微伏级信号直接接入就可以放大,不用额外搭仪表放大器。第二张王牌是内部集成了电压基准、激励电流源和内部温度传感器,RTD 和热敏电阻需要的恒流源不用外挂,冷端补偿需要的测温通道也内置了。
这颗芯片跟常见 ADC 最大的区别在接口上。ADS122U04 是 UART 接口,而不是 SPI。传统 ADS1220 这类 ADC 用 SPI 通信,短距离没问题,但工业现场一旦主控板离传感器采集板有两米、三米远,SPI 时钟线稍不留神就辐射噪声和误码。UART 接口天生适合低速、可靠的长距离传输,接线只要 TX、RX、GND 三根线,线束成本低,而且可以直接挂 RS485 总线驱动器,把通信距离拉到几十米以上。
还有一点容易被忽略:它外部引脚少,供电范围宽,适合做成小尺寸的模拟前端板。我在项目里把它设计成独立的小模块,STM32 主控板只通过一组 UART 来指挥它,模拟信号处理集中在传感器附近,最大程度缩短了微弱信号在长线束里的传输距离。这个布局方式对工业现场非常友好。
1.3 STM32F745ZG 在这里到底扮演什么角色
STM32F745ZG 在这个项目里不是单纯的“读 ADC 工具”。它是一颗 Cortex-M7 内核的主控,主频 216MHz,带浮点运算单元,跑温度线性化算法和 PID 控制循环都很充裕。F745ZG 的 UART 数量多,除了跟 ADC 通信这个口,还能留出口来跑 Modbus RTU、BACnet MSTP 这些楼宇自控常用协议,不需要另加协议转换芯片。芯片本身自带以太网 MAC,如果将来要做 Web 配置界面或者 MQTT 上云,硬件基础都现成。
很多人觉得,测个温度何必用 M7。但 HVAC 控制器通常不只有温度采集。我做的这个板子同时驱动风阀执行器、采集水压、做防冻保护逻辑,还要响应上位机的启停命令。F745ZG 的定时器资源丰富,浮点能力强,一个人能干几个人的活。从 BOM 成本看确实比 M0/M4 贵一些,但它省掉了外部协处理器、协议处理芯片和可能的第二块 MCU,整机成本反而更可控。
选型时我另外看重的是它内部有硬件 CRC 和多种复位源,在温湿度变化大、电网不干净的现场更不容易死机。ADC 的 UART 通信如果异常,主控可以主动拉复位,重新初始化采集链路。F745ZG 的 IO 翻转速度快,DRDY 中断响应足够及时,不会因为读取滞后导致循环采样丢点。
1.4 不同方案对比:为什么不是普通 ADC 或数字传感器
做技术选型不能只看芯片宣传,得把几个常见路线摆在一起比,才能发现谁合适。
| 方案 | 典型器件 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| MCU 内置 ADC + NTC | 各类 MCU | 成本低、软件简单 | 精度受基准温漂影响大,抗干扰弱 | 消费家电 |
| 数字温度传感器 | DS18B20 / TMP117 | 免标定、协议简单 | 不能直接接 RTD/热电偶,量程有限 | 室温监测 |
| 独立 SPI ADC | ADS1220 | 精度高、速度快 | 长线通信容易出问题,需要控制片选时序 | 近距离仪器 |
| 独立 UART ADC | ADS122U04 | 通信线少、抗干扰好、传感器适配灵活 | 数据速率不如高速 SPI ADC | 工业 HVAC、数据采集板 |
从这个表能看出,ADS122U04 的核心优势不是单项指标极限高,而是把“传感器适配能力”和“工业现场通信可靠性”结合得很好。STM32F745ZG + ADS122U04 这对组合覆盖的是闭环控制加远程通信的中高端温控设备,而不是最便宜的消费级方案。如果产品定位是地暖温控面板那样对成本极其敏感的场合,那就老老实实 NTC 加 MCU 内部 ADC,别学我。
2. 硬件设计细节:信号链才是生死线
2.1 热电偶、RTD、NTC 怎么接前级
ADC 本身再好,前端接错一样白搭。热电偶输出的是差分微伏信号,我把它接到 ADC 的差分输入通道 AIN0/AIN1,PGA 增益开到 64 以上。热电偶内阻很小,但信号又是低电压,所以输入引脚旁边加了一对 RC 滤波:串联电阻选 100Ω,两脚之间放 0.1μF 电容。这个电容不能省,否则工频干扰会直接折进带内,尤其是长线走线经过变频器附近的时候。
PT100/PT1000 的接法我推荐三线制。三线制的思路是:用 ADC 内部的两个 IDAC 电流源分别从两条导线注入,再通过精密的参考电阻和 RTD 分压,利用比例测量把导线电阻的影响抵消掉。实际接法可以理解为 RTD 一端接激励电流源,另一端接参考电阻到地,ADC 同时测量参考电阻上的电压和 RTD 上的电压,阻值 = 电压比 × 参考电阻。这样即使环境温度变化引起 IDAC 输出电流漂移,由于是同时测量的比例关系,漂移被抵消,读数仍然稳定。
NTC 更简单,直接做分压器:NTC 串一个精密电阻接到激励电流源或者电压基准,中间点接 ADC 单端输入。注意 NTC 是非线性的,25℃ 附近灵敏度高,到 100℃ 以上变化率下降,所以量程较大时建议选择分压电阻跟 NTC 在中间温度附近等值,这样最常用的区间分辨率最高。
2.2 冷端补偿的两种实现思路
热电偶测的是热端和冷端的温差,所以冷端温度必须知道才能算出真实温度。冷端其实不一定在设备外壳上,而是指热电偶线材与铜导线(通常是接线端子)连接处的温度。ADS122U04 内部集成了温度传感器,可以直接读一个接近芯片温度的数值,如果芯片紧挨着接线端子,这个值可以做冷端补偿。
但内部温度传感器有一个明显坑:芯片本身工作会发热,读数会比真正的接线端子温度高几度。要想精度做得高,我建议两种优化:第一,PCB 布局时让 ADC 尽量远离大功率元件和电源芯片,减少自热影响;第二,不要依赖内部传感器做高精度补偿,而是在热电偶接线端子处贴一个外置高精度数字温度传感器,比如 TMP117 或精度好一点的 NTC,冷端补偿值用这个外置传感器计算。
我的实际项目是这么处理的:普通应用读内部温度传感器,出厂校准阶段做一次偏差校正;要求误差小于 ±0.5℃ 的场合,接线端子附近加一个外部温度传感芯片,与热电偶信号进入 ADC 的同时采集冷端温度。这样整机成本增加不多,但性能会明显上台阶。
2.3 ADS122U04IPWR 与 STM32F745ZG 的 UART 连接
ADS122U04 与 STM32F745ZG 通信接口的连接方式是标准的 UART 交叉连接:主控的 UART_TX 接 ADC 的 RXD,主控的 UART_RX 接 ADC 的 TXD,两边的 GND 必须连在一起。电平都是 3.3V TTL,可以直接连接,不需要电平转换。如果两块板子距离较远,或者现场存在地电位差,建议在中间加数字隔离器,隔离器两侧分别供电,把信号地用磁珠单点连接。
我这边在 F745ZG 上用的是 USART3,PA10/PA11 这组引脚正好在调试接口附近,布线方便。硬件设计时把 DRDY 脚接在 F745ZG 的一个外部中断引脚上,ADC 每完成一次转换,DRDY 拉低,MCU 立刻进入中断服务程序读取结果。用 GPIO 中断而不是轮询的好处是省 CPU:数据速率不高的时候 MCU 可以把时间拿去做显示、通讯和控制逻辑。
波特率设置这里要提醒一下:ADS122U04 的 UART 波特率与它的时钟配置相关,具体数值务必对照数据手册的 SBCLK 相关章节。我在项目里选择了 19200bps,这个速率对 24 位 ADC 的转换结果和配置命令来说非常充裕。上电时建议先给 ADC 一个复位时序,等待 DRDY 重新有效后再发命令,避免两端波特率状态不同步导致第一帧命令丢失。
2.4 电源、地线和 PCB 布线的几条实操经验
温度采集系统的电源设计优先级很高。ADC 的数字电源和模拟电源最好分开供电,模拟电源用低噪声 LDO,比如 3.3V 的 LDO 后端再串一个 LC 滤波给 AVDD。数字电路和继电器、风阀驱动回路要跟模拟电源严格分区,不能让地电流穿过 ADC 的电源引脚。
PCB 布局上,我习惯把 ADS122U04 放在传感器接口附近,模拟输入走线尽量短、等长,并且远离数字通信线。地平面要完整,不要在 ADC 底下开槽或大片铺铜,否则参考地不干净会直接影响数据低位的稳定性。去耦电容按照数据手册放在电源引脚旁边,参考电压的滤波电容选 C0G 材质,避免陶瓷电容的直流偏压特性影响精度。
输入滤波电阻的位置也有讲究:滤波电阻靠近传感器端,滤波电容紧靠 ADC 引脚,这样高频噪声进入芯片之前先被电容旁路。如果前端有 ESD 风险,比如传感器线是从外面拉进来的,我会在输入对地加 TVS 管,但要注意 TVS 的漏电流和结电容不能太大,否则会影响微伏级信号。
3. 固件与算法:从原始码到可靠温度值
3.1 STM32F745ZG 侧 UART 驱动的初始化要点
固件第一步是初始化与 ADC 通信的 UART。我的做法是用 HAL 库加外部中断,串口配置为 8-N-1,波特率与 ADC 匹配。初始化顺序有讲究:先配置 GPIO 时钟和复用功能,再初始化 UART,然后使能 DRDY 外部中断。如果一开机就陷入忙等读取,系统后面就没法做多任务了。
代码片段大概长这样:
UART_HandleTypeDef huart3; GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_USART3_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); huart3.Instance = USART3; huart3.Init.BaudRate = 19200; huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; HAL_UART_Init(&huart3);注意初始化完成后不要立刻发数据,先等几百毫秒让 ADC 内部基准稳定。工业现场很多通信失败不是时序写错,而是上电太快,ADC 还没准备好就收到了命令。
DRDY 中断回调里我一般只置一个标志位,真正的读取动作放到主循环里做。这样避免在中断服务函数中做耗时操作,也方便加互斥保护。数据速率比较低时,这种方式完全没有丢数风险。
3.2 ADS122U04 的命令交互与寄存器配置
ADS122U04 的命令与寄存器体系延续了 ADS1220 的经典布局,配置围绕 PGA 增益、数据速率、输入选择、IDAC 电流这几项展开。使用前必须发出复位命令,然后按顺序写配置寄存器,最后发送启动转换命令,之后每次转换完成 DRDY 引脚都会拉低提示 MCU。
我的配置思路分三步。第一,根据传感器类型设置 PGA 增益:热电偶用高增益,比如 64 或 128;PT100 用 8 或 16;NTC 分压信号较强,用 1 到 2 倍增益就够。第二,选择数据速率:如果现场有工频干扰,优先选带 50Hz/60Hz 抑制的速率,不要盲目追求高速度。测温对象本身就是慢变化物理量,20SPS 到 50SPS 足够了。第三,设置 IDAC:测 RTD 时需要把电流源接到对应引脚,电流值选 1mA 或者 0.25mA。电流大了信号幅度大但自热明显,电流小了功耗低但需要更高增益。
这里放一个伪代码流程:
ADS122U04_Reset(); SetRegister(REG0, Gain=64, Input=MUX_AIN0_AIN1); SetRegister(REG1, DataRate=50SPS, OpMode=Normal); SetRegister(REG2, IDAC=0.25mA, Route=AIN2); SetRegister(REG3, Burnout=Off); StartConversion(); while (DRDY_Flag) { ReadData(); }寄存器里的位域一定要按数据手册对照,我手里这版固件就吃过“IDAC 电流和输入通道配置错位”的亏,表面上看寄存器都写进去了,实际上 RTD 的电流根本没走对引脚,读出来的数据完全不对,排查了好久才发现是第 3 个寄存器的某一位配置反了。所以写驱动的时候建议先把寄存器回读一遍,确认写入值正确再开始采样。
3.3 温度换算与线性化处理
ADC 输出的原始码是 24 位二进制补码,不能直接用。电压计算公式大致是:
电压 = (原始码 / 8388608) × 基准电压 / PGA 增益
如果是双极性测量,实际满量程范围需要按基准电压和增益换算。我在代码里把基准电压做成一个宏,校准后再修正常数,方便量产时统一调整。
RTD 的换算我强烈建议用比例法:同时读 RTD 通道和参考电阻通道的原始码,然后用 RTD 阻值 = (RTD 编码 / 参考电阻编码) × 参考电阻阻值。这种算法不依赖于基准电压的绝对精度,是教科书级别的精度提升技巧。换算成阻值之后,再用 Callendar-Van Dusen 公式或者查表得到温度。
热电偶的处理稍微复杂些。把测量电压换算成微伏后,先查热电偶分度表得到“未补偿温度”,然后加上冷端温度。更标准的做法是查表得到冷端温度对应的热电势,再与测量热电势相加,最后查回温度。单纯把测量温度和冷端温度相加会引入几个摄氏度的误差,追求精度的场合一定要用“热电势相加再查表”的方式。
NTC 用 Steinhart-Hart 公式比较方便:
1/T = A + B·ln(R) + C·(ln(R))^3
系数 A、B、C 由标定确定。如果不想解方程,也可以把电阻-温度表做成定长数组,在代码里做线性插值,效果差别不大。
3.4 滤波、数据平滑与故障诊断
工业现场不存在完美的原始数据,滤波是必须的。我通常做两级处理:第一级是滑动平均窗口,把最近 8 到 16 次转换结果平均;第二级是中值滤波,用来剔除偶发的毛刺。为什么两级都用?滑动平均对随机噪声有效,但对付脉冲干扰不行;中值滤波能干掉尖刺,但平滑效果不如平均。两者结合,读数既稳又不失真。
断线检测是一个经常被忽略的功能。热电偶断线时,ADC 输入悬空,PGA 通常会输出接近电源轨的值;RTD 断线时,比例电路中的阻值会变成无穷大,测量结果会直接跳变到异常大。固件里给温度变化速率设一个阈值,比如 1 秒内变化超过 20℃,马上标一个 DIAG_ALERT 标志位,提示现场人员检查传感器接线。这个方法对付冰水机组旁偶尔“打电话”一样跳变的探头特别有用。
内部温度传感器的读数也可以做自检:如果读到的“芯片温度”超过 100℃ 或者低于 -40℃,说明芯片可能已经损坏或者焊接有问题,应该直接上报故障而不是上报一个异常温度值。
4. 实测数据、校准方法与现场问题排查
4.1 实测结果:这套组合能到什么样的精度
我在实验室用恒温槽和一个 0.01% 精度的电阻箱做过一轮实测。PT100 三线制接法下,PGA 增益 8、数据速率 20SPS、滑动滤波取 16 次平均,0℃ 到 100℃ 区间的测量偏差基本能控制在 ±0.2℃ 以内,噪声峰峰值等效温度小于 0.02℃。K 型热电偶加冷端补偿后,100℃ 到 400℃ 区间的误差大约是 ±0.5℃ 到 ±1℃,主要偏差来源是热电偶分度表的拟合残差和冷端传感器的绝对精度。
当然这个结果是在恒温条件下出来的,现场环境噪声更大,读数波动会明显一些。但即使在变频器旁边实测,滤波后的数据也没有出现肉眼可见的跳动,整套方案对于 HVAC 的应用场景来说是绰绰有余。
如果发现实测误差超出预期,优先检查校准环节,不要怀疑 ADC 芯片。24 位 ADC 的线性误差本身很小,真正影响精度的是参考电阻精度、PGA 失调、冷端测温偏差和 PCB 漏电流。
4.2 两点校准和多点标定的实操方法
校准是温度采集系统量产前绕不开的一步。我的做法是在固件里保留两个校正参数:增益校正系数和失调校正系数。测试时给系统通入两个已知的精密电阻,比如 100Ω 和 200Ω,分别记录 ADC 的原始读数,然后解线性方程,得出校正系数,烧录到片上 Flash 里。
对热电偶冷端传感器,我用多点校准:把电路板放进温控箱,在 10℃、25℃、40℃ 三个点读取冷端温度真值和 ADC 内部温度读数,做一次线性拟合,把偏移和增益误差修掉。这个动作不复杂,但能把冷端补偿误差从几度压到零点几度,非常划算。
量产时校准设备要稳定,最好用干体炉或者恒温槽,不要用天气温度代替。每块板子校完之后把校准数据写到独立 Flash 扇区,固件升级时不要擦除这个扇区,否则客户一升级固件,精度就回到出厂状态,售后会很头疼。
4.3 常见问题与排查技巧实录
我整理了一张故障速查表,都是实际调试验证过的场景。
| 现象 | 可能原因 | 排查与解决路径 |
|---|---|---|
| 通信完全无响应 | UART 接线反、波特率不匹配、ADC 未复位 | 量 TX/RX 电压,核对波特率,重新复位 ADC |
| 读数固定为满量程 | 热电偶断线、输入悬空、PGA 饱和 | 检查传感器接线,启用烧断检测 |
| 读数漂移严重 | 基准电压不稳、IDAC 自热、电源纹波大 | 检查 LDO 输出,增加平均滤波,远离发热源 |
| 数据偶发跳变 | 工频干扰、地回路噪声、滤波电容失效 | 换 50SPS 抑制模式,检查屏蔽层接地 |
| 冷端补偿不准 | 内部温度传感器受自热影响 | 设置温度修正系数,改用外部冷端传感器 |
| 上电第一帧读错 | 复位时序不完整、UART 状态未就绪 | 延长上电等待,复位后回读寄存器验证 |
这里单独说一下屏蔽层接地问题。热电偶线用屏蔽线时,屏蔽层只能一端接地,不要两端都接。两端接地会在屏蔽层里形成地环路电流,感应的工频磁场反而会坏信号。这个原理和音频线是一样的,但到现场经常有人忘记。
4.4 继续扩展:多通道、隔离与现场总线
这套方案扩展起来潜力不小。如果一路 ADC 不够用,可以在前端加模拟多路复用器,比如 TMUX 系列,把多路 RTD 轮流切换到一个 ADC 采集,代价是扫描周期变长。风管温度这种变化缓慢的通道,牺牲一点速率换成本,很划算。
如果 ADC 板跟主控板距离超过 3 米,我建议在中间加数字隔离器,然后用 RS485 驱动器替代 UART 电平。ADS122U04 本身是 UART 协议,接 RS485 只需要加一颗收发芯片和方向控制信号,通信距离可以到几十米,这对楼宇自控的现场布线非常关键。F745ZG 再通过自带的以太网 MAC 或者扩展 RS485 口接上位机,整个系统就串起来了。
最后分享一个个人习惯:每次新板回来,先把 ADS122U04 的 DRDY 信号、供电电压、RX/TX 波形全部用示波器量一遍,再上电烧固件。波形干净了再调算法,不要一上来就跑上位机软件看温度,否则问题藏在哪一层根本说不清楚。这套方法帮我省下的调试时间,远比我写固件的时间多得多。