☰
PT100高精度温度采集方案:基于ADS122U04与STM32F107VC的设计
2026/11/5 1:06:48 网站建设 项目流程

去年接了一个HVAC控制柜改版的项目,甲方要求把老设备里的NTC热敏电阻全部换成PT100铂电阻,温度误差控制在±0.3℃以内,新系统还要通过CAN总线把温度数据上报给楼宇自控平台。主控我选了STM32F107VC,原因很直接:这颗芯片带以太网MAC和两个CAN控制器,做集中控制器和协议网关非常合适;采集端则选了TI的ADS122U04IPWR,一颗24位Δ-Σ ADC,带UART接口,内部把PGA、基准电压、IDAC恒流源全集成了。这种“STM32F107VC负责通信和逻辑、ADS122U04IPWR负责模拟前端”的组合,在我最近的工业现场和暖通项目里反复出现,这篇就把从硬件设计到固件实现、再到校准验收的完整链路讲清楚。

1. STM32F107VC负责“管”,ADS122U04IPWR负责“测”

1.1 系统的整体架构与器件分工

先看这套系统在干什么。ADS122U04IPWR放在传感器一侧或者主控板上的模拟输入区,它负责把PT100随温度变化的电阻信号变成24位数字量,通过UART送给STM32F107VC。STM32F107VC作为主控MCU,一边通过UART接口把温度数据收回来,做滤波、线性化、校准,一边通过CAN或以太网把结果送到上层管理系统。如果现场需要本地显示,还能挂个屏或者按键,但这已经不是这套采集方案的核心了。

整个系统的组成其实很清晰:

子系统器件/方案职责
温度传感器PT100/PT1000 铂电阻把温度变化转换为电阻变化
模拟前端ADS122U04IPWR24位AD转换、PGA放大、激励电流、基准电压
主控制器STM32F107VC处理数据、跑协议、统一调度
通信链路STM32F107VC的USART半双工接口 ↔ ADS122U04的UART传输寄存器配置与ADC结果
上位连接CAN/以太网/RS-485(由主控制器扩展)与HVAC系统或工业设备通信

STM32F107VC的型号后缀VC意味着256KB Flash、64KB SRAM,LQFP100封装,72MHz主频。在温度采集项目中这些资源完全够用,而且它的互联型定位让它非常适合做“上传下发”的中间层:温度数据采集上来之后,既要进本地的控制PID,又要打包成Modbus或者CAN报文送走。

ADS122U04IPWR这颗ADC则把以前需要运放、基准、恒流源、模拟开关一堆电路才能做的事,全部简化成一颗芯片加外围几个电容电阻。它的4个模拟输入引脚可以配成差分或单端,一对IDAC恒流源可以给RTD提供激励电流,内置的PGA可以把毫伏级信号放大到合适的幅度,内部2.048V基准还能配合外部精密电阻做比率测量。对像我这样不喜欢把模拟前端搞得过于复杂的工程师来说,这几乎是省事到极致的选型。

1.2 为什么不用STM32F107VC内部ADC

可能有人会问:STM32F107VC本身有12位ADC,为什么非要多加一颗外置芯片?这个问题我在项目初期也纠结过,后来实测数据说明了一切。

STM32F107VC的内部ADC是12位SAR型,满量程3.3V时,1个LSB大约是0.8mV。而PT100在0℃时的电阻是100Ω,如果用1mA电流激励,产生的电压只有100mV;温度变化1℃,电阻变化约0.385Ω,电压变化只有385μV。也就是说,直接用内部ADC去测,一个LSB就相当于2℃以上的温度变化,这还没算SAR ADC本身的INL、DNL和电源噪声影响。即便用高增益运放把信号放大,也解决不了参考电压漂移和运放失调的问题。

外置24位Δ-Σ ADC的思路完全不同。它以过采样和噪声整形把信噪比做上去,内置PGA可以让传感器信号在进ADC之前就已经被放大,内置基准又保证了转换的稳定性。ADS122U04IPWR在这个场景下,把0.1℃以内的温度分辨率变成了一件不费力气的事。所以我的结论很明确:做工业温度采集,MCU内部ADC拿来监控电压、管管按键可以,但别拿它做高精度模拟量采集。

