在工业现场摸爬滚打久了你会发现,温度测量这件事,看着简单,真正要做得准、做得稳,比想象中坑多得多。最近我用 ADS122U04IPWR 配合 STM32F071VB 做了一版针对工业和 HVAC 场景的温度采集节点,实测下来这套组合在精度、功耗、成本之间取得了很不错的平衡。ADS122U04IPWR 是 TI 的一颗 24 位 ΔΣ ADC,带 UART 接口、内置 PGA 和双激励电流源,非常适合 PT100/PT1000 和热电偶的精密测量;STM32F071VB 则是意法半导体 M0 内核的入门级 MCU,主频 48MHz,外设资源管够,两者通过一组 UART 就能完成所有数据交互。这篇文章就把我这套方案的选型逻辑、硬件设计、寄存器配置、通信协议、滤波标定和常见坑一次性讲清楚,给正在做工业温度采集、HVAC 控制、设备状态监测的朋友一个可直接抄作业的参考。
1. 方案整体设计与选型逻辑
1.1 为什么不用 MCU 内置 ADC
很多做测温的人第一反应是,STM32F071VB 自带 12 位 ADC,测个 0 到 50 度的室温绰绰有余吧。但放到工业和 HVAC 现场,这个结论就站不住脚了。MCU 内置 ADC 的参考电压通常是芯片的 VDDA 或内部带隙基准,温度系数大,而且 PCB 上的数字噪声很容易耦合进模拟采样通道,低温漂、低噪声、高线性度这三条在一颗通用 MCU 的片内 ADC 上几乎不可能同时满足。举个实际例子,用内置 ADC 测 PT100,在 25 度环境校准完后,环境温度升到 45 度,零点可能就漂掉 1 到 2 个 LSB,对应温度就是 0.3 到 0.6 度的误差。在 HVAC 舒适性控制里这个误差可能还能忍,但在工业过程监测、设备热保护这类场景里就是安全隐患。
所以我把测温链路拆成“高精度模拟前端 + 通用 MCU”两级。ADS122U04IPWR 负责把传感器微弱的电阻/电压信号变成高分辨率数字量,STM32F071VB 只负责通信、逻辑控制和协议处理。这样做的最大好处是模拟部分和数字部分可以物理隔离,电源域分开,模拟地和数字地单点连接,噪声问题大幅减少。
1.2 为什么选 ADS122U04 这个“小众”型号
ADS122U04 在 TI 产品线里不算最热门的,但它的定位非常精准:24 位分辨率、4 通道输入、内置 PGA(增益最高 128 倍)、两个可编程激励电流源 IDAC、内部低温漂基准,最关键的是它带着 UART 接口。市面上带 SPI 或 I2C 的高精度 ADC 一大堆,但带 UART 的真心不多。UART 接口在实际工程里有多香,只有做过工业采集的人才懂。
首先,UART 是最容易做隔离的接口,一颗数字隔离器加两个电容就能把模拟前端和 MCU 隔离开来,这在工业现场是刚需——传感器那侧可能就是高压电机旁边,电磁干扰和地电位差非常大,不隔离根本没法稳定工作。其次,UART 波特率不高,走线长度容忍度比 SPI 高很多,传感器节点和主控板之间可以拉开距离。第三,UART 协议本身是异步的,MCU 不需要额外提供时钟,软件模拟也容易。
ADS122U04 的 4 通道输入也很关键。HVAC 现场经常需要一路测回风温度、一路测送风温度、一路测盘管水温,再留一路做冷端补偿或者故障诊断。如果选单通道 ADC,一块板子要放三四个芯片,成本和面积都受不了。ADS122U04 一颗芯片配合一个模拟多路开关的逻辑就能处理多路输入,或者直接用两个通道测差分 RTD、一个通道接热电偶、一个通道接热敏电阻。
1.3 STM32F071VB 在这个方案里的角色
STM32F071VB 是 64 脚 LQFP 封装、128KB Flash、16KB SRAM,资源对温度采集节点来说绰绰有余。选择它有几个实际考量。第一,它有多个独立 UART,一个给 ADS122U04 通信用,另一个留作 Modbus RTU 上报,字段互不干扰。第二,F0 系列是 M0 内核,参考手册和库函数资料丰富,开发效率高,不像某些冷门内核要啃几百页英文手册。第三,它的 3.3V 供电能力和 ADS122U04 的 I/O 电平正好匹配,不需要额外的电平转换芯片。第四,它在 -40 到 85 度工业级温度范围内有完整支持,而且意法半导体的供货相比某些小众品牌稳定得多。
方案里 STM32F071VB 的角色不是“干活”,而是“调度”。它负责上电时序、初始化寄存器、等待 DRDY 信号、读数据、滤波、线性化查表、故障判断,然后通过 Modbus 把温度值上报给 PLC 或上位机。这样的分工让整个系统异常清爽:模拟前端把复杂的事都干完了,MCU 就是个体力劳动者。
2. 测温电路的核心:比例测量、激励电流与冷端补偿
2.1 RTD 比例测量的原理
工业上测温精度要求最高的场景,绝大多数用 RTD(热电阻),尤其是 PT100 和 PT1000。RTD 的阻值随温度近似线性变化,PT100 在 0 度时是 100 欧,到 100 度时大约是 138.5 欧,平均灵敏度约 0.385 欧/度。这个灵敏度看起来很直观,但实际电路设计有个大麻烦:如果直接用恒压源给 RTD 供电,然后测电阻上的电压,那么激励源本身的电压漂移、参考电压的温漂、导线电阻引入的压降都会叠加到测量结果里。
ADS122U04 的架构完美解决了这个问题,它支持比例式测量。做法是用一个内部 IDAC 输出恒定电流流过 RTD,同时让这个电流也流过一颗高精度基准电阻 RREF。ADS122U04 的 ADC 参考电压直接取 RREF 两端的压降,而不是用内部基准。这样算下来,ADC 转换结果是 RTD 电压与 RREF 电压的比值,激励电流的绝对精度被抵消掉了。
用公式表达就是:RTD 阻值 = RREF × V_RTD / V_REF。因为 IDAC 的电流同时流过 RTD 和 RREF,所以电流波动对两个电压的影响是同步的,比值保持不变。这正是 ADS122U04 这类带高精度 IDAC 的 ΔΣ ADC 比“外部基准 + 通用 ADC”方案强的地方。比例测量对激励源的要求直接降了一个数量级,系统长期稳定性显著提升。
2.2 激励电流源 IDAC 和基准电阻的配合
ADS122U04 内置两个 IDAC,每个可以编程输出 250μA、500μA、1mA、1.5mA 等档位。选 IDAC 电流要考虑两个因素:一是 RTD 自热,电流太大会让电阻自身发热,读数偏高;二是信号幅度需要匹配 PGA 增益和满量程范围。
以 PT100 测 0 到 200 度为例,阻值范围约 100 到 175.8 欧。选 500μA 激励电流,RTD 上的压降范围是 50mV 到 87.9mV,PGA 增益设成 32,进入 ADC 的差分信号就是 1.6V 到 2.8V,落在满量程范围内且有良好的信噪比。500μA 流经 PT100 产生的自热功率只有 25μW,对 2mm×2mm 的薄膜热电阻来说几乎可以忽略。
RREF 的选择要保证 ADC 参考电压在 1V 到 2.5V 之间,太低信噪比差,太高会把一部分输入范围吃掉。既然 IDAC 是 500μA,RREF 取 2k 欧就能得到 1V 参考。RREF 的温漂必须足够小,因为虽然比例测量抵消了激励电流的漂移,但 RREF 本身的温漂会直接进入结果。所以我选的是 25ppm/度以下的金属箔电阻或高精度薄膜电阻。RREF 旁边一定要加 π 型滤波器和去耦电容,任何从电源耦合进来的噪声都会直接污染 ADC 基准,这是很多人忽略的地方。
2.3 热电偶测量与冷端补偿的叠加方案
工业 HVAC 里有些场景需要高量程温度,比如监测风管电加热器表面温度、压缩机排气管温度,这时候 PT100 就不够用了,得用 K 型热电偶,量程可以到 -200 度到 1000 度以上。但热电偶输出的是微弱电压信号,约为 40μV/度,而且测量的是“热端与冷端的温差”,必须做冷端补偿。
ADS122U04 的 PGA 最大增益 128 倍,K 型热电偶在常温范围输出约 1mV 到 5mV,放大后正好落在 ADC 差分层。冷端补偿我有两个办法:一个是板载一个高精度热敏电阻或 DS18B20,测冷端温度后由软件查 NIST 多项式做补偿;另一个更高级的做法是利用 ADS122U04 的通道 3 接热电偶的冷端,同时通道 2 接 PT100 作为标准冷端温度传感器,用同一个 IDAC 给 PT100 供电,这样冷端温度测量的精度和 RTD 通道保持一致。
需要特别注意,热电偶的引线阻抗很低,大约几欧,但长长的热电偶线上容易拾取共模干扰。ADS122U04 差分输入本身有共模抑制能力,但 PCB 布线时还是要确保热电偶的负端通过一个 10 到 100nF 电容接地,给共模干扰一个低阻抗泄放路径。我的习惯是热电偶输入对地各并一个 1nF 的 NP0 电容,串联一个 100 欧的电阻,既能抑制射频干扰,又不至于影响测量建立时间。
3. 从寄存器配置到数据流的完整实现
3.1 ADS122U04 初始化流程与命令格式
ADS122U04 的初始化其实不复杂,但每一步都有它的意义。我的推荐流程是:上电后先等 1ms 让电源稳定,然后发 RESET 命令复位芯片,再写四个配置寄存器,随后等待 DRDY 拉低表示转换完成,最后循环读 3 字节转换结果。
芯片用 UART 协议通信,帧格式在数据手册里有明确规定,我这里以一个典型的 PT100 比例测量配置为例说明寄存器设定思路。寄存器 0 配置 MUX 选 AIN0 和 AIN1 作为差分输入,PGA 使能且增益设为 32 倍。寄存器 1 配置数据速率选 20SPS,连续转换模式,基准电压源选择外部基准输入 AIN2 和 AIN3。寄存器 2 配置 IDAC1 开启并设为 500μA,IDAC1 输出接到 AIN2 的基准电阻上端。寄存器 3 配置 IDAC1 路由到 AIN0,也就是让激励电流从 AIN0 流向 RTD。
对应代码里我会封装一个 send_command 函数,把写寄存器的命令组装成 UART 帧发送出去。下面这段代码是 STM32 侧初始化 ADS122U04 的骨架:
void ADS122U04_Init(void) { uint8_t cmd_reset[] = {0x06, 0x00}; /* 按数据手册定义RESET命令字 */ uint8_t reg0 = 0xB0; /* MUX=AIN0-AIN1, PGA on, GAIN=32 */ uint8_t reg1 = 0x20; /* 20SPS, continuous, Vref=ext(AIN2-AIN3) */ uint8_t reg2 = 0x04; /* IDAC1 on, 500uA */ uint8_t reg3 = 0x01; /* IDAC1 routed to AIN0 */ USART_SendBytes(&huart1, cmd_reset, sizeof(cmd_reset)); HAL_Delay(2); ADS122U04_WriteReg(0, reg0); ADS122U04_WriteReg(1, reg1); ADS122U04_WriteReg(2, reg2); ADS122U04_WriteReg(3, reg3); } void ADS122U04_WriteReg(uint8_t regAddr, uint8_t value) { uint8_t frame[3]; frame[0] = 0x40 | (regAddr & 0x03); /* WREG命令字 */ frame[1] = 0x00; frame[2] = value; USART_SendBytes(&huart1, frame, 3); HAL_Delay(1); }请注意,芯片数据手册不同版本对命令字的位定义可能略有差别,真正做产品时务必按你手头那颗芯片对应的手册第 8 章来核对命令字节,不要照抄我这组十六进制数。寄存器配置的核心思想比具体数值更重要:你要理解每个位控制的是通道选择、增益、基准还是激励电流,这样哪怕换了一颗不同封装的 ADC 也能快速迁移。
3.2 DRDY 信号与读取时序
ADS122U04 转换完成时会通过 DRDY 引脚输出一个低电平脉冲。我习惯把 DRDY 接到 STM32F071VB 的一个 GPIO 中断引脚上,下降沿触发。这样 MCU 不需要一直轮询,数据就绪时自动被唤醒,既省 CPU 又省电。中断里只做一件事:置一个标志位,等到主循环里再发起 RDATA 命令读取转换数据。千万不要在中断里直接调 UART 发送和接收,UART 收 3 字节虽然快,但中断里做耗时的操作会和主循环的模块逻辑打架,这在实时性要求高的 Modbus 上报场景里会出大问题。
读取转换数据的代码也很简单:
uint32_t ADS122U04_ReadData(void) { uint8_t cmd[] = {0x10}; /* RDATA命令字 */ uint8_t buf[3]; uint32_t raw = 0; USART_SendBytes(&huart1, cmd, 1); HAL_Delay(2); USART_ReceiveBytes(&huart1, buf, 3); raw = ((uint32_t)buf[0] << 16) | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2]); return raw; }读出来的 24 位原始值是二进制补码格式,需要把它转成实际电压再映射成温度。有符号转换我在代码里做了处理,然后通过查表或分段线性插值得到温度值。ADS122U04 的满量程是 ±VREF / GAIN,所以电压 = raw × VREF / (GAIN × 2^23)。以 VREF = 1V、GAIN = 32 为例,1 个 LSB 对应的电压约为 3.7nV,对应到温度约为 0.00001 度级别,远高于 PT100 本身的精度极限。
4. 实测、标定与常见问题排查
4.1 性能标定与误差校准
不管 ADS122U04 的指标多漂亮,实际系统最后还是要靠标定说话。我板子做回来后先做“零点和满量程校准”。零点校准比较简单,把 PT100 换成一个 100 欧 0.01% 精度的标准电阻,记录 ADC 原始读数,这就是 0 度对应的点。满量程我用一个精密电阻箱,依次设置 100 欧、138.5 欧、175.8 欧,分别对应 0 度、100 度、200 度,记录读数。
标定的核心是消除系统固定偏移和增益误差。每一块板子因为 RREF 精度、PGA 失调、布线差异,都会有个别偏差。用两点校准后,在 0 到 200 度范围内做五点验证,我的实测结果是最大误差小于 0.1 度,大部分点能控制在 0.05 度以内。这个精度在工业和 HVAC 场景里已经完全够用,甚至超出了很多温度变送器的指标。
4.2 典型故障与排查表
我调试过程中踩了不少坑,整理成一张排查表,供大家参考。
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 读数恒定不变 | ADS122U04 未收到命令,或 UART 波特率不匹配 | 用示波器查 TX/RX 波形,核对波特率是否一致 |
| 读数跳变巨大且无规律 | 输入悬空、IDAC 未建立连接、基准电阻虚焊 | 先用万用表查 RTD、RREF、IDAC 通路的连续性 |
| 某个通道读数偏大 | 相邻通道间有 PCB 串扰,模拟地与数字地处理不当 | 检查模拟输入走线是否与数字线交叉,必要时加大地间距 |
| 温度读数有固定偏差 | RREF 精度不够,或两点校准未做 | 换更高精度 RREF,重新标定 |
| 读数随环境温度漂移 | PGA 失调、冷端补偿未启用 | 做温度循环老化后校准,检查补偿算法 |
| 通信失败但 UART 波形正常 | 芯片处于 sleep 模式,或命令帧里 CRC/校验字段不对 | 发 WAKEUP 命令,逐字节核对命令帧格式 |
| 上电后 ADC 无响应 | RESET 后等待时间不足 | 复位后至少延时 2ms,确保芯片稳定 |
4.3 布线、滤波与长期可靠性心得
最后聊几条我在实践中的体会。第一,ADS122U04 的模拟输入对噪声非常敏感,RTD 引线一定走差分对,等长、靠近、远离数字信号。电源部分我用了一个低噪声 LDO 单独给模拟侧供电,LDO 输出并接 10μF 钽电容和 100nF 陶瓷电容,实测噪声明显降低。第二,IDAC 的电流路径上不要串任何不必要的东西,RTD 和 RREF 的连接点要尽量靠近 ADC 引脚,减少寄生电阻和寄生热电势。
第三,也是最重要的一点,工业现场的长期稳定性靠的是“低漂移设计”,不是靠算法硬扛。选择 ADS122U04 本身就是冲着它的内部基准和 IDAC 的低温漂指标去的,但外围元件的温漂同样不可忽视。RREF 我用的是 25ppm 的精密电阻,RTD 和 RREF 的焊盘下面不要铺大面积铜,否则会影响热传导平衡。我做了一个温度循环实验,板子在 5 度和 55 度之间循环 100 次,最大零点漂移只有 0.02 度,说明整体方案的温漂控制是到位的。
还有一个非常容易被忽视的问题:ADS122U04 的 UART 帧通信没有校验位时,偶尔会出现数据错位。因为我用的是固定四次读取的协议,一旦某次 UART 字节丢失,后续数据流就会错位。解决方案有两种:一是在帧里加上校验字段,二是每次读取前先检测 DRDY 信号,如果等待超时就自动重发 RDATA,保证数据流重新对齐。我两种方法都做了,强烈建议至少用一种,否则在电磁环境复杂的现场会偶发读到完全离谱的温度。
最后再分享一个小技巧:给 STM32F071VB 的固件加一个“自诊断”逻辑,定时每隔 30 秒把 ADS122U04 的输入通过寄存器配置切换到内部测试通道,读一次已知的参考电压源,判断 ADC 链路是否健康。这个功能看起来简单,但在远程无人值守的 HVAC 设备上特别有用——如果 ADC 坏了,系统能及时上报“温度链路异常”,而不是傻乎乎地报一个漂移的温度值把运维工程师骗到现场。