ADS122U04+STM32L073RZ高精度工业温度采集方案
做温度和暖通空调HVAC项目的人应该都体会过这种尴尬传感器明明选的是高精度型号主控也算力充足但实测温度飘得就像在跟你玩躲猫猫。尤其是工业现场和暖通末端长线缆、变频器干扰、电网波动、冷端温度漂移任何一个环节都能把“高精度”三个字变成笑话。我最近刚完成一个基于ADS122U04IPWR和STM32L073RZ的温度采集方案专门用来覆盖工业空调箱、冷水机组和风管温度监控这类场景。ADS122U04IPWR 是一颗带 UART 接口的 24 位 Δ-Σ ADCSTM32L073RZ 则是一颗主打超低功耗的 Cortex-M0 单片机。这两个器件组合起来既能伺候 PT100/PT1000 热电阻也能接热电偶和 NTC采集链路干净利落通信布线还特别简单。这篇就把我的选型思路、硬件接线、寄存器配置、校准方法和调试踩坑一并写出来给正在做同类测量方案的朋友一个可复现的参照。1. 先聊聊工业和 HVAC 对温度测量的真实需求很多人以为测温就是把传感器往被测物体上一贴然后读个数。实际去现场跑一遍就会发现事情远没有那么简单。工业机柜里的电机绕组温度、压缩机排气管温度、液压系统回油温度这些点往往远离主控板线缆要走上好几米甚至十几米。线缆一长问题就来了一是线路电阻会带来附加误差二是工业环境里的变频器、接触器会产生强烈的电磁干扰三是传感器本身的非线性需要处理。HVAC 领域稍微温和一点但也同样有痛点冷冻水进出水温度、风管送风温度、回风温度、表冷器盘管温度这些测量点分散在楼宇各处对功耗、布线和维护成本都很敏感。所以做这类系统的核心思路不是“选一个贵传感器”而是把模拟前端、信号调理、数字化转换和主控通信这几个环节整体优化。这也是我选择 ADS122U04IPWR 的根本原因它把多路复用器、可编程增益放大器PGA、24 位 Δ-Σ ADC、激励电流源和 UART 接口全部集成在一颗芯片里相当于把“模拟前端”和“通信接口”打包了。主控端不用再操心模拟电路设计和 SPI 时序抖动直接用 UART 收发命令和数据就行。再配上 STM32L073RZ这颗 MCU 的优势也很明显。它跑在 32 MHz 的 Arm Cortex-M0 内核上有 128 KB Flash 和 20 KB SRAM功耗控制做得相当好。在需要电池供电的 HVAC 温控节点里它可以进 STOP 模式靠 LPUART 或 RTC 定时唤醒把整个节点的平均功耗压得很低。更重要的是它本身就有多个 USART 外设和 ADS122U04 的 UART 接口天然匹配不需要额外搭电平转换或者模拟 SPI硬件上省掉一大截。这套方案最后能做到什么水平拿 PT100 来说在 -50℃ 到 150℃ 的常用区间内经过两点校准后系统级精度可以稳定做到 ±0.1℃ 以内。对于 HVAC 应用这个精度已经远超验收要求对工业现场也能满足绝大多数过程监控的指标。2. 为什么是 ADS122U04 STM32L073RZ 这个组合2.1 选型时对比过的其他方案做方案设计的时候我其实先考虑过两条常规路线。第一条是直接用带温度采集功能的 PLC 模块或者专用信号调理芯片但这玩意单路成本高、通道数固定、灵活性差而且往往需要配套专用总线协议和自研主控对接很麻烦。第二条是采用高分辨率 ADC 加 MCU 的经典组合比如 ADS1220 加 STM32走 SPI 接口这也很常见但在长线缆、高干扰的工业现场SPI 的时钟抖动和主控侧的中断延迟都可能成为噪声来源。相比之下ADS122U04IPWR 用 UART 接口替代 SPI这个设计在我实际项目里带来的好处非常直观。UART 本身就是异步传输对时序的要求比 SPI 宽松得多主控这边不需要用定时器去精确控制时钟。ADC 的转换结果准备好之后通过 DRDY 引脚拉低来通知主控主控在空闲时间读数据就可以这种机制天然规避了 SPI 时序竞争。另外这颗 ADC 内部还集成了激励电流源和低侧电源开关。做 PT100 测量时不再需要外置高精度恒流源电路直接配置内部 IDAC 输出 1 mA 或者 0.25 mA 给热电阻供电配合外部精密参考电阻就能完成比率测量。这个架构不光省元件还顺手把参考电压源的漂移误差消除了后面我会详细展开。2.2 STM32L073RZ 的定位不只是省电STM32L073RZ 在 L0 系列里属于全能型选手。它继承了超低功耗平台的优点但外设配置又很充裕。我在项目里同时用了 USART2 连 ADC、LPUART1 做对外通信还留了 I2C 接口给液晶屏和温湿度传感器GPIO 也够用。这颗芯片带有真正的 EEPROM校准参数可以直接存在片上不用外挂 AT24Cxx。这个细节在量产和现场校准时省事不少每台设备的增益校准值、零点偏移值、传感器类型配置都能独立保存换主控板也能立刻恢复参数。从抗干扰角度看Cortex-M0 的内核虽然简单但跑 Modbus RTU 协议栈、处理 PID 温控逻辑完全够用。工业现场最怕主控处理不过来导致丢数据STM32L073 在 32 MHz 主频下搭配 DMA基本不会出现这类瓶颈。2.3 这套组合的应用范围用这套硬件我做过三种类型的温度采集前端一是 PT100/PT1000 热电阻测量主要用于冷冻水管、锅炉水路、电机绕组这类对精度和长期稳定性要求高的场景。二是热电偶测量配合内部烧毁检测和外部冷端补偿用于压缩机排气管、高温风道等地方。三是 NTC 热敏电阻测量用于风管内部环境温度、回风温度这类精度要求一般但响应速度要快的点位。一颗 ADC 芯片几种传感器类型通吃这在实际项目中降低了不少备货和设计压力。而且 ADS122U04 有四个模拟输入通道可以自己切换测量不同点位扩展性也够。3. 硬件连接与 PCB 布线的关键细节3.1 电源是测量的命脉ADS122U04IPWR 的模拟电源 AVDD 建议接 3.3V 或 5V数字电源 DVDD 可以直接接到 MCU 的 I/O 电压域。我在设计里用了独立的 LDO 给模拟部分供电没有直接拿数字电源裸奔。电源纹波对于 24 位 ADC 来说是个隐形杀手。如果直接拿 DC-DC 的输出给 AVDD 供电开关噪声会通过基准引脚和模拟输入耦合进去最终表现为测量结果上叠加了几十微伏的随机干扰。我实测过用一个纹波 30 mV 的 DC-DC 和一个纹波 2 mV 的 LDO 分别供电同样的传感器最终温度读数波动能差 0.15℃ 左右。所以我的做法是5V 输入先过一级 LDO比如 TPS7A4901 这类低噪声器件得到 3.3V再用 π 型滤波磁珠加电容分别供给 AVDD 和 DVDD。如果项目对功耗要求苛刻可以共用一级 LDO但模拟电源引脚一定要加 10µF 和 0.1µF 并联去耦。3.2 传感器输入端的连接方式传感器输入端的精髓在于“参考地和信号地要单点汇聚”。ADS122U04 的模拟输入是差分的输入引脚 AIN0 和 AIN1 之间测量电压差这样环境中的共模干扰会被抵消掉相当大一部分。以 PT100 四线制连接为例激励电流从 IDAC1 引脚流出经过 PT100 热电阻后回到 AIN2 这个低侧感应引脚。电压采样线从热电阻两端直接引到 ADC 的 AIN0/AIN1 差分输入端。这种四线制接法彻底消除了导线电阻的影响因为采样回路里没有电流流过只有电压信号。如果是三线制 PT100在两个采样线上分别各串一个精密电阻或者靠 IDAC 的对称性来抵消线阻。ADS122U04 的低侧电源开关在这里也很好用测量间歇期把传感器供电切断节省功耗。但是要注意烧毁检测功能需要这个开关配合偏置电流才能工作配置寄存器时别把它关错了。3.3 参考电压的选择我为什么用比率测量做 PT100 的时候我没有用 ADC 内部的参考电压而是把外部精密参考电阻比如 2kΩ、精度 0.1%接在 REFP0 和 REFN0 引脚上让激励电流同时流过参考电阻和 PT100。这样 ADC 输出码值的计算公式里激励电流的大小会直接约掉只剩参考电阻和 PT100 电阻的比值。只要参考电阻的温漂控制好激励电流哪怕从 1mA 漂到 1.01mA对最终电阻计算的影响也微乎其微。这就是比率测量的妙处。3.4 UART 接口的接线ADS122U04 的 UART 接口只有四个关键引脚RST、DRDY、TXD、RXD。按照完整 UART 连接ST 的 TX 接 ADS 的 RXDST 的 RX 接 ADS 的 TXD这是标准交叉。DRDY 引脚要接在 MCU 的一个外部中断输入上。每次 ADC 转换完成后DRDY 拉低MCU 触发中断然后在中断里或者主循环里发命令读数据。这样比轮询方式稳健主控有更多时间处理其他任务也不会因为查询时序不准漏掉转换完成标志。PCB 布线的时候记得给模拟输入引脚和参考引脚留出足够的间距传感器线缆过来之后不要和数字信号线平行走线。我对这块板子做了四层设计给模拟部分专门划了隔离区数字信号线走内层传感器接口安排在板边实测下来 EMC 效果比之前的双面板提升明显。4. 固件实现从初始化到温度换算4.1 STM32 的 UART 外设初始化我用的开发环境是 STM32CubeIDE用 HAL 库跑USART2 作为和 ADC 的通信接口。初始化只要设定波特率、字长、停止位和奇偶校验。ADS122U04 默认支持的波特率可以从 9600 到 262k 之间选我实际用了 115200兼顾速度和稳定性。代码大致长这样void ADS_UART_Init(void) { huart2.Instance USART2; huart2.Init.BaudRate 115200; huart2.Init.WordLength UART_WORDLENGTH_8B; huart2.Init.StopBits UART_STOPBITS_1; huart2.Init.Parity UART_PARITY_NONE; huart2.Init.Mode UART_MODE_TX_RX; huart2.Init.HwFlowCtl UART_HWCONTROL_NONE; HAL_UART_Init(huart2); }特别注意ADS122U04 的默认帧格式里可能包含 CRC 校验位。如果你在寄存器配置里enable了 CRC那 UART 的每个数据帧要多算一个校验字节主控这边要用相同的 CRC 多项式做校验。我的经验是调试阶段先关闭 CRC把通信调通再打开免得把协议问题和硬件问题混在一起分不清。4.2 ADS122U04 的复位与寄存器配置上电后第一步要复位 ADC。通过 RST 引脚拉低至少 17 个 UART 时钟周期再拉高也可以在 UART 发送端口连续发几十个 0x00 字节让 ADC 内部的异步接口重新同步。复位完成后把初始化配置写入寄存器。ADS122U04 有五个配置寄存器核心配置集中在寄存器 0 到寄存器 4寄存器 0 配置输入多路复用器选择哪一个输入端接差分测量比如 AIN0/AIN1 测 PT100AIN2/AIN3 测热电偶。寄存器 1 配置 PGA 增益PT100 用增益 16 或 32 比较合适热电偶则要用 128 倍增益把微弱信号放大。寄存器 2 配置数据速率和转换模式这个要根据系统对实时性的要求来选择数据速率越快噪声越大后面细说。寄存器 3 配置激励电流源的大小和输出引脚PT100 用 1mAPT1000 可以降到 0.25mA减少自热误差。寄存器 4 配置内部温度传感器、低侧开关和 CRC 选项。写入寄存器的时候按芯片手册发送写命令帧命令字节 寄存器起始地址 数据长度 数据。比如我要把寄存器 0 设为 0x32、寄存器 1 设为 0x00、寄存器 2 设为 0x70、寄存器 3 设为 0x84、寄存器 4 设为 0x02就连续发送五组写命令。4.3 PT100 测温的完整流程配好寄存器之后开始转换。先发送启动转换命令等待 DRDY 引脚拉低说明转换完成然后发读数据命令收到的三个字节就是 24 位转换结果需要拼装成有符号整数。int32_t ADS_ReadADC(void) { uint8_t data[4] {0x01, 0x40, 0x00, 0x00}; uint8_t buf[3]; int32_t raw; // 发送读数据命令 HAL_UART_Transmit(huart2, data, 4, 100); // 等待 DRDY 拉低 while (HAL_GPIO_ReadPin(DRDY_GPIO_Port, DRDY_Pin)); // 接收 3 字节数据 HAL_UART_Receive(huart2, buf, 3, 100); raw ((int32_t)buf[0] 16) | ((int32_t)buf[1] 8) | buf[2]; // 24 位有符号数扩展 if (raw 0x800000) raw | 0xFF000000; return raw; }拿到原始码值后先算电阻值。因为用了比率测量公式是R_Sensor R_Ref x Raw / (2^24 x Gain)我这里 Gain 就是寄存器 1 里配的 PGA 增益倍数不是分贝。算出来 RTD 电阻再用 Callendar-Van Dusen 公式换算为温度。对于 PT100在 0℃ 以上区域可以写成R(T) R0 (1 AT BT^2)其中 R0 100ΩA 3.9083e-3B -5.775e-7。解这个二次方程就能得到温度。0℃ 以下还需要加一个 C 系数项。如果嫌公式麻烦很多项目直接用查表法把 -50℃ 到 150℃ 范围内每 0.1℃ 对应的 PT100 电阻值做一张表然后用线性插值查。代码简单执行速度快MCU 的 Flash 也装得下。4.4 热电偶测量和冷端补偿ADS122U04 做热电偶测量时信号源内阻小、输出电压也很小所以要开最大的 PGA 增益同时把输入多路复用器切到热电偶接入的通道。热电偶测温必须要做冷端补偿。我的做法是在接线端子旁边放置一颗高精度 NTC 热敏电阻同时在端子位置测一次温度拿到冷端温度 T_cold。热电偶的热端温度计算公式是T_hot T_cold (V_measured 冷端等效电压) / 热电偶灵敏度更标准的做法是用线性化的多项式先计算出冷端热电偶产生的电压加上实测电压再反查温度。ADS122U04 内置了芯片温度传感器可以用来粗测环境温度但它感知的是芯片自身温度和端子处温度有温差做 CJC 我个人不建议依赖它。热电偶还有一个常见坑断线检测。如果热电偶或者延长线中间断了ADC 输入端会悬空读数变成随机漂移或者直接飘到满量程。ADS122U04 支持烧毁检测内部有上拉/下拉电流源拔掉传感器后能稳定输出一个满量程或者零刻度信号主控就能靠阈值判断“传感器异常”。4.5 低功耗采集模式如果是电池供电的 HVAC 温控节点可以让 STM32L073 进 STOP 模式用 LPUART 或者 RTC 定时唤醒。我实测的功耗数据是ADS122U04 和传感器处于不测量状态时系统整机待机电流约 2.5µA每 10 秒钟唤醒一次完成一次采样和 Modbus 数据上传平均电流约 40µA。两节 AA 电池供电理论续航远超一年。做法就是在测量周期开始时唤醒然后给 ADC 上电、配寄存器、触发转换读完数据、上传完再切回 STOP。低功耗模式下有几个细节要处理传感器供电的 IDAC 电流在测量空闲期要关掉ADC 的低侧电源开关也要断开唤醒后先等电源稳定再启动转换我一般延时 5ms 到 10ms如果使用内部参考也要等参考电压建立稳定否则前几次读数的误差会很大。5. 校准、滤波与精度分析5.1 校准流程的实操步骤24 位 ADC 是精度高但并不代表它不需要校准。芯片本身存在零点失调和增益误差电路板的漏电流和寄生热电势也会引入偏差。实际项目中我用零点校准和两点校准两步搞定。零点校准把 PT100 换成一个精密 100Ω 电阻或者放入冰水混合物中测一组原始码值算出偏移量存到 EEPROM。测量时把这个偏移量从原始值中减掉。两点校准在 0℃ 和 100℃ 使用标准温度源分别记录计算电阻值和实际值的偏差求出一个增益修正系数。修正公式就是R_corrected (Raw - Offset) x KK 标准电阻增量 / 实测电阻增量工业现场没有恒温槽的话可以用高精度电阻箱替代把电阻箱分别设定到 100Ω 和 138.5Ω模拟 0℃ 和 100℃ 的 PT100 输出也能达到同样效果。5.2 数字滤波策略数据速率和噪声是一对矛盾。ADS122U04 在 20 SPS 的低数据速率下双电阻噪声的有效值可以压得很低但系统响应变慢。在 1000 SPS 下响应快了噪声却会明显增大。我的做法是根据不同应用场景来取舍。测量风管温度这种变化缓慢的变量用 20 SPS 加滑动平均滤波每 10 个点取一次平均温度读数的峰峰值波动能控制在 0.02℃ 以内。测量压缩机排气管温度这类快速变化的点位用 175 SPS加一个一阶低通滤波兼顾响应速度和稳定性。在 STM32 上做一阶低通滤波很简单float filtered 0.0f; #define ALPHA 0.1f filtered ALPHA * new_sample (1.0f - ALPHA) * filtered;ALPHA 取 0.1 时滤波时间常数大约在 1/0.1 10 个采样周期左右具体效果需要现场调。5.3 系统级误差来源分析把整个链路的误差拆开看第一项是 ADC 本身的噪声通过低速率和滤波基本可以压掉。第二项是电阻匹配和温漂外部参考电阻选了低温漂 0.1% 精度的金属箔电阻温漂系数 10ppm 左右。第三项是传感器自热PT100 用 1mA 激励时100Ω 电阻上功耗只有 0.1mW影响微乎其微但是 PT1000 用 1mA 激励时功耗有 1mW能引起 0.05℃ 到 0.2℃ 的附加误差如果放在气流中散热好影响小放在密闭管道液体里影响会被放大。所以我的经验是高阻值 RTD 尽量把 IDAC 配到 0.25mA牺牲一点信噪比换稳定性。第四项是连接线缆和端子的热电势。铜和接头之间的热电效应虽然很小但测量温差大于 0.01℃ 时仍然能观察到。为了消除它ADC 的采样速率和架构决定了我们没法完全规避但可以尽量让两个输入端子的温度一致端子排布紧凑避免一侧靠近热源。6. 常见问题与调试经验记录这一节直接把我调试中遇到过的坑列出来每一项都是真实踩过的。读数漂移误差忽大忽小。检查电源纹波和传感器线缆屏蔽层是否接地。我遇到过屏蔽层单端接地没接好结果整个模拟输入悬空示波器上看到 50Hz 工频干扰峰峰值 200mV后来把屏蔽层良好接机壳后读数瞬间稳定。UART 通信偶尔乱码。ADS122U04 对 UART 时序要求没有 SPI 那样苛刻但波特率偏差不要超过 ±2%。检查 MCU 的时钟源如果用了内部 HSI误差可能到 1% 以上我建议直接把 SYSCLK 锁到外部晶振上。热电偶测量读数明显偏低。多半是冷端补偿环节出了问题冷端温度测的是 ADC 芯片温度而不是端子温度。在端子旁边贴一颗完整的 NTC 或者用集成数字温度传感器重新做 CJC问题立刻消失。传感器一拔掉就出现满量程读数重新插上后要很久才恢复。这说明烧毁检测电流源一直在用而且偏置方向反了。把烧毁检测电流方向或者大小重新配置让传感器插回后能快速回到正常测量域。ADC 读数整体偏小而且和线缆长度强相关。多数原因是误用了两线制接法导线电阻分压了激励电压。换成三线或四线制问题解决。低功耗节点的电池续航远低于预期。检查是不是没有关闭 IDAC 和低侧开关测量准备阶段功耗被拉高。我最初就是忘了切低侧电源开关待机电流从 2.5µA 涨到了 1.2mA续航缩水到原来的零头。除了上面这些问题再说一个容易被忽略的点ADS122U04 的 UART 帧格式里命令字节和寄存器地址的组合必须和数据手册完全一致模棱两可就会导致读写错位。我建议调试时先用简单命令读取寄存器值回读确认无误后再去操作 ADC 转换别跳过协议验证直接上数据链路。7. 最后的实操体会和个人建议整套方案做下来我的体会是ADS122U04IPWR 和 STM32L073RZ 的组合最适合那种需要兼顾精度、低功耗和布站灵活性的分散式测温系统。硬件上省掉了外部模拟前端和恒流源软件上只要把 UART 协议跑顺再填好寄存器配置剩下的温度检测就能顺手做得很准。如果你也是第一次用这颗 ADC我建议先拿面包板搭一套最小系统。第一周别追求完美精度先把读码和写寄存器这两个基础动作跑通。第二周再接传感器把电阻计算和温度公式调通。第三周再上滤波和补偿算法。这样分阶段推进出问题的时候定位会快得多。另外板子画好后量产前最好做一轮老化测试。我曾经有一版样机刚上电精度很好跑了 48 小时之后PT100 读数漂了 0.3℃排查下来是 PCB 板材的湿气吸收导致漏电流变化。后续在裸板表面对模拟区域做三防漆涂覆漂移问题就没有再出现。最后分享一个小技巧把校准参数和传感器配置全部存到 STM32L073 的片上 EEPROM然后通过 UART 或者 Modbus 指令在线修改。这样现场换传感器不需要重新烧录程序直接命令行校准后期维护省掉大量工时。这个项目后续我准备把两个测量通道分别接 PT100 和热电偶用同一个 MCU 同时管理再把 Modbus RTU 从站协议加上让楼宇自控系统直接读取温度值。如果你也正在做类似的工作欢迎按这个方案试一下有问题随时对照这篇文章里的寄存器配置和调试思路排查。