2026/11/5 3:16:14

基于ADS122U04与STM32的PT100高精度温度采集系统设计

基于ADS122U04与STM32的PT100高精度温度采集系统设计 做工业温度采集的人应该都有过这种经历PT100传感器输出信号就那么几毫伏配上变频器、压缩机的干扰环境用普通仪表放大器加16位ADC的方案折腾半天还是一跳一跳的。这个项目用TI的24位Delta-Sigma ADC芯片ADS122U04IPWR配合STM32F411RE来做一套工业和HVAC暖通空调场景的温度测量系统核心思路就是把模拟信号链简化到极致让一颗高集成度ADC把PGA、基准源、激励电流源全包了主控只负责通过UART把数据读回来算温度。ADS122U04IPWR这个型号看着长拆开其实很直白ADS122U04是器件名I代表工业级温度范围-40℃到125℃PWR表示TSSOP-16封装加卷带包装。它最特别的地方在于接口是UART而不是更常见的SPI这意味着MCU端只需要两根线就能通信对STM32F411RE这种Cortex-M4主控来说非常友好。这套组合做完之后温度分辨率可以轻松做到0.01℃以内放在HVAC楼宇自控的风管温度监测、工业电机轴承温度采集这类场景里电路简单、调试方便、稳定性也比DIY的分离方案靠谱得多。这篇文章就把整个设计思路、硬件配置、软件驱动和现场调试的完整过程记录下来适合正在做温度变送器、数据采集卡或者HVAC控制器的朋友参考。1. 方案选型为什么是ADS122U04 STM32F411RE1.1 工业温度测量的真实痛点工业现场测温度尤其是RTD热电阻测温最头疼的其实不是ADC精度不够而是信号太娇气。PT100在0℃时刚好100Ω灵敏度大约是0.385Ω/℃如果用250µA电流激励换算成电压信号只有大约96µV/℃。这么小的信号随便一点电源纹波、地线压降、电磁耦合就会把有效精度吃掉一大截。更麻烦的是HVAC场景里干扰源特别多。冷冻站里有变频压缩机风柜里有大功率风机电控柜里还有继电器接触器的火花这些干扰都会通过电源、空间和传感器线缆耦合进测量回路。传统方案为了扛住这些干扰往往要加仪表放大器、有源滤波器、隔离放大器一堆器件塞在PCB上布板稍有不慎就出鬼影噪声。还有一个容易被忽略的问题——长线缆的导线电阻。一栋楼里的温度传感器可能距离控制柜几十米甚至上百米铜导线本身有电阻环境温度一变导线电阻也跟着变两线制接法下这个误差根本没法分清是传感器温度变了还是导线温度变了。所以选型时我看重的不是ADC位数而是芯片把抗干扰和信号调理需要的外围电路集成到了什么程度。ADS122U04IPWR恰好把PGA可编程增益放大器、2.048V基准源、两个IDAC恒流源、内部温度传感器全集成进去了温度测量最核心的信号链在一块芯片里就能闭环。1.2 选型过程中的几个关键决策在ADS122U04和STM32F411RE这个组合之前我其实先对比过几种常见方案。第一种是经典的分离方案仪表放大器基准源24位ADCMCU这套性能天花板很高但调试难度大成本也压不下来。第二种是现成的数字温度传感器芯片比如DS18B20精度只有正负0.5℃分辨率倒是够但稳定性在高精度场景撑不住而且响应速度慢。ADS1220系列之所以吸引我是因为它有SPI和UART两种接口版本。ADS1220是SPI接口ADS122U04是UART接口。选UART版本的理由很实际SPI要接SCLK、MISO、MOSI、CS四根线而且主从时序必须卡得严严实实UART只要TX和RX两根线通信距离也更远一些对MCU引脚占用少。在STM32F411RE上跑HAL库UART的收发代码写起来比SPI更顺手调试时逻辑分析仪抓线上数据也直观。STM32F411RE这颗芯片在F4系列里算是性价比很均衡的。100MHz主频、Cortex-M4带FPU浮点单元做温度计算里的多项式求解完全不吃力512KB Flash和128KB SRAM对这类数据采集任务来说绰绰有余后续想加LCD显示、网络通信也都留得住空间。更重要的是生态成熟CubeMX配置外设几分钟就能把工程骨架搭起来。1.3 系统的整体信号链这套系统的信号链路从传感器一直延伸到MCU的串口终端中间经过的关键节点包括RTD传感器 - 屏蔽双绞线缆 - 输入RC滤波网络 - ADS122U04内部多路选择器 - PGA可编程增益放大器 - Delta-Sigma调制器 - 数字抽取滤波器 - 24位数据寄存器 - UART接口 - STM32F411RE串口外设 - 温度换算算法 - 最终温度值每个节点都有各自的噪声和误差贡献设计时的任务就是把各级误差合理分配。ADC自身的有效位数在PGA128时能做到20位以上这是理论上限实际系统的误差往往出在传感器本身PT100的精度等级、激励电流的温漂、输入滤波电阻的失配这些环节。想通这一点就不会盲目追求“24位就是24位”而是把精力放在如何把这些误差源一个个压下去。2. 测量原理与核心参数配置2.1 用PT100测温度本质是在测电阻PT100的阻值和温度近似成线性关系0℃时100Ω100℃时138.5Ω平均灵敏度约0.385Ω/℃。但这只是近似工程上如果要到0.1℃以内必须用Callendar-Van DusenCVD方程做非线性修正。好消息是这些计算在带FPU的F411RE上毫无压力一次温度换算不过几个周期。测电阻的办法有很多我用的是比例测量法让ADS122U04内部的IDAC恒流源流过PT100产生一个与电阻成正比的电压再用ADC测量这个电压。这里的关键词是“比例”——如果激励电流和ADC基准电压来自同一个参考体系它们之间的漂移可以被部分抵消这是温度测准的核心。激励电流的选择是个权衡。电流大了PT100上压降大信噪比高但自热效应也大——电流流过电阻产生的热量会让传感器自身温度高于被测介质产生虚假读数电流小了自热小了但信号也小了对抗干扰不利。我在这套系统里用250µAPT100在0℃时压降25mV100℃时34.6mV这个量级配合32倍PGA刚好能踩在理想的信号范围里。如果是测多点或者长线缆可以降到100µA自热影响更小代价是需要更大的PGA增益噪声会稍微抬起来一点。2.2 ADS122U04的寄存器配置逐位拆解ADS122U04的配置通过四个8位寄存器完成从CONFIG0到CONFIG3每位的含义在芯片数据手册里写得很清楚。这里说几个我在实际项目中确认过、最容易配错的点。CONFIG0主要管输入选择和PGA增益。差分输入通常选AIN0-AIN1或者AIN0-AIN2取决于三线制接法怎么安排。PGA增益从1到128可选增益越高分辨率越细但输入失调和噪声也随之放大。我的经验是能不用高增益就不用先用激励电流把信号抬高到合理量级再决定PGA档位。CONFIG1管数据速率和滤波模式。50Hz和60Hz工频干扰是HVAC现场的家常便饭配置数据速率时优先选择对工频有抑制能力的档位。20SPS时内置滤波器对50Hz有很好的陷波这是大多数温度采集场景的默认起点。如果响应速度要求高可以提到100SPS以上但此时干扰会明显增多后期靠软件滤波补。CONFIG2和CONFIG3负责IDAC恒流源的输出方向和电流大小、基准电压选择、内部温度传感器开关等。这里最关键的是让IDAC电流方向和ADC测量通道匹配好如果电流根本没流经PT100读出来的数据就是浮空的——这个问题在实物调试中非常常见焊接完先按数据手册把IDAC方向核对一遍能少走太多弯路。2.3 满量程计算为什么增益不能拍脑袋选很多人拿到24位ADC就习惯性地把增益开到最大觉得“放大倍数越高精度越高”其实这是个误区。ADC满量程输入电压是基准电压除以增益ADS122U04内部基准是2.048VPGA32时满量程约正负64mVPGA64时只有正负32mV。回到PT100的0-100℃量程250µA激励下最大输出电压是250µA乘138.5Ω约34.6mV。这时用PGA64就会出问题因为满量程只有32mV信号会削顶。用PGA32满量程64mV信号最大34.6mV预留了约一倍余量才是合理选择。这个计算过程每次换传感器类型或者换激励电流时都要重新走一遍。我见过不少项目现象是“温度到七八十度读数就停着不动了”排查半天发现就是增益配太高导致ADC饱和。所以选增益之前先掏出计算器把最大信号电压算出来比什么技巧都管用。3. 硬件接线与PCB设计要点3.1 传感器接线三线制怎么接才准RTD的引线方式有三种两线制、三线制、四线制。两线制最简单但导线电阻直接串进测量回路误差最大四线制最准但现场传感器线缆成本高、接线端子多。工程上折中方案几乎都是三线制。ADS122U04恰好有两路IDAC恒流源天生就是给三线制设计的。典型接法是让IDAC1和IDAC2分别从RTD的两端提供激励电流两条电流路径经过的导线电阻压降方向相反在差分测量时相互抵消。这样即使导线长到几十米导线电阻引入的误差也被抑制到只剩微小残差。接线时还有几个实操细节。传感器线缆要选屏蔽双绞线屏蔽层单端接地千万不要两端都接——两端接地会形成地环路反而把更多干扰引进系统。另一个细节是接插件要压接牢靠松动会造成瞬间开路表现为数据突然跳到一个极端值。我一般在现场巡检时先拿手摇一摇接线端子如果是数据跟着抖多半就是接触不良。3.2 与STM32的接口不光是三根线ADS122U04和STM32F411RE的接口主要有四条线UART_TX、UART_RX、DRDY数据就绪、RESET。有些板子还会用到RTS流控我这里是悬空处理软件里也关掉了流控。这里容易被忽略的是DRDY线。它相当于ADC告诉MCU“新数据准备好了”的门铃下降沿有效。如果不用DRDY纯靠延时去读数据只要时序稍有偏差就可能读到上一帧或者半截数据。我把DRDY接到了STM32F411RE的一个EXTI外部中断引脚上数据就绪就触发中断在主循环里设置标志位再去读数据这样每一帧数据都是完整且新鲜的。复位管理也得认真对待。芯片上电后内部有复位时序同时也有RESET引脚建议用一个GPIO控制RESET程序启动时先拉低再拉高确保ADC处于已知状态。之前我偷懒直接靠上电复位结果低温环境下偶尔出现通信不同步后来加上硬复位就再没犯过。3.3 电源与抗干扰的细节ADS122U04的模拟电源和数字电源虽然都是3.3V但PCB上不能把它们当同一路用。我的做法是用一颗低噪声LDO给模拟侧单独供电磁珠再隔一道给数字侧电源平面分区域铺铜ADC底下尽量保持完整地平面。去耦电容按常规组合摆每个电源引脚放一个0.1µF陶瓷电容靠近引脚放置另外在模拟电源入口放一个10µF钽电容做低频储能。参考电压如果用的是内部基准电源噪声会直接影响基准稳定性所以电源这关过不去后面精度全是空谈。输入滤波网络也要讲究。Delta-Sigma ADC内部的开关电容网络会周期性地从输入端抽取电荷如果外部RC的电容值选得过大充电建立时间跟不上采样节奏会引入可观的增益误差。一般差分位置串100Ω电阻配10nF电容是安全的起点线缆特别长的场合可以适当加大但要用实测数据校验不能想当然。4. STM32软件驱动与温度换算实现4.1 UART命令帧与初始化流程ADS122U04的通信协议和普通传感器不太一样所有操作都是通过发送命令字节完成的。常用的命令有RESET0x06、START0x08、RDATA0x10、WREG写寄存器0x40加寄存器地址、RREG读寄存器等。初始化流程在代码里是有顺序的我总结成固定的几步void ads122u04_init(void) { // 1. 硬件复位 HAL_GPIO_WritePin(ADS_RESET_GPIO_Port, ADS_RESET_Pin, GPIO_PIN_RESET); HAL_Delay(2); HAL_GPIO_WritePin(ADS_RESET_GPIO_Port, ADS_RESET_Pin, GPIO_PIN_SET); HAL_Delay(10); // 2. 软复位指令 ads122u04_send_command(0x06); // RESET HAL_Delay(50); // 3. 写配置寄存器组从CONFIG0开始连续写4个字节 uint8_t config[4]; // 注意以下值需要对照数据手册的寄存器位定义结合你的通道和量程修改 config[0] 0x00; // 示例AIN0-AIN1差分输入PGA1 config[1] 0x20; // 示例20SPS自适应滤波 config[2] 0x20; // 示例IDAC相关方向和内部基准选择 config[3] 0x04; // 示例IDAC电流设置以实际需求为准 ads122u04_write_reg(0x00, config, 4); HAL_Delay(10); // 4. 启动转换 ads122u04_send_command(0x08); // START }这段代码里的配置值只是示例真正用到自己的板子上时务必对照ADS122U04数据手册的寄存器位定义逐位确认。我见过太多人直接抄网上的寄存器值结果通道或者电流方向对不上调试半天才发现是参考案例的硬件接线和自己不一样。4.2 读取24位数据并换算成温度数据读取的原理是等待DRDY变低然后发送RDATA命令串口会连续返回三个字节组成24位有符号数。这个数是二进制的补码形式需要做符号扩展。拿到原始码之后换算电压的公式是V_输入 原始码 * LSB其中LSB 2 * VREF / (PGA * 2^23)。下面是我在实际工程里验证过的读取和换算代码volatile uint8_t data_ready_flag 0; // 在DRDY中断服务函数里置位 void EXTI0_IRQHandler(void) { if (__HAL_GPIO_EXTI_GET_IT(ADS_DRDY_Pin) ! RESET) { __HAL_GPIO_EXTI_CLEAR_IT(ADS_DRDY_Pin); data_ready_flag 1; } } int32_t ads122u04_read_raw(void) { uint8_t buf[3]; HAL_UART_Transmit(huart2, (uint8_t *)0x10, 1, 100); // RDATA HAL_UART_Receive(huart2, buf, 3, 100); int32_t raw ((int32_t)buf[0] 16) | ((int32_t)buf[1] 8) | buf[2]; if (raw 0x800000) { raw - 0x1000000; // 24位有符号数扩展 } return raw; }DRDY的下降沿有时非常短如果用轮询方式在主循环里读很容易漏掉。中断加标志位的方式最稳妥即便主循环在忙别的事数据就绪也不会丢。4.3 校准、滤波与工程化优化换算温度之前还有一道工序不能省——校准。单片机系统做温度采集ADC本身是准的但基准源、激励电流和传感器本身的误差都会叠加上去。我常用的校准做法是零点加增益两点校准先把传感器换成精密电阻箱分别在100Ω和138.5Ω对应0℃和100℃的名义值下记录原始码计算出实际K和B再存进Flash里。这样即使传感器批次有差异整套系统的误差也能控制在很小范围。软件滤波我用的是滑动平均加限幅判錯。滑动平均窗口取8到16个点对20SPS的数据速率来说延迟很小限幅判断则是把单次跳变超过设定阈值比如5℃以上的采样直接丢弃能有效过滤掉接插件瞬间虚接这类脉冲干扰。double pt100_resistance(int32_t raw, double pga, double iidac) { double vref 2.048; double lsb 2.0 * vref / (pga * 8388608.0); double vin raw * lsb; return vin / iidac; } double pt100_temperature(double r) { double r0 100.0; if (r r0) { // 0℃以下用简化线性近似严格场景用CVD方程 return (r / r0 - 1.0) / 0.00385; } else { double A 3.9083e-3; double B -5.775e-7; double a r0 * B; double b r0 * A; double c r0 - r; return (-b sqrt(b * b - 4.0 * a * c)) / (2.0 * a); } }实际上100℃以内用CVD方程的二次项和线性近似差异大概在零点几度级别如果系统要求不高直接线性换算也能用。但既然F411RE的FPU闲着也是闲着把二次项算进去是零成本的提升。5. 现场调试的坑与排查实录5.1 数据漂移和噪声哪来的这套系统调试初期我被一个现象困扰了很久室温下读数稳定在24.2℃但加热一段热风后数值不是平滑上升而是在24.35、23.9、24.1之间乱跳幅度看着有半度。按说24位ADC不该表现成这样。排查思路是把信号链逐级短路。先把ADC输入端直接短接不接传感器发现输出码确实稳定在极窄的区间内说明ADC和软件读时序没问题。再接上传感器但不加热数据也稳。一加热就跳问题锁定在干扰路径上——加热器是交流供电的热风机的电磁辐射比较强传感器线缆当时用的是普通平行双绞线没有屏蔽交流干扰直接耦合进了信号。解决方法是换上屏蔽双绞线并把屏蔽层单端接地同时在输入端把RC滤波的电容加大到33nF效果立竿见影跳动幅度降到0.02℃以内。这事的教训是在HVAC这类电磁环境里屏蔽和滤波不是可选项而是必选项。5.2 通信时好时坏怎么查还有一个高频故障是UART通信时好时坏。现象是上电后前几次读数据正常过几分钟突然返回的全是0xFF或者偶尔读到的数据在第2、3字节错位。最开始怀疑是DRDY那根线接触问题重新焊过也没解决。后来用逻辑分析仪抓UART波形才发现问题根源STM32F411RE用的是HSE外部晶振但当时手头刚好没25MHz的晶振临时用内部HSI顶的。内部RC振荡器的精度本来就不高温度一变化波特率也跟着偏接收端采样点就滑到数据位边缘了。换回外部晶振后问题彻底消失。这个小坑提醒我ADS122U04这类UART通信芯片对波特率精度是有要求的MCU端时钟源不干净再简单的协议也会翻车。5.3 精度上不去先看这几项如果最终测试发现精度始终达不到0.1℃我把排查顺序总结成一条线照着走基本都能找到原因先测激励电流。用万用表串在RTD回路里看IDAC实际输出是不是配置的250µA偏差多大温度变化时漂多少。电流不准后面全是空中楼阁。再测参考电压。内部基准电压实际是多少是否和手册标称一致。这步能发现芯片个体差异。然后检查导线电阻残差。三线制的残余误差在高精度场合会冒出来如果传感器线缆太长、芯线太细残差就不能忽略了。有一种做法是实际测出导线电阻在软件里做补偿。最后才是校准。用电阻箱模拟标准电阻值记录原始码做两点或三点校准把整个系统的增益误差和偏置误差一次性修正掉。校准做完这套系统的实测表现是在0℃到100℃范围内最大偏差能稳定在0.05℃以内足够覆盖绝大多数HVAC和工业温度监测需求。最后再分享一个我自己调试惯了的小技巧拿到新板子别急着焊传感器先把ADC输入端用飞线短接确认读回来的原始码稳定且接近零。这一步过了再逐步接入传感器和激励源每加一级就验证一次。按这个顺序来出问题的时候你永远知道是哪一级引入的省掉的是按天计算的返工时间。