ADS122U04+STM32L031C6高精度PT100温度测量方案详解

发布时间:2026/11/5 1:03:44
ADS122U04+STM32L031C6高精度PT100温度测量方案详解

做工业现场和 HVAC 设备的温度测量时,我试过好几套 ADC 加 MCU 的组合,最顺手的就是 ADS122U04IPWR 配 STM32L031C6。这套方案的核心优势在于,ADS122U04 自带 24 位 Δ-Σ 调制器、可编程增益放大器和 UART 接口,而 STM32L031C6 又是一颗低功耗、带硬件串口的 Cortex-M0+ MCU,两者搭配起来,既能满足 0.1℃ 级别的测量精度,又能让固件写得很轻松——不需要折腾 SPI 时序,直接走串口命令拿数据。这篇文章就把我从选型、画板到调参、跑现场测试的完整过程拆开讲,包括容易踩的坑和实测表现,给正在做 HVAC 控制器、工业温度变送器或者冷库监控的朋友一个参考。

1. 项目定位与选型逻辑

1.1 这套组合能解决什么问题

工业和 HVAC 场景里的温度测量,通常不是简单读个传感器数值就完事。比如楼宇自控里的风管温度、冷水机组进出口水温、工业机柜内的环境温度、恒温恒湿箱的控制反馈,这些应用对响应速度、长期稳定性、抗干扰能力都有明确要求。环境温度通常要求 ±0.5℃,小型设备可能放宽到 ±1℃,但冷冻水、蓄能系统里的水温测量,往往需要 0.1℃ 或更高的分辨率和稳定性。

用 ADS122U04IPWR 加 STM32L031C6 的组合,就是冲着三个痛点去的:第一,24 位分辨率足够让 RTD 信号在 0~100℃ 范围内轻松分辨 0.01℃ 级别的变化;第二,ADS122U04 内置两个可编程激励电流源和一路高精度基准输入,可以做一个完整的三线制 PT100 测量桥路,不需要外部运放和精密恒流源;第三,ADC 通过 UART 与 MCU 通信,而不是 SPI 或 I2C。

提示:如果你只需要测一路温度,用这套组合确实是“杀鸡用牛刀”,但正因为它的信号链干净,后续要扩展成多通道或者换热电偶、NTC 传感器,硬件和固件框架都不用推倒重来。

1.2 为什么选 ADS122U04IPWR 而不选其他 ADC

对比常见的 ADS1220(SPI 接口)、ADS1115(I2C 接口),ADS122U04 最大的不同就是 UART 接口。UART 在工业现场的实用性很强:线缆可以拉得更长,抗共模干扰能力更好,而且单片机和 ADC 之间不需要同步时钟信号,软件上只要配置好波特率、按帧收发命令即可,省去了一大堆 GPIO 模拟 SPI 的麻烦。

我曾在一个项目里用过 SPI 接口的 ADS1220,结果布线太长导致时钟线反射,数据偶尔错位;换成 UART 版之后,相同长度线缆下再没出现过通信失败。此外,ADS122U04 的指令系统本身也沿用 TI 常见的寄存器读写模式,配置 PGA、基准电压、数据速率都很直接,上手成本很低。

ADS122U04 的功耗在低功耗模式下可以到微安级别,但工业现场一般不在乎这几十毫瓦。更多是为了简化 MCU 侧的协议栈——STM32L031C6 只有 32KB Flash 和 8KB RAM,如果去跑完整的 Modbus 协议再处理高精度的滤波算法,资源会非常紧张;UART 驱动和命令解析只占很少的 Flash,剩下的空间可以放心做线性化、数字滤波和状态机。

1.3 STM32L031C6 的角色

STM32L031C6 是基于 Cortex-M0+ 的低成本 MCU,主频 32MHz,内置多路 UART、12 位 ADC、SPI、I2C,还有 RTC 和多种低功耗模式。在这个项目里,它不负责算温度变换公式——那些数学运算大可以在 PC 端做,也可以让 MCU 做简单的查表。MCU 的主要任务有三个:

  • 通过 UART 周期性发送命令,从 ADS122U04 读取转换结果;
  • 对 ADC 原始码做平均值滤波、剔除毛刺,再乘上比例系数得到电阻值;
  • 根据 PT100 分度表查表得到温度值,或直接调用 ITS-90 公式计算,最后通过 Modbus RTU、4-20mA 或者简单的 PWM 占空比输出。

