基于UART接口ADC与STM32的工业温度采集方案解析
在工业现场和 HVAC 机房里面,测温这件事看着简单,做起来全是细节。传感器在管道里、风柜里、冷却塔旁边,控制器往往在十几米外的电控箱里,中间还要和动力线一起走线槽。这种环境下,SPI、I2C 这种同步接口反而不是最优解,UART 接口的精密 ADC 往往更能派上用场。今天聊的这套组合,是我实际用过并认为很适合这类场景的方案:ADS122U04IPWR 这颗自带 UART 接口的四通道 24 位 Σ-Δ ADC,搭配 STM32L152RE 这颗超低功耗 Cortex-M3 单片机,用来测 PT100、PT1000、NTC 以及热电偶。文章会从为什么选择 UART 接口切入,把传感器接入、硬件接线、寄存器配置、温度换算以及现场调试中的坑都过一遍,希望能给正在做 HVAC 控制器或工业温度采集模块的朋友一点参考。
1. 方案选型:为什么是“UART 接口 ADC + 低功耗 MCU”
1.1 工业与 HVAC 场景对温度采集的特殊要求
先说说场景。空调系统里的送风温度、回风温度、冷热水盘管温度,工业设备里的轴承温度、介质温度、管道温度,这类测量点普遍有几个特点:传感器离主控板有一段距离;现场总线长;环境里变频器、接触器、电机启停带来的电磁干扰不小;而且很多时候系统的可靠性要求是“坏了能查、线少好修”。
温度传感器本身输出的是模拟量,要么是电阻变化,要么是微弱的电压变化,必须经过 ADC 数字化之后才能交给单片机处理。在选 ADC 的时候,大家习惯性先想到 SPI 或 I2C。这两个接口在板级电路里非常顺手,但在“传感器和主控分离”的场景里就会暴露出问题:SPI 需要时钟线,I2C 需要地址和时钟同步,线多不说,I2C 的抗干扰能力也稍微弱一些。UART 则不同,它天生就是为“两个设备之间串行通信”设计的,线少、异步、不需要同步时钟,把波特率配对好就能跑。
UART 还有一个隐藏优势:隔离容易做。工业现场经常要用光耦做电气隔离,UART 的信号是异步电平,只加一个光耦就能把模拟前端和数字控制端隔开,成本和电路复杂度都比同步接口低很多。HVAC 系统里虽然不一定每次都要隔离,但整套方案预留出这个能力,后面真遇到 220V 强电干扰的时候会从容很多。
1.2 把“为什么选 UART”这件事讲透
ADS122U04IPWR 这颗片子最特别的地方,就是它把 UART 直接做进了 ADC 里面。之前很多人对 UART ADC 有偏见,觉得 UART 慢、协议繁琐,不如 SPI 干净利落。实际用下来,测温场景的采样率本来就不高,20SPS 到 200SPS 足够覆盖绝大多数 HVAC 和工业应用,UART 的带宽完全够用,而且换来的好处非常实在。
第一是布线自由度。一个温度采集前端,引脚就那么几个:电源、地、通信线、数据就绪线。UART 只需要一根发送线(漏极开路输出)加一根接收线,如果愿意折腾,甚至可以合并成一根半双工总线。对于很多实测现场来说,少一根线就少一分故障的可能性。
第二是同步问题的简化。SPI、I2C 对时序要求比较严格,长线上时钟边沿容易变形,导致数据错位。UART 是异步的,接收端自己根据波特率采样,只要波特率和布线不是太离谱,几十米内的工业信号线都能稳定跑。再加上 ADC 的 UART 数据速率可以设置在 9600 或 19200 这个档位,抗干扰能力相当理想。
第三是开漏输出的天生优势。ADS122U04IPWR 的 TX 引脚是漏极开路结构,外部上拉之后才能输出高电平。这种结构在隔离和电平转换方面特别灵活,想接光耦就直接把 LED 串在上拉回路里,想切换 3.3V 和 5V 电平就把上拉电阻接到对应电源。这个特性在混合电源域的板子上非常值钱。
1.3 ADS122U04IPWR 与 STM32L152RE 的分工
ADS122U04IPWR 负责的是整个模拟前端:24 位 Σ-Δ 转换、内部 PGA 可编程增益放大器、两个匹配的激励电流源 IDAC、内部 2.048V 基准电压源、内部振荡器,一个片子几乎把传感器需要的所有模拟资源都包圆了。我的理解是,TI 做这颗芯片的定位就是“让主控端只管通信和算法,别去操心模拟链路”。
STM32L152RE 这边,负责的是通信调度、温度换算、控制逻辑、人机交互。选择 STM32L1 系列主要是因为低功耗和控制能力的平衡。HVAC 控制器很多时候需要常年上电,但又不至于跑到纯电池供电场景,L1 系列的低功耗模式可以做到在两次测量之间让单片机进入睡眠状态,定时唤醒读一次 ADS122U04,整体功耗能压得很低。而且 STM32L152RE 集成度不错,512KB 闪存、80KB RAM,跑温度线性化、滤波算法、Modbus 通信协议都绰绰有余,不会把资源卡在“算一个 log”这种小事情上。
这套搭配还有一个实际的好处:开发流程成熟。STM32 用 STM32CubeMX 生成工程,几分钟就能把 UART 和 GPIO 初始化搞定,ADS122U04 的寄存器数量和命令结构也不复杂,固件难度完全在一个 Linux 工程师、单片机工程师或者暖通工程师能快速接受的范围之内。
2. 传感器信号链与计算原理
2.1 PT100/PT1000 三线制:原理与接线
工业上用得最多的温度传感器大概率是 PT100。它本质是一个铂热电阻,0°C 时阻值 100Ω,100°C 时大约 138.51Ω,线性度相当好。测量 RTD 最基础的办法是给一个已知电流,让电流流过电阻,测电阻两端电压,再由电阻反推温度。
两线制最简单,但线缆电阻会直接叠加到 RTD 阻值上。假如导线电阻是 1Ω,PT100 在 0°C 时测出来就是 101Ω,对应温度误差大约 2.5°C,这在工业现场完全不可接受。所以工业上最常用的是三线制或四线制。
三线制的思路是:给 RTD 施加已知激励电流,同时用另外的导线把电流路径上的电压降“补偿掉”。ADS122U04IPWR 内部带两个可编程电流源 IDAC1 和 IDAC2,这两个电流源做成比例式测量特别合适。典型接法是把 IDAC 电流灌进 RTD 后,经过一个参考电阻回到地,AD 转换的结果是 RTD 电压与参考电阻电压的比值,电流源的绝对值漂移就会相互抵消,这是比例式测量的核心优势。配合三线制接法,线缆电阻的影响可以压到非常低。
接线层面,RTD 的 A 端接 IDAC1 输出和 ADC 通道正端,RTD 的 B 端接一根线到 ADC 通道负端,同时从 B 端再引一根线到参考电阻附近的地。测量时先采一次通道正负之间的电压,再采一次补偿通道的电压,软件里做差,就能把两个导线的压降都消掉。这个流程我在后面固件部分会给出代码思路。
PT1000 和 PT100 原理一样,只是 0°C 阻值是 1000Ω,信号幅度大了十倍,激励电流可以小一些,自热效应也更低。HVAC 和工业场合如果传感器距离不远,用 PT1000 会更省功耗。
2.2 NTC 热敏电阻的接法
HVAC 领域大量使用 NTC 热敏电阻,尤其是 10kΩ@25°C、B 值 3435 或者 3950 的规格。NTC 的好处是便宜、响应快、灵敏度高,缺点是严重非线性,而且自热效应需要控制。
NTC 的测量电路最常见的做法是分压器:把 NTC 和一个固定电阻串联,接在电源和地之间,中间节点接到 ADC 输入。选择分压器上电阻值时,需要先估算 NTC 在目标温度范围的电阻变化。比如 10k NTC 在 -40°C 时可能达到 300kΩ 以上,在 100°C 时只有约 1kΩ。如果上面电阻取 10kΩ,那么 -40°C 时输出电压几乎等于电源电压,分辨率很差;100°C 时输出电压又很低。所以要看实际测温区间来选。
如果测温范围是 0°C 到 60°C,NTC 阻值大概在 3kΩ 到 33kΩ 之间,分压电阻取 10kΩ 比较均衡,中间节点电压落在电源的 1/4 到 3/4 范围内,ADC 有效分辨率利用得比较充分。如果是暖通水管温度这种 0°C 到 90°C 的工况,分压电阻可以选 4.7kΩ 或 5.1kΩ。
NTC 换算温度用 Steinhart-Hart 方程:1/T = A + B·ln(R) + C·(ln(R))³。A、B、C 可以由厂商给的三个温度点阻值反推,也可以直接用 B 值公式做近似。工程上更可靠的做法是整理一张“阻值-温度”查表,再在代码里做线性插值,速度和精度都容易控制。
2.3 热电偶与冷端补偿
工业场景里测量几百度到上千度温度时,PT100 就不太合适了,要用 K 型、J 型热电偶。热电偶输出的是两种不同金属接触产生的热电势,电压非常小,K 型大约 40μV/°C,几百度的温差也就几十毫伏。
把热电偶接到 ADS122U04 上,主要靠 PGA 把微弱信号放大。如果把增益设在 32,内部基准 2.048V 对应的满量程大约是 64mV,K 型热电偶在 0 到 1200°C 的范围内基本能覆盖。热电偶没有自带激励,不需要开 IDAC。
热电偶绕不开的是冷端补偿。所谓冷端就是热电偶信号进入 PCB 的接线端子,这个端子的温度会变化,必须在靠近接线端子的位置再测一次温度,然后在软件里把冷端温度对应的热电势加回去。ADS122U04 有四个输入通道,正好一个通道测热电偶,另一个通道接 NTC 或者二极管测冷端温度,轮流用多路复用器切换测量。
当然,如果整套系统只需要测 PT100 和 NTC,热电偶可以暂时不接。但是方案设计之初知道 ADC 支持这个模式,后面产品扩展的时候就不用换硬件,这也是我选四通道 ADC 的原因之一。
2.4 配置原则:激励、增益与数据速率
配置 ADS122U04 的核心其实是三个参数:激励电流、PGA 增益、数据速率。
激励电流决定传感器上的信号幅度,也决定自热效应。PT100 用 1mA 或者 500μA 比较合适,PT1000 用 250μA 或 500μA,NTC 用 50μA 到 100μA 就够。电流源的输出范围要注意,如果传感器阻值太大,IDAC 会把电压顶到接近电源轨,这时候信号反而削顶。常见配置是让传感器最大阻值乘以激励电流后,输出电压不超过参考电压的一半。
PGA 增益要看传感器最小信号和满量程参考值。PT100 在 0°C 时是 100Ω,1mA 激励下只有 100mV;把增益设为 8,满量程大概是 2.048V/8=256mV,信号占满量程约四成,分辨率和线性度都不错。NTC 分压器出来的信号本来就是 0 到 3.3V 级别的,增益设 1 就够了,开增益反而容易饱和。
数据速率这块,ADS122U04 内部的数字滤波器会跟着速率变化,速率越高有效分辨率越低。测温场景没必要追求 1000SPS,20SPS 或者 45SPS 已经能让 24 位精度发挥出实际效果,还能有效压制 50Hz 工频干扰。这个取舍我在调试部分还会再提。
3. 硬件连接与 PCB 布局
3.1 ADS122U04 引脚级接线
ADS122U04IPWR 是 TSSOP-16 封装,IPWR 后缀里 I 代表工业级温度范围,PWR 代表 TSSOP 封装加卷带包装。引脚不多,但接线有几个容易出错的地方。
我这里给出一套比较常用的连接关系,具体引脚编号请以官方数据手册为准,我当初画板子时也踩过“想当然接引脚”的坑,所以建议各位一定对着手册核实:
| 信号 | 连接对象 | 说明 |
|---|---|---|
| AIN0 | RTD 正端或传感器信号正端 | 第一输入通道 |
| AIN1 | RTD 负端或传感器信号负端 | 第二输入通道 |
| AIN2 | NTC 分压点或参考电阻高侧 | 第三输入通道 |
| AIN3 | 备用通道或冷端 NTC | 第四输入通道 |
| AVDD、DVDD | 3.3V | 模拟和数字电源 |
| DGND、AGND | 系统地 | 单点接地 |
| TX | 通过上拉电阻后接 STM32 的 RX | 漏极开路输出,必须有上拉 |
| RX | 接 STM32 的 TX | ADC 的接收端 |
| DRDY | 接 STM32 的 GPIO 输入 | 数据就绪信号,低有效 |
| MODE | 接 VDD 或 GND | 决定波特率/唤醒方式,需要按手册接 |
我当时是把 ADS122U04 放在模拟前端板上,STM32L152RE 放在主控板上,两块板之间只有三根线:地线、UART 发送线、接收线。DRDY 如果距离远也可以不用线直连,改用轮询状态寄存器,但轮询会占用通信时间,能直连的时候尽量直连。
3.2 电源、去耦与参考电压
ADS122U04 支持 2.3V 到 5.5V 供电,STM32L152RE 是 1.8V 到 3.6V,通常两者都跑 3.3V。画板的时候要给 AVDD 和 DVDD 分别加 100nF 陶瓷电容和 10μF 电解电容去耦,电容尽量靠近电源引脚。模拟电源和数字电源可以从同一个 3.3V 出来,但 PCB 上要走星形连接,避免数字电路开关噪声从电源路径耦合进模拟部分。
ADC 内部基准电压是 2.048V,短距离、温度变化不大的情况下直接用内部基准即可。做 RTD 比例式测量时,不需要太纠结基准的绝对精度,因为比例式测量的本质是“传感器和参考电阻共用一个电流源”,基准电压的任何漂移都会被比值抵消。外部基准只有在宽温范围、追求超高精度时才必要,而且要用精密基准芯片,工程成本会高不少。
参考电阻 RREF 的选择也很关键。如果要让 ADC 的基准电压正好等于 2.048V,而 IDAC 设置成 1mA,那么 RREF 应该是 2.048kΩ,可以用 2kΩ 标称电阻再加软件校准。实际项目里我常常用低温漂的精密电阻,比如 25ppm/°C 以下的,而不是普通厚膜电阻,否则温漂会直接影响电阻换算结果。
3.3 隔离和电平转换的做法
UART 接口做隔离非常顺手。一个典型的光耦隔离接线是:STM32 的 TX 经过光耦 LED 驱动,输出接到 ADS122U04 的 RX;ADS122U04 的 TX 是漏极开路,输出经过另一个光耦 LED 和上拉,传到 STM32 的 RX。两个光耦各占一个通道,成本不过几毛钱,却能把模拟前端和主控之间的地电位彻底断开,解决接地环路和共模浪涌问题。
有一点要特别注意:光耦本身有延迟,会影响波特率的裕量。使用普通 EL357N 或 TLP281 这类光耦时,波特率最好不要超过 38400,更保险的做法是用 9600 或 19200。ADS122U04 和 STM32L152RE 内部都带误差容限,低速上非常稳定,所以测温系统完全没有必要跑高速串口。
如果不需要电气隔离,只是两块板电平不同,那就用 TXB0104 这类电平转换芯片,或者在 MCU 端配置开漏输出加上拉,也能解决。
3.4 MODE 引脚、波特率和上拉电阻
ADS122U04 的 MODE 引脚是上电时必须正确配置的引脚。它决定了 UART 的通信速率档位,也会影响一些唤醒特性。有些工程师懒得看手册,直接悬空,结果串口连不上,查了半天才发现 MODE 电平不对。我自己的习惯是接一个 100kΩ 下拉电阻到地,再在 PCB 上留一个 0Ω 电阻跳线位,方便切换到另一个档位。
TX 上拉电阻也不能省。ADS122U04 的 TX 引脚作为漏极开路输出,如果没有上拉电阻,总线一直处于低电平,MCU 永远读不到高电平的起始位,自然没有任何数据。上拉电阻的值常用 10kΩ,如果只接一颗 ADC,5.1kΩ 到 20kΩ 都可以,但要考虑上拉速度和总线电容的平衡。我在调试时先用 10kΩ,确认波特率能稳定跑 9600 之后再根据示波器波形微调。
另外一个容易忽略的是接地。UART 看似只有两根信号线,但地线必须和两个板卡可靠连接。没有地线的串口,数据线会变成参考地,通信要么完全不行,要么偶尔乱码,而且会随着负载启动时好时坏。这个现象在变频器启动瞬间特别明显,属于现场最容易排查不出来的问题时大半都能归到这个原因。
4. STM32 固件实现:从串口到温度值
4.1 初始化 UART 和 DRDY 引脚
STM32L152RE 使用 STM32CubeMX 配置非常方便。我通常把 USART2 作为 ADC 的通信口,波特率设置成 9600 或者 19200,8 位数据、1 个停止位、无校验。如果传感器板离主控板十几米,我可能会把波特率进一步降到 4800,反正测温数据量很小,慢一点无所谓的。
初始化代码大致是:
huart2.Init.BaudRate = 9600; 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);DRDY 引脚我一般接到一个 EXTI 外部中断输入,比如 PB0。ADS122U04 的 DRDY 是低有效,转换完成时拉低,MCU 在中断里设置一个标志位,主循环看到标志位就发起数据读取。这样不会因为轮询错过转换完成时刻,也不会频繁占用 CPU。
如果板子上已经用掉了所有 EXTI 引脚,也可以轮询读取状态寄存器的 DRDY 位,但要注意每次通信都有延迟,轮询周期和转换速率要匹配,否则容易丢数据。
4.2 配置 ADS122U04 的寄存器
ADS122U04 的 UART 通信格式是主机发起命令,从机响应。命令包括 NOP、读寄存器、写寄存器、启动转换、读取数据等。具体的命令字节编码建议查数据手册确认。下面给出我项目里实际用到的写寄存器流程,关键处加了注释。
static uint8_t ADS_WriteReg(uint8_t reg, uint8_t value) { uint8_t cmd[3]; uint8_t resp; // 写寄存器命令体,寄存器地址和命令代码以手册为准 cmd[0] = 0x40 | (reg & 0x1F); cmd[1] = 0x00; // 表示写 1 个寄存器 cmd[2] = value; HAL_UART_Transmit(&huart2, cmd, 3, 100); HAL_UART_Receive(&huart2, &resp, 1, 100); return resp; // 通常为应答字节 }配置顺序也很重要。我一般是先停止转换,再写寄存器,最后启动转换。这样能避免转换过程中寄存器被改动导致时序混乱。典型配置如下:
- 输入多路复用器选择需要的通道
- PGA 增益按传感器类型设置
- IDAC 电流设置为 1mA 或 500μA
- IDAC 输出路由到对应传感器引脚
- 内部基准开启,数据速率设为 20SPS 或 45SPS
启动转换后,等待 DRDY 拉低,即可读取数据。整个过程比 SPI ADC 繁琐不了多少,只是多一步“等待应答”的时间。
4.3 转换结果的读取与拼接
ADS122U04 是 24 位 ADC,一次转换结果会通过 UART 以多字节形式返回。我通常发送一次读取数据命令后,连续接收 3 个数据字节,再接收 1 个状态字节。状态字节里能看出输入是否超量程、数据是否有效,调试时非常重要。
static uint32_t ADS_ReadRaw(void) { uint8_t buf[4]; uint32_t raw; HAL_UART_Transmit(&huart2, &read_cmd, 1, 100); HAL_UART_Receive(&huart2, buf, 4, 100); // 根据数据手册确认三字节顺序和符号扩展 raw = ((uint32_t)buf[0] << 16) | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2]); if (buf[3] & 0x80) // 假设该位代表超量程 { // 做异常标记,后续程序去处理 } return raw; }这里有个容易踩的坑:三个数据字节拼接时,要注意 ADC 输出的格式是有符号还是无符号。24 位 Σ-Δ ADC 常用二进制补码输出,满量程一半的地方是 0x800000 跳到 0x7FFFFF,如果软件里按无符号整数处理,负数温度附近会直接算出个很大的正数。我第一版固件就是这么翻车的,后来把原始值强制转为有符号整数才算正常。
4.4 从电阻到温度的换算代码
拿到 ADC 原始值之后,第一步是把原始值换算成传感器电阻值。比例式测量下,传感器电阻和 ADC 输出码是线性关系。假设参考电阻为 RREF,ADC 满量程对应 0x7FFFFF,换算公式可以写成:
double adc_ratio = (double)raw / 0x7FFFFF; double r_sensor = adc_ratio * RREF * scale_factor;这个 scale_factor 取决于硬件拓扑、PGA 增益、IDAC 路由方式。我在代码里会把它放到配置表中,方便换传感器类型时直接调整,而不是硬编码成一个魔法数字。
PT100 转温度,可以使用 Callendar-Van Dusen 方程。0°C 以上时:
R(t) = R0 × (1 + A·t + B·t²)
其中 PT100 的 A 约为 3.9083×10⁻³,B 约为 -5.775×10⁻⁷。如果反向求解温度,最简洁的办法是用二分查找或者查表插值。代码里我常实现一个二分查找:
static double rtd_to_celsius(double r) { double lo = -200.0, hi = 850.0; for (int i = 0; i < 50; i++) { double mid = (lo + hi) / 2.0; double rm = 100.0 * (1.0 + A*mid + B*mid*mid); if (rm < r) lo = mid; else hi = mid; } return (lo + hi) / 2.0; }NTC 温度换算我用的是查表加线性插值。先把传感器电阻和温度对照表放在 const 数组里,然后找到两个相邻的电阻区间,线性插值算温度。这样比运行时算 log 快,而且查表数据可以做任意非线性修正,实际工程里比纯公式更好维护。
4.5 滤波和异常值处理
温度信号变化慢,但现场干扰是随机的,所以滤波很有必要。我最常用的是两种:滑动平均和去极值平均。
滑动平均适合平滑细小的噪声,窗口取 4 到 16 个点。对于 HVAC 这种温度每秒变化零点几度的地方,16 点窗口足够,响应延迟也不会感觉很明显。去极值平均适合对付触点抖动、变频器脉冲干扰引起的毛刺,把窗口里最大和最小的点去掉再求平均,效果非常明显。
代码上比较简单:
// 一阶低通滤波 float temp_filtered = 0.0; float alpha = 0.15f; temp_filtered = alpha * temp_current + (1.0f - alpha) * temp_filtered;如果你把窗口设得太大,系统会变得很迟钝。我建议先用真实数据记录下来后观察波形,再决定窗口大小,不要一上来就套一个大窗口。
5. 现场调试与常见问题排查
5.1 串口无应答的四个坑
第一个坑就是 TX 引脚忘了上拉,前面已经提过。ADS122U04 的 TX 是漏极开路,悬空时电平不定,MCU 收到的全是低电平,就像不停收到数据。用万用表量 TX 对地电压,如果一直是 0V,说明上拉没接或者接错了。
第二个坑是 MODE 引脚配置和波特率不匹配。上电时 MODE 是高低电平决定通信速率档位,而 STM32 的 UART 初始化波特率是固定的。两边如果对不上,发送出去的数据在 ADC 看来全乱码,ADC 不会响应任何命令。检查方法是用逻辑分析仪抓 MCU 发出去的命令波形,解码出波特率,再和 ADS 的 MODE 档位比对。
第三个坑是上电时序。STM32 先起来,马上给 ADS122U04 发命令,但 ADC 复位还没完成,第一个命令就直接被丢掉了。稳妥的做法是 MCU 上电后延迟 100ms 以上,再对 ADC 做一次 NOP 命令或者读 ID 寄存器,确认通信正常后再继续。
第四个坑是半双工总线冲突。如果为了省线把 MCU 的 TX 和 RX 并到一起,但 MCU 的 TX 没有设为开漏模式,那么 MCU 要发数据时会把总线硬拉到高电平,同时 ADS122U04 想回数据时又拉低,两边直接短路。这个坑在代码里不容易看出来,必须要让 TX 输出模式改成开漏,或者干脆用两线方案。
5.2 温度读数乱跳怎么办
读数乱跳,第一件要检查的是电源噪声。ADC 的 AVDD 如果和继电器驱动共用一个电源轨,继电器吸合瞬间的电流冲击会把模拟电压拉出毛刺,转换结果就会跳。处理方法是给 ADS122U04 单独加 LC 滤波,或者在 PCB 布局上把模拟电源和数字电源完全分开。
第二件是增益设置不合适。比如 NTC 分压器输出是 0 到 3.3V,你把 PGA 增益设成了 8,信号直接饱和,读数反而变成满量程附近乱跳。正确的做法是先估算信号范围,再选择增益,确保最大输入电压不超过满量程的 80% 左右。
第三件是 IDAC 电流设置太大导致传感器自热。PT100 在静止空气中如果通过 1mA 电流,自身温升可能达到零点几度;在风道里不明显,但放在密闭管道里就会看到读数随流速变化。如果调试时发现 0°C 恒温下读数偏高,而且随环境中空气流动有明显变化,那基本上可以断定是自热效应。解决办法是把电流从 1mA 降到 500μA 甚至 250μA,用提高 PGA 增益来补偿信号幅度。
第四件是线路接触不良。工业现场端子排的氧化、松动会形成热电势,而且这种干扰是随机的,AD 测量会表现出“某个方向上跳到特定值”的现象。排查方法很简单:把传感器拆下来,直接接一个已知的精密电阻,看看读数是否稳定。如果接精密电阻就稳定,那问题就在传感器和线缆上。
5.3 比例测量与参考电阻带来的偏差
比例式测量的好处是抵消电流源漂移,但前提是参考电阻本身的温漂必须足够低。曾经有一版设计用了普通 1% 电阻,标称 2kΩ 但温漂达到 100ppm/°C,结果系统在高温环境下读数整体偏移,一开始我怎么也找不到原因,后来用台式万用表量出参考电阻随温度变化了将近 4Ω,才意识到是这个电阻的问题。
换成一枚 25ppm/°C 或者 10ppm/°C 的精密电阻之后,问题立刻消失。所以在 BOM 里,ADS122U04 旁边那几个电阻电容千万不要为了省几分钱用普通货,精密电阻看起来贵,但能省掉大量调试工时。
另外,三线制 RTD 的补偿算法不能在软件里省略。有些工程师直接用两线制公式计算还要怪硬件不好,实际上三线制是把两个电流路径之间的压差通过通道切换和软件减法消掉了。这个减法如果没做,线缆电阻误差会直接进入最终温度,现场走线越长越明显。
5.4 逻辑分析仪和示波器排障
排查 UART 通信问题,最好用的工具是逻辑分析仪。几十块钱的逻辑分析仪就能解码 9600 波特率的 UART 数据。把探头夹在 ADS122U04 的 RX 引脚上,抓 MCU 发出的命令,看解码出的十六进制数据是否和代码里预期的命令字节一致。再夹在 TX 引脚上,看 ADC 有没有应答字节和转换数据。
示波器主要看波形完整性。正常的 UART 波形,空闲电平为高,起始位低电平,停止位回到高。如果 TX 上拉电阻太大,总线电容又偏高,波形的上升沿会变得很缓,接收端采样时可能采到错误电平。把上拉降到 4.7kΩ 或者 2.2kΩ,往往能明显改善长线通信的稳定性。
除了波形,还要看 DRDY 时序。如果 ADS122U04 的转换速率是 20SPS,DRDY 每 50ms 拉低一次,但 MCU 的中断响应偶尔延迟,读取命令发出时可能已经错过了 DRDY 的下降沿。这时候要么缩短中断延迟,要么改用查询状态寄存器的方法。实际项目中我就是把 DRDY 中断优先级调到最高,然后阻塞式读取数据,确保每次都能赶上。
6. 做完这个项目之后我的一些体会
如果非要提炼几条经验,我首先想说的是:ADC 的精度永远不是靠一颗芯片就能保证的,电源、参考电阻、布线、接地、软件滤波,每个环节都会拉低最终精度。ADS122U04IPWR 和 STM32L152RE 这对组合,真正帮你省掉的是“模拟前端设计”的复杂度,而不是让你无视模拟设计的基本功。
其次是不要把 UART 当成一个“慢速落后”的接口。在工业温度测量的带宽下,UART 的优势——长线、易隔离、抗干扰——是实打实的。选型的时候多想想物理场景,多想想线缆怎么走,比单纯看接口速率更有价值。
最后建议大家在产品定型前,把传感器型号、量程、现场走线长度、电源环境这几项提前列清楚,再决定激励电流、增益和数据速率。很多项目最后出了问题,都是前期没有约束好这几个参数,导致硬件板子已经做了,软件怎么调都别扭。项目里留好跳线选择、软件配置表,趁早做一轮温度校正,后面量产和现场维护都会非常顺利。