2. ADS122U04IPWR的模拟前端设计:从RTD到24位数字量

2.1 芯片集成资源的实际价值

ADS122U04IPWR最值得说的一点,是它在小小的TSSOP-16封装里把RTD测量需要的模拟资源几乎全做了进去。做传统模拟方案时,一个高精度仪表放大器、一个精密基准、两个恒流源,占的PCB面积和成本都很可观,更不用说每一级单独调零和温漂。而在这颗芯片里,这些都只是寄存器配置项。

对我而言,有几项特别关键。第一是PGA,增益可以从1倍配置到128倍,对于PT100在0.5mA激励下产生的几十毫伏信号,选16倍或者32倍增益,信号幅度正好落在ADC最佳线性区。第二是内部基准2.048V,精度和温漂比普通MCU内部基准好很多,常规精度要求完全够用。第三是两个IDAC恒流源,同一个芯片内匹配性好,做三线制RTD时用来抵消引线电阻再合适不过。第四是它自己带内部温度传感器,虽然不能当精确测量用,但用来监控芯片结温、发现异常发热很有用。

2.2 两线、三线与四线:RTD接法怎么选

RTD的接法直接决定最终能测到多准。传感器离控制器近的时候,两线制看着省线省端子,但两根引线电阻会直接叠进测量结果里。一段20米长、截面0.5平方毫米的铜线,电阻大概0.7Ω,相当于PT100读数本身偏高了1.8℃左右,这个误差工业现场完全不能接受。

三线制是工业现场最常见的妥协方案:三根线,一根是激励电流的回路,另外两根是采样线。设计思路是让两个IDAC输出大小相同的电流,一个激励RTD,一个激励外部精密参考电阻,ADC测量RTD电压与参考电阻电压的比值。由于两个电流源同源同大小,引线上的压降会同步出现在两条测量路径里,比率运算后互相抵消,这样即使引线电阻随温度变化也能保持稳定。

四线制最准确,也最奢侈。两根线走激励电流,两根线走电压采样,采样线上没有电流所以完全不产生压降,引线电阻的影响理论上为零。实验室计量设备、要求最高的工业计量点才会这么用。我在实测中通常这样安排:现场空间允许或传感器是四线封装时直接上四线,老设备只有三根线或者原厂端子固定为三线则用三线制。ADS122U04IPWR的两路IDAC正好支撑三线制方案,这也是我给它加了不少分的原因。

接法引线数引线电阻误差适用场景
两线制2根完全误差,不可消除短距离、精度不高的场合
三线制3根可以抵消大部分HVAC现场常用的经济方案
四线制4根理论上为零高精度计量、实验室

2.3 外围电路与PCB布局的实操细节

ADS122U04IPWR的模拟部分就算集成度再高,外围想做严谨还是有几个固定动作。首先是供电去耦,AVDD和DVDD上分别加1μF和100nF的组合电容,电容要尽量靠近引脚。其次是模拟输入端的RC滤波,我习惯在AIN引脚串几百欧到1kΩ电阻,并一个1nF到10nF的电容到地,这能抑制来自现场的射频干扰和工频干扰。

还有一个特别容易忽略的:ADS122U04IPWR带PowerPAD的TSSOP封装,散热焊盘在芯片底部,数据手册要求把它和AVSS连接,同时大面积铺铜散热。有些人按普通TSSOP随便焊一下不接地,结果高温环境下测量值忽高忽低,查了半天就是这个原因。

电源方面,如果主控板只有5V,建议给ADS122U04的模拟供电单独用LDO降到3.3V或5V也行,但要用低噪声LDO,比如LP5907、TL1962之类的,别直接从DCDC输出串个电阻就往上怼。DCDC的开关纹波虽然幅值不大,但对24位ADC来说仍然可能体现为噪声底抬升。我实际测试中,用同一个DCDC和用低噪声LDO,数据速率低时区别不明显,但提高到几百SPS以上,RMS噪声差的量还挺明显。