实际选择 L031 而不是更常见的 STM32F103,是因为项目有低功耗需求,空调控制器往往希望整机待机功耗小于几十毫瓦。L031 的 STOP 模式配合 RTC 唤醒,可以在两次采集之间让系统休眠,大幅降低平均功耗。

注意:如果你的应用不需要休眠,用 STM32F030 或者国产替代芯片也完全够用,核心代码不用改。芯片只是工具,模块化设计才是保证可移植性的关键。

2. 硬件设计与信号链搭建

2.1 传感器类型与接线方式

我这次用的传感器是 PT100 热电阻,三线制接法。为什么选三线制?因为两线制导线电阻直接叠加到传感器电阻上,1Ω 线阻就能造成约 2.4℃ 的误差;四线制最准,但要四根线,工业现场不一定方便。三线制配合 ADC 的差分输入,能把导线电阻的影响抵消掉大部分。

三线制接法的核心思想是这样的:两条线分别接在 ADC 的正输入和负输入侧,第三条线用来提供激励电流回路,通过测量两个输入端的压差,导线电阻上的压降在差分信号中相互抵消。ADS122U04 有两个可编程电流源 IDAC1 和 IDAC2,可以把它们分别接到 RTD 的两个引脚上,然后通过寄存器设置电流方向和大小。通常我设置激励电流为 250μA,这样在 0℃ 时 PT100 电阻为 100Ω,产生的信号大约 25mV,再通过 PGA 放大到合适的范围。

2.2 模拟前端配置与关键器件选择

整个模拟前端其实很简洁:RTD、基准电阻 RREF、两个激励电流源、差分输入滤波电容。ADS122U04 的数据手册里有一个典型应用图,我照着做并做了些优化。

基准电阻的选择直接决定测量的绝对精度。因为 ADC 的转换结果是基于“输入电压 / 基准电压”的比例,也就是数字码 = 输入电压 × (2^23 − 1) / 基准电压。如果基准电压由同一个激励电流源流过 RREF 产生,那么激励电流的漂移会被自动抵消,这种“比率式测量”是 RTD 高精度测量的关键。我选的是 100Ω、精度 0.01%、温度系数 5ppm/℃ 的精密电阻。必须用低温漂器件,否则参考基准会跟着环境温度跑。

输入端的滤波器我用了两个 1nF 的 C0G 电容分别跨接在正负输入到地之间,同时在输入端并联一个 100nF 的差分电容。这样既能滤掉射频干扰,又不会影响信号建立时间。HVAC 环境里常有变频器、继电器、开关电源,这些设备会产生很强的高频噪声,不加滤波的话,24 位 ADC 很容易出现跳动。

2.3 电源、参考地与 Layout 的实战经验

ADS122U04 的供电我用的是一颗 3.3V LDO(比如 TPS7A4901)单独供给 AVDD,MCU 的数字电源用另一路 LDO,两者在 PCB 上分开走线,只在单点通过磁珠相连。数字地和模拟地统一在一个地平面,没有分割,但在 ADC 芯片下方留出完整的模拟地铺铜。很多初学者会画“模拟地隔离岛”,结果产生很大的地回路电感,还不如统一地平面。

我在画 PCB 时特别注意了这几个点:

  • RTD 输入端走线尽量短,且完全对称;线宽至少 0.3mm。
  • 激励电流源的输出管脚与 RTD 之间不要过孔,直接走表层,避免过孔电阻导致电流不平衡。
  • RREF 基准电阻靠近 ADC 的 VREF 输入脚,走线要走 Kelvin 连接,尽量减少引脚电阻的影响。
  • UART 通信线远离模拟输入区,最好用包地处理。

实际打样后,按照这种布局,在 20MHz 干扰源附近测试,ADC 输出码的峰峰值跳动只有 3 个码左右,对应温度约 0.01℃,效果完全可以接受。如果布局乱来,跳动可能到 30 码以上,后面软件再滤波也救不回来。

3. 固件与通信协议实现

3.1 MCU 初始化与 UART 配置

STM32L031C6 初始化不复杂,但有几个容易犯的低级错误。首先是时钟,我习惯用 LSI 或者 HSI 作为 UART 时钟,这样可以不管外部晶振的频率误差。UART 波特率我用 9600bps,为什么不用更高?因为工业现场线缆可能很长,高波特率对线间电容更敏感,而且 ADS122U04 的默认功耗模式下,9600 波特率非常稳定。STM32L031 的串口初始化需要注意:使能 UART 时钟、配置 GPIO 复用功能、设置波特率、字长 8 位、1 停止位、无校验,并使能发送和接收中断。

