最近整理了一套给 HVAC 项目用的温度采集小系统,主控是 STM32L031C6,测温前端用的是 ADS122U04IPWR。这套组合实际跑起来相当稳,也解决了不少工业温度采集里的实际问题。ADS122U04IPWR 是一颗 24 位 Δ-Σ ADC,最大特点是带 UART 接口,内部集成了 PGA、低漂移基准和可编程激励电流源,接 PT100、PT1000 这类电阻式传感器特别顺手;STM32L031C6 则是 ST 低功耗 Cortex-M0+ 系列,32KB Flash、8KB SRAM,跑一个 UART 测温协议非常轻松。这套组合不只适合 HVAC 的风管、水管温度采集,稍微改一下测温范围也能覆盖大部分工业温度变送器的需求。我把选型、硬件、固件、现场调试这几个环节完整跑了一遍,其中有些细节翻手册翻了几遍才想明白,下面直接讲能落地的做法。
1. 这套组合为什么适合工业 / HVAC 温度采集
1.1 从温度和信号幅度反推 ADC 选型
先看应用端的要求。HVAC 里最常见的测温场景是冷冻水管、冷却塔回水、风管送风温度,范围基本在 0 到 100℃ 之间,偶尔要测 -20℃ 的防冻液;工业现场则会更宽一些,可能要测到 150℃ 甚至 200℃。这些场合用 PT100 或 PT1000 最稳妥,精度高、长期稳定性好,比 NTC 热敏电阻靠谱得多。
温敏电阻的输出信号非常小。PT100 在 0℃ 时是 100Ω,到 100℃ 时约 138.5Ω,温度变化 100℃ 对应的电阻变化只有 38.5Ω。如果激励电流取 500µA,电压变化大约是 19.25mV,这个信号直接送 ADC 等于浪费分辨率。所以前端必须带可编程增益放大器,把毫伏级信号放大到接近 ADC 满量程。ADS122U04IPWR 内部集成 PGA,增益最高 128,24 位 Δ-Σ ADC 对 0.01℃ 级别的分辨目标是足够冗余的。
我实测下来,PGA 增益取 16 或者 32 比较合适。以 PT100 在 100℃、激励电流 500µA 为例,RTD 上压降约 69.25mV,经过增益 16 后是 1.108V,信号利用率不错;如果增益取 128,信号饱和风险变大,而且对电源噪声更敏感。这里选 24 位 ADC 的意义不在于把 24 位全部用满,而在于低噪声前端和数字滤波能力。
1.2 UART 接口在隔离和布线上的实际优势
ADS122U04IPWR 和常见的 SPI 接口 ADC 相比,最特别的点就是 UART 接口。SPI 要接 CLK、MOSI、MISO、CS 四根线,隔离难度高,走线距离长一点就容易出现时序问题。UART 只要两根信号线,随便一个几毛钱的光耦或数字隔离器就能跨隔离墙,工业现场把模拟前端和主控隔离开非常常见。
另一个实际好处是,UART 本身对时序要求不高,波特率设 9600 或 19200 时,线缆拉几十米问题不大。ADS122U04 支持主机和从机两种 UART 模式,我最常用的做法是把 STM32L031 当主机,按需要向 ADC 发命令读取转换结果。这样 STM32 可以在两次读取之间进入低功耗状态,配合 L031 的 LPUART,非常适合做电池供电的无线温度传感器。
STM32L031C6 虽然是入门级低功耗芯片,但它有 32KB Flash,跑一个简单的状态机和温度换算算法绰绰有余。ADC 负责模拟量采集,MCU 只做通信和计算,不需要额外用 STM32 内部 12 位 ADC 去硬凑精度。
2. 硬件电路:从引脚连接开始把地基打好
2.1 最小系统接线和电源处理
ADS122U04IPWR 的供电分成模拟和数字两部分。我把 AVDD 接 3.3V,DVDD 也接 3.3V,因为 STM32L031C6 工作在 3.3V,这样 UART 电平直接匹配,不用做电平转换。模拟电源要干净,AVDD 引脚前加了一级 10Ω 电阻加 10µF 电容的 π 型滤波,靠近芯片引脚再放一个 0.1µF 的陶瓷电容。数字电源 DVDD 单独放 0.1µF 去耦即可。
STM32L031 的 USART 引脚我用 PA2 作为发送、PA3 作为接收,分别接 ADS122U04 的 RXD 和 TXD,注意是交叉连接。实际接线表大致如下:
| 信号 | ADS122U04IPWR 引脚 | STM32L031C6 引脚 | 说明 |
|---|---|---|---|
| UART_TX | TXD | PA3 (USART2_RX) | ADC 发送,MCU 接收 |
| UART_RX | RXD | PA2 (USART2_TX) | MCU 发送,ADC 接收 |
| 电源 | AVDD / DVDD | 3.3V | 加 π 型滤波和去耦 |
| 地 | AVSS / DGND | GND | 单点接地 |
如果是电池供电产品,建议在 AVDD 前用低噪声 LDO,不要直接拿 DC-DC 输出给 ADS122U04,否则高频纹波会直接耦合到模拟测量结果里。HVAC 柜内 24V 供电转 3.3V 时,我习惯用 TPS7A 系列 LDO 或者 AMS1117,效果都能接受,关键是后端滤波要做好。
2.2 RTD 传感器的两线、三线与四线接法
RTD 接线方式直接影响测量误差,这是硬件设计里最容易犯迷糊的地方。两线制最简单,但激励电流回路上的两根引线电阻全部串联进测量回路。PT1000 灵敏度约 3.85Ω/℃,如果两根引线电阻一共 0.5Ω,带来的温度误差约 0.13℃,线一长误差就很明显。两线制只适合短距离、对精度要求不高的场景。
三线制是工业和 HVAC 的主流。它的原理是用一根导线承载激励电流,另外两根导线分别走测量高边和测量低边,配合 ADC 内部多个 IDAC 电流源做补偿,可以把大部分引线电阻误差抵消掉。四线制精度最高,在 RTD 根部用独立的四根线,两根给电流、两根测电压,完全没有引线电阻影响,但成本高,主要用于计量级设备。
实测下来,三线 PT100 配合 ADS122U04 两个 IDAC 电流源,在 50 米屏蔽双绞线条件下,温度误差可以控制在 0.2℃ 以内。这个精度对 HVAC 的换热站控制完全够用。如果只是做机房环境温度监测,用两线 PT1000 加校准也可以,省一根线,成本更低。
2.3 比例测量是怎么把温漂“消掉”的
ADS122U04 内部有两个可编程激励电流源 IDAC,这是做 RTD 测量的关键资源。我推荐的做法是把 IDAC 电流同时送往 RTD 和一个外部精密参考电阻 R_REF,用 R_REF 两端的压降作为 ADC 的参考电压。这种做法叫比例测量,推导出来非常漂亮。
ADC 转换结果是输入电压与参考电压的比值:
code / (2^23 - 1) ≈ V_RTD / V_REF
V_RTD = I_IDAC × R_RTD,V_REF = I_IDAC × R_REF,代入后 I_IDAC 直接从公式里约掉了:
R_RTD ≈ (code / (2^23 - 1)) × R_REF
这意味着激励电流源本身的温漂、长期漂移都不会进入最终结果,只要 R_REF 足够稳定,测量就有保证。这是很多新手容易忽略的点,直接用内部 2.048V 基准做参考也能测,但那个 2.048V 基准的温漂和 IDAC 电流温漂会组合起来,误差比比例测量大一个量级。
R_REF 选型上,建议用 0.1% 精度、温漂系数 5ppm/℃ 的金属箔或高精度薄膜电阻。R_REF 取 2kΩ、IDAC 取 500µA 时,参考电压正好 1V,PT100 在 100℃ 经过 PGA 16 倍放大后约 1.1V,信号利用率好,也不容易削顶。
3. 固件开发的三个关键环节:寄存器、通信、换算
3.1 ADS122U04 寄存器配置的几个关键参数
ADS122U04 的寄存器配置要通过 UART 命令写入,配置点无非是输入多路选择器、PGA 增益、数据速率、IDAC 电流和参考源。这里最需要注意的是命令帧格式,不同版本的芯片命令码可能有细微区别,量产前必须对着最新数据手册核对。
我的一套典型配置思路是这样的:输入通道选择 AIN0-AIN1 作为差分对,接三线 PT100;PGA 增益设 16;数据速率设 20 SPS;IDAC 电流设 500µA;参考源设为外部参考,也就是上文的 R_REF 接法。20 SPS 这个速率对 50Hz 工频干扰有很好的抑制效果,HVAC 现场电机、变频器很多,用这个速率比 1000 SPS 稳得多。
配置完寄存器之后,建议马上读回一遍做校验。UART 通信一旦受到干扰,写进去的寄存器值可能是错的,如果直接进入测量流程,报了错误温度很难排查。我在代码里加了读回比对,校验失败就重新初始化,简单可靠。
3.2 STM32L031 的 UART 通信代码与出错处理
STM32L031 的 UART 配置不复杂,波特率设 9600、8 数据位、无校验、1 停止位。下面是主程序调用 ADC 读取的函数框架,命令字节和状态字节的使用以手册为准,代码保留宏定义方便对照查阅。
#define ADS122U04_CMD_READ 0x20 /* 示例值,请按数据手册确认 */ #define ADS122U04_STATUS_ERROR 0x01 typedef struct { uint32_t raw; /* 24 位原始转换码 */ uint8_t status; /* 状态字节 */ } ads_result_t; static void uart_send_byte(uint8_t data); static uint8_t uart_recv_byte(void); ads_result_t ads122u04_read_conversion(void) { ads_result_t res; uint8_t rx[4] = {0}; uart_send_byte(ADS122U04_CMD_READ); rx[0] = uart_recv_byte(); rx[1] = uart_recv_byte(); rx[2] = uart_recv_byte(); rx[3] = uart_recv_byte(); res.raw = ((uint32_t)rx[0] << 16) | ((uint32_t)rx[1] << 8) | rx[2]; res.status = rx[3]; return res; }主循环里不要无脑一直读,建议 500ms 或 1s 采一次,中间让 MCU 进入低功耗或做别的事。如果发现状态字节里报错了,要对这次数据打上无效标记,而不是照样换算温度。这样上位机拿到数据时,不会被一个跳变的坏点误触发报警。
3.3 原始码换算成摄氏度的完整链路
拿到 24 位原始码后,第一步是换算电阻。以比例测量为例,满量程码是 0x7FFFFF 即 8388607,所以:
R_RTD = (raw / 8388607) × R_REF
这个值再换成温度,可以用查表法,也可以用 Callendar-Van Dusen 方程。我比较推荐查表法,把 PT100 的 ITS-90 分度表做成一个 const 数组,每 1℃ 一个点,用二分查找定位,再线性插值。STM32L031 的 32KB Flash 存这个表毫无压力,代码也容易做离线校准。
如果不想查表,0℃ 以上范围可以用简化二次方程:
R = R0 × (1 + A·T + B·T²)
其中 A = 3.9083×10⁻³,B = -5.775×10⁻⁷。反推温度就是解一元二次方程,用 C 语言实现如下:
float pt100_resistance_to_temp(float R, float R0) { float A = 3.9083e-3f; float B = -5.775e-7f; float disc, T; disc = R0 * R0 * A * A - 4.0f * R0 * B * (R0 - R); if (disc < 0.0f) { return -273.0f; /* 无效数据 */ } T = (-R0 * A + sqrtf(disc)) / (2.0f * B * R0); return T; }这里 R0 是 0℃ 时的标准阻值,PT100 取 100Ω,PT1000 取 1000Ω。公式在 0 到 200℃ 范围内实测误差很小,工业和 HVAC 足够用。更严格的场合就查分度表,误差可以压到零点零几度。
4. 实测中反复踩到的坑:通信、精度与低功耗
4.1 UART 通信乱码与开机时序问题
ADS122U04 上电后需要时间稳定内部基准和 IDAC。我最初调试时,STM32 复位后立刻发命令,经常收到一堆乱码或者 0xFF,后来在初始化前面加了 20ms 延时,问题消失。这个延时必须放在 ADC 供电稳定之后,而不是放在 UART 初始化之前,顺序错了效果打折。
另外要注意 UART 引脚的上电状态。STM32 的引脚在复位期间如果被配置成输出高电平,会向 ADC 的 RXD 脚灌入一个毛刺,ADC 可能误判成启动命令。解决方法是先配置 GPIO 为输入,初始化完 UART 之前再加一个短暂延时,让线上电平稳定后再开启外设。这一步在低功耗唤醒时同样重要。
HVAC 柜内动力线多,UART 走线最好加 100Ω 串联电阻和 TVS 管,防止插拔时静电打坏芯片。如果 STM32 和 ADC 之间距离超过 30cm,建议用双绞线并降低波特率到 4800,实测可靠性更好。
4.2 温度读数漂移和高频噪声的排查
最典型的症状是温度值缓慢漂移,而且断电重启后漂移位置不一样。优先怀疑 R_REF 温漂和 RTD 引线补偿不到位。R_REF 如果用了普通贴片电阻,随着板子温度上升阻值变化,直接叠加到结果上就是零点几度的漂移。换成低温漂电阻后,问题基本消失。
读数最后几位跳变属于正常现象,24 位 ADC 的有效精度会受到热噪声影响。软件上做 8 次移动平均能明显改善,代价是响应变慢,HVAC 的场景完全可以接受。如果跳变幅度过大,比如超过 0.1℃,先查电源纹波,再查数据速率是否设得太高,最后检查屏蔽层接地。
还有一种情况比较隐蔽:三线 RTD 的第三根线没接对位置,或者引线压降没有正确补偿,温度会随线缆长度产生固定偏差。这种偏差跟温度大小有关,很难通过简单偏移校准,必须从接线结构上解决。
4.3 低功耗模式下的合理取舍
STM32L031 的低功耗能力很强,Stop 模式电流 1µA 以下。配合 ADS122U04 的睡眠模式,做电池供电的无线温度传感器非常合适。但要注意,进入低功耗前先把 UART 的 TX 引脚拉低,避免浮空电平消耗额外电流,也避免 ADC 误识别。
ADS122U04 从睡眠模式唤醒后,最好先读一次状态寄存器确认真空转换完成,再读取数据。我踩过的坑是,唤醒来不及等稳定就直接读,结果第一帧数据是旧数据或者 0,后面才正常。工业应用中,这种错误如果不处理好,会引起误报警。
低功耗设计不要把功耗目标压得太死,否则唤醒周期变长,温度采样的实时性就差了。HVAC 机房温度变化很慢,60 秒采样一次完全够用。采样瞬间把 MCU 和 ADC 都跑起来,处理完马上睡,平均电流能做到几十微安级别。
5. 一组现场数据与 HVAC 部署经验
5.1 用干井炉标定的数据记录
我在一个换热站项目里用这套方案做了现场标定,干井炉从 0℃ 往上走到 100℃,每隔 25℃ 记录一次数据。截取一组测试手记,仅供参考:
| 标定温度(℃) | ADC 换算电阻(Ω) | 系统显示温度(℃) | 偏差(℃) |
|---|---|---|---|
| 0.00 | 100.05 | 0.13 | +0.13 |
| 25.00 | 109.77 | 24.95 | -0.05 |
| 50.00 | 119.43 | 50.05 | +0.05 |
| 75.00 | 129.05 | 75.02 | +0.02 |
| 100.00 | 138.52 | 100.06 | +0.06 |
这个偏差包含 PT100 传感器本身误差和引线误差,对 HVAC 控制来说完全合格。如果想进一步提高精度,可以在系统里做两点校准,把偏移量和增益误差存到 Flash,实测能把全量程偏差压到 ±0.1℃ 以内。
5.2 现场布线和探头安装的几点经验
风管温度探头要保证风速能吹到感温元件,不能紧贴管壁。水管温度套管要插入管道深度至少 10 厘米,并保证探头周边没有死水区。探头安装完成后,套管外露部分要做保温,否则环境温度会顺着金属套管导热,造成测量偏低或偏高。
信号线远离变频器输出电缆,如果无法避开,交叉时必须直角走线。我见过一个现场,温度线和变频器线捆在一起,开机后温度跳了 2℃,把线分开后立刻正常。屏蔽层必须单端接地,双端接地反而会形成地环路,在雷雨季节更容易出问题。
最后分享一个调试技巧:每次在现场装完,先用万用表测一下 R_REF 实际阻值,把测量值读进程序当作常量使用。PCB 上丝印标称值和实际值总有偏差,哪怕 0.5% 的偏差也会导致最终温度误差超过 1℃,但用实际值校准后,误差能立刻降下来。这个小动作成本为零,但是对精度的影响非常直接。