3. 一根线的UART:STM32F107VC与ADS122U04IPWR的通信对接

3.1 ADS122U04的单线UART协议

ADS122U04IPWR的接口不需要两根独立的TX/RX线,而是通过单根数据线进行半双工通信,另外还有一根DRDY作为转换完成指示。主机在这根数据线上发命令,配置寄存器、启动转换、读取结果,ADC也在同一根线上回复。

这种设计对系统很有好处:原来SPI至少四根线,I2C也有两根线,现在只剩一根信号线,特别适合把ADC放在离传感器很近的位置,又不想在主机和前端之间铺太多线的场景。如果再往前走一步,这根单线UART还可以改造成长距离传输,比如接成RS-485半双工总线,主机到前端几十米甚至上百米都能稳定通信。我在一个分布式测温项目里就干过这件事,效果不错。

波特率方面,芯片手册给出的范围是1200到115200,上电默认是9600。我建议初始化时先用9600握手,确认通信正常后再按需要调高。ADS122U04内部有低功耗振荡器,波特率精度依赖它,所以除非器件手册明确允许,不要指望它能在115200bps下长期稳定,我实际用38400比较稳妥。

3.2 STM32F107VC侧的半双工USART配置

STM32F107VC的USART本身支持半双工模式,这也算是我选它的一部分原因。把USART_CR3的HDSEL位置1,TX和RX就自动合并到TX引脚上,此时外部只需要一根线连到ADC的数据引脚。GPIO模式要配置成复用开漏,外部加上拉电阻,空闲时线路由电阻拉到高电平。

基于STM32F1标准外设库,初始化代码大致是这样:

// 引脚:PA9/PA10 如果复用,用PA9做单线数据脚 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 关键:复用开漏 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // USART1 配置 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_TX | USART_Mode_RX; USART_Init(USART1, &USART_InitStructure); USART_HalfDuplexCmd(USART1, ENABLE); // 打开单线半双工 USART_Cmd(USART1, ENABLE);

外部上拉电阻选4.7k到10k都行。注意这个上拉不能省,否则释放线路时电平悬空,误码率会激增。

实际项目中我发现一个细节:HAL库内部收发流程在某些版本对半双工方向切换处理得不够干净,现象是发送完最后一个字节后立即接收,有概率收到第一个垃圾字节。规避方法是发送命令后主动延时1到2个字节时间,或者干脆用寄存器操作清掉发送完成中断标志后再切到接收。这里的核心思想是:半双工模式下方向切换要预留稳定时间,千万不要在TE位刚复位、线路还没被上拉拉回到高电平前就开RE位。

3.3 通信时序和上电唤醒

ADS122U04IPWR上电之后不会立刻处于工作状态,芯片默认是睡眠省电模式,等着主机发唤醒命令。很多第一次用这颗芯片的人遇到“发命令没反应”,十有八九是跳过了唤醒步骤,直接去发配置命令。我的建议是每次上电后先发唤醒命令,确认收到设备响应,再做后续的寄存器配置。

配置寄存器的命令格式并不复杂,核心是两条:SETB写某个配置寄存器,RUNB启动转换。我现在习惯把所有寄存器配置写成一个初始化函数,每次上电都按顺序写一遍,哪怕某些寄存器跟默认值一样。这样代码逻辑统一,出了bug也容易排查。

DRDY这根线建议接到STM32的外部中断引脚,由下降沿触发读取流程。用轮询方式也能工作,但ADC数据速率高一点时,轮询的MCU会不断空转,浪费CPU时间。我在设计时通常把DRDY接一个带有EXTI功能的引脚,中断里只做一个标志位置位,主循环看到标志再去读数据,这样既不丢数据,也不会把中断服务函数搞得太长。

4. 从原始码到真实温度:固件换算、滤波与多通道轮询