指令发送前最好预留一段静默时间。ADS122U04 的协议里,每帧指令之间有严格的时序要求,数据手册上写的是指令间隔至少要几个 bit 时间,实际我加了一个 1ms 左右的延时,确保不会粘帧。

3.2 与 ADS122U04 的寄存器配置步骤

ADS122U04 的地地址是固定的(实际上它支持通过 ADS122U04 的 ADDR 引脚设置地址,允许一总线上挂多片 ADC),我做的板卡上只挂一片,所以直接连到默认地址。初始化的寄存器配置顺序如下:

  1. 复位 ADC:发送 RESET 命令,等待 2ms 让内部上电完成。
  2. 配置配置寄存器 0(设置 PGA 增益和通道选择)。PT100 测量时,PGA 增益我设置为 8 倍,因为 RTD 在 0~100℃ 时输出电压范围从 25mV 到约 38mV,8 倍放大后信号幅度约 200~300mV,离满量程还有余量,不会削顶。
  3. 配置寄存器 1(设置数据速率、转换模式)。我使用连续转换模式,数据速率设为 20SPS,这是 50Hz/60Hz 工频干扰抑制效果最好的档位,因为 20SPS 的斩波频率能很好地抑制 50Hz 工频干扰。
  4. 配置寄存器 2(设置激励电流源模式、电流大小)。IDAC1 和 IDAC2 都接到 RTD 的差分输入端,电流设为 250μA。
  5. 配置寄存器 3(设置基准源为外部 REFP/REFN 引脚),因为基准电阻接在 REFP 与 REFN 之间,必须选择外部基准。

写寄存器之后最好读回校验,确保通信正常。我遇到过一次因为片选时间不够导致配置没写入的情况,读回来的寄存器全是 0xFF,排查了老半天。加一段回读比较代码非常有必要。

3.3 数据读取与温度转换计算

连续转换模式下,只需要每隔一段时间发送 RDATA 命令,然后读 3 个字节,合并成 24 位有符号整数。也可以配置为 DRDY 引脚指示数据就绪,用 MCU 的 EXTI 沿中断读取,但我实际用轮询就够,20SPS 转换周期是 50ms,UART 9600 波特率下传 3 字节数据约 3ms,完全够用。

拿到原始码之后,温度计算我分成三步:

  • 第一步,把 24 位补码转成整数,然后除以 (2^23 - 1) 得到归一化比例值。
  • 第二步,用比例值乘以基准电阻值,得到 RTD 当时电阻值。例如 ADC 输出码为 0x1B9F58(约 1810776),比例值约 0.21586,乘以 100Ω 得到 21.586Ω,对应的温度接近 -64℃。这个计算逻辑是比率式测量的直接结果,不需要关心激励电流的具体值。
  • 第三步,根据 PT100 的 Callendar-Van Dusen 公式或查表,得到温度。

为了省 Flash,我没有用浮点公式,而是用查表加线性插值。把 -50℃ 到 200℃ 的 PT100 分度表按 1℃ 一个点存成两个数组(电阻值高 16 位和低 16 位分别存储),再在两点之间做线性插值。实测在 -20℃ 到 80℃ 区间内,插值误差不超过 0.02℃。如果你要求更高,可以直接用浮点库解方程,STM32L031 的 Cortex-M0+ 没有硬件浮点,运算会慢一点,但每秒钟算一次温度完全没问题。

提示:不要一开始就急着写滤波器。先让原始码裸奔,观察 ADC 的噪声水平,再决定是取平均还是用滑动中值滤波。一般来说 8 次平均就能把高斯噪声降 3 倍,但如果现场有尖峰干扰,平均滤波会被拉偏,改用中值滤波更稳。

4. 校准、标定与系统级优化

4.1 单点校准与两点校准的实际操作

任何高精度温度测量系统,除非元器件的基准电阻和 RTD 都是极高精度且互相匹配,否则都需要校准。RTD 本身是标准化的,但 ADC 的增益误差和基准电阻的误差会叠加进去。最简单的做法是单点校准:把 RTD 放入冰水混合物(0℃),读取 ADC 的输出码,反推出基准电阻的实际等效值,以这个值替换理论上的 100Ω。这样一次性抵消了基准电阻误差和 ADC 增益误差在 0℃ 附近的综合影响。

单点校准在 0~50℃ 范围内效果不错,但如果要覆盖到 150℃ 或更高,最好做两点校准。比如 0℃ 和 100℃ 两点,计算出比例系数 k 和偏移 b,然后对所有测量结果做数字修正:

R_true = k × R_raw + b

由于 PT100 的非线性很小(在 0~100℃ 区间内,误差小于 0.4℃),两点校准配合线性修正,可以把剩余误差压到 0.05℃ 以内。我一般会把校准得到的 k、b 存到 STM32L031 的内部 Flash 的独立扇区,在量产时每台设备写一次。

校准过程中还要注意热电势的影响。手捏住探头、仪表自身发热、接线端子之间的温差,都可能产生微伏级别的寄生电动势,在 24 位分辨率下会表现为零点漂移。校准时一定要等待传感器温度稳定,至少恒温 10 分钟再读数。

4.2 HVAC 现场的干扰排查案例

我的客户现场有一台风冷热泵机组,温度板卡装在电控箱里,旁边就是变频器。第一次上电,温度值每隔几秒就会跳一下,跳变幅度大约 0.4℃。我用串口抓原始码,发现出现跳变时正好是变频器切换频率的时刻。问题不是电源,而是变频器的谐波通过空间辐射耦合到了 RTD 的输入线上。

排查思路是逐一排除:先靠近 ADC 输入端加共模电感,效果不理想;然后把 RTD 的屏蔽层又重新接地,也不明显;最后发现是激励电流源输出线太长,形成了一个环形天线。把 IDAC 输出线由两条平行线改成双绞线,并紧贴 PCB 地平面走线,跳变幅度立刻降到了 0.02℃。

另一个 HVAC 常遇到的坑是冷凝水。室内盘管温度探头在夏天会处于接近露点的环境,接线端子氧化后会产生整流效应,导致读数漂移。处理办法是在接线端子涂三防漆,或者直接用环氧树脂把板卡和探头封起来。

4.3 低功耗与平均功耗优化

如果不是做电池供电设备,低功耗优化可以往后放;但很多 HVAC 控制器要求待机功耗低于 0.5W,所以还是要把 MUC 和 ADC 的功耗控制好。STM32L031 可以在采集完数据后进入 STOP 模式,用 RTC 定时 500ms 唤醒一次,唤醒后花 5ms 启动 ADC、读取数据,然后继续睡。ADS122U04 也有断电模式,通过寄存器可以切换待机状态。

实测整机平均电流可以做到 2.3mA,其中 MCU 休眠电流约 1.2mA,ADC 工作时平均电流 0.6mA,UART 和 LDO 静态电流占剩下的一部分。如果还想进一步降低,可以把 MCU 休眠时间拉长到 1 秒,对 HVAC 的温度控制来说,1 秒的采样周期完全不影响控制效果。

5. 常见问题与排查技巧实录

5.1 UART 通信缺失或乱码

症状:发送 RDATA 命令后,MCU 收到的要么是 0xFF,要么是随机数据。第一步检查的是 MCU 与 ADC 之间的 TX/RX 是否接反?这个问题我踩过太多次。ADS122U04 的 SDO 脚应该接 MCU 的 RX,SDI 接 MCU 的 TX。别只顾看丝印,拿万用表二极管档测一下信号链路的通断最靠谱。

第二步检查波特率误差。ADS122U04 的时钟如果是内部振荡器,一般误差在 1% 以内;而 STM32L031 如果直接用 HSI,误差也还行,但要检查是不是把串口外设时钟配错了,导致波特率差了几个百分点。最好在发送命令后,用逻辑分析仪抓一下,看波形高低电平是否规整。

第三步,检查指令间隔。ADS122U04 的数据手册规定连续两条命令之间至少要有一个“静默期”,如果 MCU 连续快速发送,ADC 可能会把第二条命令的前几个字节当作上一个命令的延长而忽略。我在发送每条命令后加 100μs 延时,从此没再丢过字节。

5.2 温度读数漂移,开机一段时间后缓慢变大

这种漂移通常不是 ADC 的问题,而是 RTD 自热效应和芯片温漂共同作用的结果。激励电流越大,RTD 自热越严重。我用 250μA 电流时,在 0℃ 冰水混合物里测到自热温升约 0.03℃,这已经算很小了。如果电流改成 1mA,自热温升可达 0.4℃以上,绝对不能直接用在精密测量里。