4.1 24位二进制补码怎么换算成电压和电阻

从ADS122U04IPWR读回来的原始数据是24位二进制补码,直接当成无符号数用肯定出错。先把最高位当符号位处理,转换成int32_t的有符号整数,再乘上LSB对应的电压值,就成了实际电压。

LSB的计算公式是:LSB = 2 × VREF / (G × 2^24),其中VREF是基准电压,G是PGA增益。举个例子,VREF=2.048V,PGA=16倍,算下来每个LSB约等于15.26nV,这个量级意味着1℃对应的PT100电压变化约有380μV,相当于两万多个LSB,分辨率根本就不是瓶颈。

把电压换算成电阻就简单了:已知激励电流IIDAC,电阻R = V_measured / IIDAC。不过这里我提醒一句:直接用内部基准和IDAC各自的值去算,会混入基准误差和电流源误差,最终的绝对精度仍然受限。想拿到真正的精度,要靠后面说的比率测量和校准,而不是依赖芯片手册给出的典型值。

如果采用比率测量方案,ADC的输入其实是两个电压的比值:一个来自RTD,一个来自参考电阻RREF。同样的电流激励下,RTD阻值 = RREF × ADC_RTD / ADC_REF。这个算式里IDAC数值直接消掉了,连基准电压也消掉了,所以基准漂移和激励电流温漂带来的误差理论上都不起作用。

4.2 PT100电阻转温度:查表法与Callendar-Van Dusen公式

电阻值算出来后,下一步是把电阻转成温度。PT100最常见的两种做法是查表插值和公式计算。

查表法简单直接:在程序里放一张PT100分度表,从-200℃到850℃,每1℃或每10℃存一个电阻值,然后线性插值。缺点是需要占Flash,想要精度高表格就密。我在工程上更推荐在主流量程范围内用公式:0℃以上PT100符合R(T) = R0(1 + aT + bT²),其中R0=100Ω,a=3.9083×10⁻³,b=-5.775×10⁻⁷。这个公式在0到850℃范围内误差很小,完全满足HVAC和大部分工业应用。

代码实现很轻量:

float PT100_R_to_T(float resistance) { if (resistance >= 100.0f) { // 0℃以上区域 float c = 100.0f * a; float bq = 100.0f * b; // 解 R = R0 + R0*a*T + R0*b*T^2(保留正根) float disc = a * a - 4.0f * b * (1.0f - resistance / 100.0f); return (-a + sqrtf(disc)) / (2.0f * b); } else { // -200~0℃区域需要引入三次项,建议在程序里直接查表插值,公式写起来啰嗦且边界要特别小心 } }

我个人的建议是:只做0到150℃范围就放心用上面的公式,如果产品需要覆盖零下温度,别图省事硬套公式,老老实实把分度表放数组里,做二分查找加线性插值。零下区域的三次修正项涉及c(T-100)*T³,边界处数值敏感性容易引入误差,查表反而快且可控。

4.3 多通道扫描与数字滤波

ADS122U04IPWR的4个模拟输入能做的通道数有限,如果每一路都是PT100四线制,那它本身就只能带两路差分输入。实际工业现场往往要测四路、八路甚至更多温度点。针对这一点我有两个方案参考:一路用一个ADC只测两路,简单可靠;或者用模拟开关在前端扩展通道,多个传感器分时接入ADC。

分时扫描要处理的现象是通道切换之后,MUX新接通的那一瞬间会有电荷注入造成的毛刺,ADC内部输入滤波器需要稳定时间。因此切换通道后不能立刻读数据,要丢几个转换周期或者等足够稳定时间再采,具体等多少个周期看数据速率,可以实测观察读数什么时候不再乱跳。

数字滤波是温度测量的标配,因为温度信号本身变化极其缓慢,而ADC即使有24位精度,瞬时噪声也常有。滑动平均是我最常用的方式:维护一个长度为16或32的环形缓冲,每采到一个新值就计算一次平均值。16点滑动平均对阶跃输入的响应时间不到1秒,温度现场完全接受。如果想更平滑,可以用一阶低通IIR后再滑窗。我见过有同行用中值滤波去剔除偶发毛刺,这在工业现场抗干扰很有效,但要注意中值滤波会引入一定的相位滞后,多点输出时可能让几个通道的显示值之间存在细微时间错位。

5. 精度不是靠芯片而是靠校准:误差链路与实践方法

5.1 误差从哪里来:链路拆解

很多工程师第一次用高精度ADC,容易把期望全押在芯片身上,觉得24位就是精度保障。实际上从物理温度到最终显示值,误差链路很长,芯片只是其中一环。我把误差源和对应解决办法整理过一张表:

误差源表现形式消除/抑制方法
PT100探头本身的精度等级全量程系统性偏差选用A级/B级探头,按等级评估
引线电阻读数整体偏高、随温度变化三线/四线制,比率测量
激励电流自热探头自身温度升高减小IDAC电流,比如250~500μA
ADC失调误差零点附近读数偏移软件校准,零输入减偏移
PGA增益误差满量程比例偏差两点或多点增益校准
内部基准温漂环境温度变化时读数漂移比率测量,或外接精密基准
采样滤波不足读数跳动数字滤波,降低等效带宽
布线耦合干扰读数周期性波动屏蔽、接地、RC滤波

这张表每次项目评审我都贴出来,核心想表达一句话:误差要逐项拆、逐项化,不能指望一颗芯片解决所有问题。

5.2 实用校准流程:零点偏移与增益校准

校准本质上是用一个精度更高的参考,把系统误差测出来并修正掉。工业现场最方便的做法是准备一只0.01%精度的电阻箱,把它当成RTD接入采集通道。

先在100Ω位置,让系统按100Ω的标称值走一遍,记录ADC原始码,这对应0℃的零点。然后把电阻箱调到138.51Ω,模拟100℃的标准PT100,再记录一次原始码。得到两点后,线性校正公式就是:

修正电阻 = R0 + (C - C0) × (R1 - R0) / (C1 - C0)

其中C0、C1是两次记录的原始码(或原始电阻计算值),R0、R1是标准值。这个两点校准能同时修正失调和增益误差,对大多数现场足够。如果要做高精度计量级温度采集,建议用恒温槽,把探头放进几个已知温度点,采集后用最小二乘拟合出一条校正曲线,再逆推回任意温度。

校准参数要保存到Flash里固化,比如用STM32F107VC的内部Flash最后几个扇区或外挂EEPROM存储。设备开机时读出来,没有有效校准值就先用默认值运行并打日志,防止校准数据未写全导致系统性能突然变差。我在实际项目里还专门做过一个“校准模式”:总线上发一条命令,设备自动切换到连续快采模式,方便产线上放好电阻箱后一键标定。

5.3 实测数据与验收指标

硬件做完、校准写完,总得拿数据说话。我在一个暖通项目里用四线制PT100加A级探头做过一组测试:25℃恒温水槽中连续采集一小时,结果最大偏差0.04℃,极差0.08℃,完全在甲方要求的±0.3℃以内。把传感器从恒温水槽拿出来放到空气中的瞬间,读数会小幅跳变,主要是探头自身热容变化,不是电路问题。

阶跃响应这块我特别注意:PT100金属封装探头在水里响应快,从室温扔进60℃热水,5秒左右能稳定到目标值的90%;如果是塑料封装的工业探头,可能会慢到30秒以上。负责控制的同事如果用PID对这些温度做闭环,得把传感器响应滞后算进去,否则调节时间会老达不到预期。

数据速率对噪声的影响是另一个直观的体验:我用100SPS和1000SPS做过对比,100SPS时RMS噪声大概是1μV量级,换算温度非常安静;1000SPS时噪声明显变大,但配合16点滑动平均,显示值依然很稳。如果系统有严格的控制周期,5~50ms一次更新完全够用,没必要把ADC速率调到顶。

6. 我在现场踩过的坑:HVAC配电柜与工业现场的实测经验

6.1 变频器和强电电缆穿进来的干扰

HVAC现场最讨厌的干扰源是变频器和接触器。风机泵组一变频,动力电缆里就有几百赫兹到几百千赫兹的开关电流,如果传感器线跟动力线走同一个桥架,测量值会周期性跳动。我的教训是:传感器线必须用屏蔽双绞线,屏蔽层在控制器端单点接地,靠近传感器一端悬空。模拟输入上的RC滤波电阻取值稍微加大一点,比如1kΩ以上,配合1nF电容,抗射频干扰的效果会很实在。

如果现场干扰已经到了让电源都不干净的程度,主机与ADC之间的通信线也可以加隔离。ADS122U04IPWR这种单线UART在半双工下做隔离稍微绕一点,但思路是明确的:用数字隔离器隔离数据线和方向控制,电源侧用隔离DC-DC。见过不少同行怕麻烦不做隔离,结果传感器地电位和控制器地电位一旦被强电设备抬高,轻则读数乱跳,重则烧芯片。

6.2 电源和地的安排

ADS122U04IPWR的AVDD、DVDD和地的布局要求并不苛刻,但前提是别乱来。我把模拟地和数字地在ADC的PowerPAD下方做单点汇合,其他数字信号不允许经过AD转换区域。去耦电容的接地孔要尽量靠近芯片地脚,而不是绕一大圈再接主地。这些细节在原理图上看不出来,到EMC测试和现场调试时会无限放大。

DCDC直接给模拟部分供电的问题我前面提过,这里再强调一次:宁可多花一毛钱加一颗低噪声LDO,也别拿示波器上看“还挺干净”的开关电源直接喂ADC。24位ADC的噪声底对高频开关纹波特别敏感,而示波器探头接地的位置不同,看到的纹波差异也很大,实测为准。

6.3 复位与看门狗:设备恢复的可靠性设计

工业设备不能出现“死机了只能断电重启”的情况。STM32F107VC的看门狗要开,这是常规操作,但ADC侧的恢复流程容易被忽略。我遇到过一个诡异问题:主控制芯片看门狗复位后,采集数据突然变成满量程或者一直卡在某个值,排查很久才发现是ADC还停在上次的上电状态,通信复位序列没执行完整。

正确的做法是:每次MCU启动,无论看门狗复位还是冷启动,都固定执行一遍完整的ADC初始化流程:等待上电稳定、发唤醒命令、重新写入所有寄存器、随后再启动转换。不要试图判断ADC当前是否还“活着”来决定要不要初始化,那样状态机容易复杂且不可控。

另外,DRDY中断标志要设计成“边沿触发+标志位清零”的模式,防止中断积压。我在程序里给温度采集任务设了一个超时保护,如果连续一秒钟没有DRDY触发,就主动重启ADC通信链路,把通信复位纳入看门狗之外的二级防护。这个策略在十几台设备上跑了一年,没有再发生采集卡死。

6.4 最后还是留三个小技巧给同行

第一,如果产品对成本敏感,PT100和PT1000可以共用同一套硬件,通过寄存器切换IDAC电流档位就行,不用改版。第二,测量精度要求高时,外部精密电阻比内部基准更靠谱,选温漂低于10ppm的金属薄膜电阻,配合比率计算,效果立竿见影。第三,产品从实验室进现场之前,把传感器线绕成一圈挂在变频器出线附近烤一烤,能提前暴露很多EMC隐患,比去认证机构排队排到崩溃再返工划算得多。

这套基于ADS122U04IPWR和STM32F107VC的温度采集方案,我用它做过暖通冷冻水温度监测、工业管道温度记录、还有几台设备上的多点温度报警,逻辑基本是同一套。硬件上模拟前端被芯片高度集成,固件上只要把单线UART和换算校准处理好,整个系统做出来既稳又省事。希望这篇把关键细节都踩过的记录能帮你少走几段弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询