另外,PCB 上靠近 ADC 的铜箔如果流过数字信号电流,热量会传导到基准电阻附近,造成基准电阻温度不均匀,从而产生缓变漂移。解决方法是让基准电阻离 ADC 的数字引脚远一点,并在铺铜时把基准电阻下方的铜挖空,减少热传导通路。还有一个简单有效的方法:在固件里做温度漂移补偿,读取 ADC 芯片内部温度传感器(部分型号支持)或者装在同一个区域的 NTC 温度,用查表去修正增益变化。但如果你想达到 0.1℃ 精度,最好还是从热设计上解决,软件补偿是最后的手段。

5.3 高速采样时数据噪声反而更大

有人为了提高响应速度,把数据速率调到 1000SPS,结果发现读数噪声反而变大,温度波动超过 0.1℃。这是正常的,Δ-Σ ADC 在高速率下数字滤波器带宽变宽,对高频噪声的抑制变差。ADI 和 TI 的文档都会给出不同数据速率下的有效分辨率表格,20SPS 时典型有效分辨率能到 20 位以上,1000SPS 时可能只剩下 18 位。

我的做法是把数据速率保持 20SPS,如果系统需要更快的温度响应,可以在 MCU 端采用“滑窗取最近 N 点求平均”的方法,而不是单纯提高 ADC 速率。一般 HVAC 系统的热惯性很大,温度变化本来就慢,20SPS 已经很快了。

6. 实测数据与工程落地建议

6.1 一组在标准恒温槽里的实测数据

我在实验室用 Fluke 恒温槽和二级标准铂电阻做过验证,分别在 0℃、25℃、60℃ 三个点比对:

设定温度本系统读数标准温度计读数误差
0℃0.03℃0.00℃+0.03℃
25℃25.02℃25.00℃+0.02℃
60℃60.04℃60.00℃+0.04℃

这是完成两点校准之后的结果。未校准时,60℃ 点误差大约在 0.2℃ 左右,主要来自基准电阻的初始精度。系统在连续工作 24 小时后,再回查 0℃ 点,漂移小于 0.01℃,说明硬件稳定性不错。

6.2 软件架构上的一点建议

把整个采集任务放到一个独立的文件中,对外提供temperature_get_value()和temperature_set_calib(k,b)这样的 API。这样不管是接 Modbus、4-20mA,还是将来换成热电偶采集,只要改内部实现,对外接口保持不变。STM32L031 的资源虽然可怜,但用来跑一个简单的状态机加环形缓冲队列完全够用。我习惯把最近 16 个温度采样点存成环形队列,每个新数据进来时先校验合法性——比如温度值必须在 -100℃ 到 300℃ 之间——再入队,然后在主循环里对队列做中值滤波,取中间值作为当前温度。这样做的好处是,偶尔的尖峰数据不会直接影响输出,比单纯最大最小剔除更聪明。

6.3 与控制系统对接时的注意事项

最终温度值精度再高,如果输出链路里有环节做了一次舍入或者转成 8 位整型,前面的努力都可能白费。我在给 HVAC 控制器对接时,一般通过 Modbus 寄存器把温度用 0.01℃ 为单位发送,也就是 25.04℃ 发送为 2504。有些第三方上位机软件默认十六位有符号数,如果超过 3276.7℃ 会溢出,但温度通常不会到这个值,没太大问题。

如果直接输出 4-20mA,要仔细校准 DAC 或者 PWM 的零点位置。很多现场问题不是温度测量不准,而是转换成 4-20mA 后,零点偏移导致控制系统误判。建议在 0℃ 时输出 4mA,100℃ 时输出 20mA,工程上用 2400Ω 精密电阻采样测试电流,精度至少做到 ±0.5% FS。

我个人在实际操作中体会最深的一点:一个温度采集系统,75% 的问题出在硬件布局和连接方式上,而不是芯片本身。ADS122U04IPWR 与 STM32L031C6 这套组合已经把信号链路的“最后一步”给你铺好了,剩下的就是把布线、校准、通信这三件事用心做好。如果你正准备做类似项目,建议先照着我第 2 节和第 3 节的思路搭一个最小系统,用便宜的 PT100 探头验证通信,跑通之后再往前推进到抗干扰和标定阶段,这样能少走很多弯路。