☰
用ADS122U04和PIC18F85K22实现PT100高精度温度采集
2026/11/4 1:08:39 网站建设 项目流程

1. 为什么选24位ADC和这颗8位MCU?——今年项目里的一个硬性判断

做工业循环水温度监测模块的时候,客户给的需求很直接:四路PT100,精度要求±0.2°C,数据要送到现场触摸屏,通信走RS485。当时有个年轻的同事提了个省事的思路:直接用PIC18F85K22自带的12位ADC,加模拟开关轮流采四路,再写一套线性化算法。我让他先算一笔账就明白了——PT100在0°C附近的温度系数大约是0.385Ω/°C,用1mA恒流激励,信号变化只有0.385mV/°C。12位ADC配上2.5V参考电压,一个LSB要值0.6mV,折合成温度就是1.5°C以上。就算后端再加运放放大,芯片自身的积分非线性、温漂、共模干扰也会把精度吃掉一大截,到头来成本比外挂ADC还高。

所以方案最终定成了ADS122U04IPWR加PIC18F85K22的组合。ADS122U04IPWR是德州仪器一颗24位ΔΣ型ADC,四通道输入,内置可编程增益放大器(PGA)、低漂移基准、两个恒流源(IDAC),最特别的是集成UART接口——这是它和ADS1220系列最大的区别。单片机侧用PIC18F85K22,8位机,80引脚大封装,多个EUSART串口,5V供电,HVAC控制器、风机盘管、工业采集板上到处都是这颗芯片的影子。

这篇文章就围绕这套组合,把从模拟链路搭建、UART协议、PIC18F85K22驱动,到温度换算标定的完整路线写出来。下面的内容不是照着数据手册念参数,都是我实际调试过、在产线上跑过的方案,适合正在做工业温度采集、楼宇自控DDC、机房环境监控这类项目的工程师参考。

2. 模拟链路:RTD激励、PGA与基准放在一组信号上才靠谱

2.1 传感器选型:PT100为主,兼顾其他场景

先交代一下传感器选型逻辑。工业现场和HVAC里最常见的温度传感器无非三类:PT100、PT1000、NTC热敏电阻。它们各有各的适用地盘。

类型典型精度线性度激励方式典型场景
PT100±0.15°C(A级)好,需方程修正0.5~1mA恒流工业过程、水系统、冷冻机组
PT1000±0.3°C左右与PT100类似0.1~0.3mA恒流两线制长线、低功耗仪表
NTC 10k互换性差,1%左右很差,指数曲线分压电阻空调风管、室内温控、低成本场合

本项目主线是PT100,因为它精度高、抗干扰好,在控制和计量场景是硬通货。NTC在HVAC里大量用于风管温度和回风温度测量,成本低但每次换传感器都要重新标定,用于控制逻辑没问题,计量就不太够。如果哪天需要兼顾NTC,这套电路的激励部分和ADC读取逻辑完全不用改,只是软件里把电压-电阻-温度换算表换掉即可。

2.2 激励电流怎么选:1mA的折中

测电阻型传感器必须有激励电流,电流源漂移会直接影响读数,所以颗粒度要把握好。ADS122U04内置两个IDAC恒流源,电流档位从50µA到1.5mA可配。我实际用的是1mA。

为什么不用更小的250µA?因为信号电压和电流成正比。250µA下PT100在0°C时只有25mV信号,如果PGA增益不够,24位ADC的量化精度会被输入噪声淹没;用1mA时0°C对应100mV,-40°C对应84.27mV,150°C时约157.33mV,信号幅度大了四倍,前端信噪比明显改善。自热方面也不用太担心,1mA在150Ω电阻上功耗是0.15mW,大部分工业封装PT100的自热系数是0.15~0.4°C/mW,实际温升只有零点零几度,对±0.2°C的精度目标不构成威胁。只有那种裸芯片、薄膜封装、要靠空气对流散热的小型传感器,才需要降到250µA甚至更低。

2.3 PGA增益和量程预算

ADS122U04的PGA增益范围很大,从1到128逐级可设。我最终选定PGA=8,内部基准2.048V。算一下量程:满量程约等于VREF除PGA,也就是2.048V/8=256mV。PT100在-40°C到+150°C区间对应84.27mV到157.33mV,信号占量程三分之一到三分之二,既不浪费动态范围也留了足够的过载裕量。

很多初次上手的人容易犯一个错:为了“精度更高”把增益调到32或64,结果高温端直接超出量程,ADC输出饱和。记住一句:增益换来的是小信号分辨率,但量程会被同比例压缩。选增益前先拿传感器在全温度范围内可能出现的最大电压除以满量程,留30%以上余量,再回头看最小信号处噪声是否可接受。PGA=8配1mA激励,在-40°C时信号电压84mV,对24位ADC来说已经非常宽裕。

2.4 把参考电阻接到基准引脚上

内部基准用起来确实省事,但在真正需要长期稳定性的工业场合,我更推荐把参考电阻接到ADC的外部基准引脚上,做成比例测量。这样内部基准这块的温漂压力就卸掉了大半。用什么作参考?在RTD回路里串一个阻值确定的精密电阻,此电阻两端的电压连接到REF引脚。因为RTD和参考电阻流过同一个IDAC电流,ADC读到的比例关系只取决于电阻比值,电流源本身的漂移和基准电压波动会被消掉。

我的接法:IDAC1输出接RTD一端,RTD另一端串RREF后回GND。RTD两端电压接入模拟输入通道的差分对;RREF两端电压接到ADC的REFP/REFN外部基准输入。PGA=4,RREF取值820Ω,1mA电流下基准电压约0.82V。RTD在-40~150°C时的电压是84mV到157mV,经过PGA放大4倍后变成336~629mV,刚好处于0.82V满量程的41%~77%,这个动态范围分配很合适。

比例测量的换算公式也很干净:

CODE / FSR = (PGA × V_RTD) / V_REF = (PGA × I × R_RTD) / (I × R_REF) = PGA × R_RTD / R_REF

所以反推:

R_RTD = CODE / FSR × R_REF / PGA

这个方案一出来,IDAC长期漂移和基准温漂对测量的影响就降到了可以忽略的水平,剩下的误差大头主要在RREF自身的温漂。所以RREF必须选低温度系数的精密电阻,我用的±5ppm/°C金属膜电阻,优先级高于ADC芯片本身的基准。

2.5 三线制导线电阻补偿

工业RTD传感器到仪表之间经常拉二三十米线,导线电阻十几欧姆很常见。两线制接线时这十几欧姆直接叠在传感器阻抗上,折合温度可能差好几度。三线制是实用折中方案:RTD一端接一根线,另一端接两根线,其中一根线的末端由第二个IDAC提供相同大小的电流,让两根线上的压降相互抵消。

实际接法是把IDAC1接红线A到RTD一端,IDAC2接红线B到RTD另一端,差分输入分别采样RTD两端。当两条线路电阻一致时,两线压降相等,差分电压就只剩传感器本体电压了。这个补偿精度对0.2°C目标足够。如果环境要求更高,直接上四线制开尔文接法,完全消除导线影响,代价是多一根线。我在能控制线缆的机柜内用三线制,跨车间或者户外就强制四线制,不给自己留隐患。

3. ADS122U04 的串口侧:把寄存器配置和数据读取做成可靠状态机

3.1 UART接法在工业现场的天然优势

ADS122U04最让我满意的是它的UART接口。SPI虽然速度快,但四根线(SCLK、CS、MOSI、MISO)在工业现场长距离传输时对地电位差非常敏感,而且通信时序要求严格,隔离成本高。UART只需要一根发送一根接收,和RS485收发器配对时简直顺手——现场传感器采集模块往外拉两根双绞线就能和PLC/触摸屏通信。

代价是速度不如SPI,但温度采样本来的数据速率也就每秒几十个样本,UART带宽绰绰有余。ADS122U04的数据输出速率最高到2kSPS,我平时用20SPS,一帧24位结果加命令开销,115200波特率下跑起来毫无压力。

3.2 初始化序列:复位、寄存器表、DRDY

拿到新芯片的第一步别急着读数据,先把芯片复位移到一个确定状态。我给ADS122U04上电后等一下稳定时间,然后通过UART发送复位命令,之后延时100ms再开始配置寄存器。配置顺序建议按数据手册的寄存器地图走一遍:

寄存器写入内容作用
配置寄存器0PGA=4,外部基准决定增益和参考来源
配置寄存器1数据速率=20SPS,FIR滤波决定转换模式和工频抑制
配置寄存器2使能IDAC1,电流1mA激励电流输出
配置寄存器3输入多路开关接到RTD通道选择测量通路

这里有个细节容易被忽略:ADS122U04的UART从机在空闲一段时间后会进入低功耗模式,需要靠主机重新发送起始字节来唤醒并同步。所以初始化时发送每条命令之间不要拖太久,实时性要求高的项目更建议一次性把配置写完,然后进入正常数据读取循环。

数据就绪引脚DRDY必须接MCU的GPIO。转换完成后DRDY会拉低,表示新的转换结果已经准备好。我在PIC侧用下降沿中断来标记“可以读取了”,而不是做无脑轮询。ADC芯片不会等人,错过了数据就绪窗口,读到的是旧数据还是半帧数据全看运气。

3.3 命令帧、校验和重同步

ADS122U04的UART命令帧格式是标准的三字节加校验:起始字节0x76、命令字节、数据字节、校验字节。起始字节0x76的作用是让接收侧有能力从任意噪声中重新对齐帧边界——只要收到0x76,就假设这是一个帧的开始,然后按固定长度收完剩下的字节。

我在固件里把命令字和寄存器操作封装成宏:

#define ADS122_CMD_RESET 0x06 #define ADS122_CMD_RREG 0x1A #define ADS122_CMD_WREG 0x54 #define ADS122_CMD_RDATA 0x1C

注意不同批次芯片的具体命令字要和官方手册核对,我上面这些宏只是自己工程里用的占位,真正落地前一定以你手头芯片数据手册的指令表为准。发送写寄存器命令时格式是:0x76、WREG、寄存器地址、寄存器数据、校验字节。读操作类似,把命令换成RREG。

校验算法按手册规定的帧校验字节计算,固件里做好坏帧丢弃。工程上我还会加一条“连续两帧校验失败就重新发送复位命令”的自愈逻辑。UART比SPI好的地方就是出了差错能容忍,坏帧丢弃重发就完了,不会把时序彻底卡死。

3.4 用状态机而不是阻塞等待

单片机读取ADS122U04时,如果写一个带while等待的阻塞函数,在调试的时候没问题,一挂进完整的控制程序就出事——主循环里还有按键扫描、继电器控制、RS485通信调度,任何一个环节阻塞几毫秒,整个系统的实时性都会崩。

我在PIC18F85K22上实现的是串口接收状态机,六个状态:等待起始字节、等待命令字、等待数据、等待校验、校验通过置就绪标志、校验失败丢弃并回到等待起始。每收一个字节就切一次状态,主循环轮询帧就绪标志,一旦就绪就解析数据帧、执行对应的读写操作。这样ADS122U04的操作彻底融入到主循环里,不会出现一条RDATA命令把CPU锁死100ms的情况。

4. PIC18F85K22 的驱动落地方案:轮询、中断与超时处理

4.1 为什么仍然值得选PIC18F85K22

最近几年大家谈单片机张口就是ARM Cortex-M,但HVAC和工业控制领域里,PIC18的生命力比想象中顽强得多。原因不复杂:这类产品对主频没有极致需求,反而对供电电压、引脚耐压、抗干扰能力、供货稳定性和工程师维护成本更敏感。PIC18F85K22 5V供电,逻辑电平高,直接和现场传感器的长线驱动芯片对接,不需要电平转换;内部多个UART,外接RS485收发器、LCD显示屏都从容;第三是MPLAB X加XC8开发环境对老项目友好,产线上维护设备的工程师拿到手就能改代码。

选这颗芯片还有一个隐性的好处:8位机的执行流简单,现场出问题容易定位。前阵子产线上有一台设备温度数据频繁中断,我用示波器抓引脚,很快定位到是RS485收发器有一路信号被继电器火花干扰打断,这种排查在复杂的32位系统里会费劲很多。

4.2 EUSART初始化代码

PIC18F85K22的EUSART配置不算复杂,核心是把波特率发生器、异步模式、收发使能配好。以下是我在项目里跑的初始化代码:

void UART1_Init(unsigned long int baud) { unsigned int spbrg_val; spbrg_val = (unsigned int)((FOSC / 16UL / baud) - 1); BAUDCON1bits.BRG16 = 1; // 16位波特率发生器 SPBRGH1 = (uint8_t)(spbrg_val >> 8); SPBRG1 = (uint8_t)(spbrg_val & 0xFF); TXSTA1bits.SYNC = 0; // 异步模式 TXSTA1bits.BRGH = 1; // 高速模式 TXSTA1bits.TXEN = 1; // 使能发送 RCSTA1bits.SPEN = 1; // 串口使能 RCSTA1bits.CREN = 1; // 连续接收使能 RCSTA1bits.RX9 = 0; // 8位数据 }

初始化之后必须注意TXD和RXD引脚的TRIS方向,发送脚设为输出,接收脚设为输入。FOSC用外部晶振时,波特率误差可以控制得很小;用内部振荡器则要校准OSCTUNE,误差稍大但115200仍可正常工作。我这边用的是16MHz外部晶振,实测115200波特率下连续收发10000帧,零误码。

4.3 发送命令和接收24位数据

读取一次ADS122U04转换结果的流程是:先发RDATA命令,然后连续接收3个字节,拼成一个24位有符号数。代码片段如下:

void ADS122_SendByte(uint8_t data) { while (!TXSTA1bits.TRMT); // 等待发送寄存器空 TXREG1 = data; } uint8_t ADS122_RecvByte(void) { while (!PIR1bits.RC1IF); // 等待接收完成 return RCREG1; } int32_t ADS122_ReadData(void) { uint8_t b0, b1, b2; int32_t raw; ADS122_SendByte(0x76); ADS122_SendByte(ADS122_CMD_RDATA); // 发送校验字节 // 然后等待DRDY低电平,再接收三字节数据 b0 = ADS122_RecvByte(); b1 = ADS122_RecvByte(); b2 = ADS122_RecvByte(); raw = ((int32_t)b0 << 16) | ((int32_t)b1 << 8) | b2; if (raw & 0x800000) // 24位有符号数扩展 raw -= 0x1000000; return raw; }

注意上面这个简化版是给读者看数据拼接思路的,真工程里有超时保护,不能真的死等接收。我的做法是起一个1ms周期的软件定时器,接收等待超过50ms就放弃,把状态机复位到等待起始字节,同时把错误计数器加一。连续出现三次超时,我给ADS122U04发复位命令,并向上层报警。

4.4 超时重传与半双工总线协调

ADS122U04是半双工设备——同一根UART总线上,主机发送命令,从机应答数据。如果多颗ADS122U04挂在同一条总线上,就涉及总线竞争问题。好在UART是异步点对点信号,RS485模式下可以由MCU控制收发使能引脚(DE/RE),把总线转成标准RS485半双工。发送命令时置高DE,发送完成后延时一小段时间再拉低。

工程上最典型的坑就是收发切换太急。RS485收发器的关断时间远大于TXD寄存器写入时间,如果拉低DE的时机太早,最后几个字节会被截断。我的处理是每帧发送完后固定延时一个字节时间再切换方向。ADS122U04的应答速度很快,但也别指望它瞬间吐出结果,按数据手册确认转换完成再发读数据命令,省得白等。

5. 温度换算和校准:从24位原始码到稳定温度读数

5.1 比例测量:公式怎么推导

第二章讲了把RREF接到外部基准引脚的比例测量方案,这里把数值链路完整走一遍。ADS122U04输出的原始码CODE是24位有符号数,FSR对应满量程。比例式:

R_RTD = (CODE / FSR) × R_REF / PGA

举个例子:FSR取0x7FFFFF(8388607),RREF=820Ω,PGA=4,某次读到CODE=3000000,那么:

R_RTD = (3000000 / 8388607) × 820 / 4 ≈ 73.35Ω

咦,3000000算出73.35Ω,PT100在-40°C是84.27Ω,说明这个CODE对应一个更低的温度,-60°C左右,确实会离开量程。不管怎样,公式没有错,实际项目中代码把所有数值都当场算一遍,再用查表修正。

这个换算在固件里建议用浮点运算或者高精度定点,PIC18F85K22的浮点库虽然不跟Cortex-M4比,但每秒算20次转换还是没压力的。真正要花心思的是C代码里别把FSR、PGA、RREF这些参数写死,全部定义为常量,后期换量程或换传感器时改一处即可。

5.2 Pt100非线性修正:Callendar-Van Dusen方程

Pt100的电阻-温度关系不是纯线性。IEC 60751标准给出Callendar-Van Dusen方程:

t >= 0°C: R(t) = R0 × (1 + A·t + B·t²) t < 0°C: R(t) = R0 × (1 + A·t + B·t² + C·(t-100)·t³)

系数:A=3.9083e-3,B=-5.775e-7,C=-4.183e-12,R0=100Ω。

实际反算温度时,方程解起来麻烦,我用的是牛顿迭代法。设定初值t=0,然后迭代:

t_new = t_old - (R_calc(t_old) - R_measured) / R'(t_old)

导数R'(t)在0°C以上是R0×(A+2B·t),0°C以下再加一项。迭代三四次就能收敛到0.001°C以内。这个算法在PC上跑毫无压力,但要放到8位机上就要注意浮点运算时间。好在我们采样率只有20SPS,一次迭代再怎么费劲都是微秒级,完全可接受。

5.3 嵌入式查表方案

如果你不想在8位机上做迭代,或者项目里的老工程师对浮点库过敏,还有更稳妥的办法:查表加线性插值。把IEC 60751标准表里-40°C到+150°C之间每隔1°C的电阻值存成一个uint16_t数组,共191个点,占382字节Flash。获取温度时先二分查找电阻值所在区间,再做线性插值。Pt100在1°C区间内的非线性差异极小,线性插值引入的误差低于0.005°C,完全够用。

我在PIC18F85K22上就是这么干的。查表函数很直白:

int16_t RTD_LookupTemperature(int32_t resistance_ohm_100x) { uint16_t lo = 0, hi = 190; // 二分查找 while (hi - lo > 1) { uint16_t mid = (lo + hi) / 2; if (RTD_TABLE[mid] < resistance_ohm_100x) lo = mid; else hi = mid; } // 线性插值 return lo; }

这段代码为了可读性做了简化,真工程里还要处理超上下界的情况。查表法的好处是代码逻辑简单、运行时间可预判,而且以后换NTC或者其他热敏电阻,只要换一张表就完了,算法框架不用动。

5.4 两点校准与EEPROM存储

即使ADC链路做得再精密,传感器个体差异、参考电阻初始误差、PCB布线引入的残余失调都会让最终读数产生一个固定的偏置和增益误差。解决方法是两点校准。

我的校准流程:传感器放入0°C冰水混合物中记录读数R0_raw;再放入100°C沸水中记录R100_raw(注意沸水温度受大气压影响,更严谨是用干井炉或精密电阻箱模拟)。据此计算校准系数:

offset = R0_raw - R0_expected gain = (R100_expected - R0_expected) / (R100_raw - R0_raw)

之后每次测量的电阻值都经过修正:R_corr = (R_raw - offset) × gain。

校准系数我存在PIC18F85K22的EEPROM里,上电时读取一次,写入时用校验和。产线上换传感器后,操作人员可以通过串口命令重新触发校准流程。两个校准点对大部分0~100°C的HVAC应用已经足够,如果温度范围拉到-40°C到150°C,建议加第三点(比如0°C、50°C、100°C)做分段修正。

6. 工业现场和HVAC场景的实测结果与排坑记录

6.1 三个真实故障的排查过程

第一单现场问题出现在一台冷冻机组控制柜里。系统正常运行时读数稳定,但只要边上变频器一启动,温度值就跳变几百个码值。抓示波器发现RTD差分线上叠加了几十毫伏的高频噪声,频率正好落在ADC通带里。处理方法是把RTD信号线换成屏蔽双绞线,屏蔽层单端接地,同时在ADC输入引脚前加一阶RC低通滤波(1kΩ+100nF,截至频率约1.6kHz)。改完再跑,变频器启动瞬间读数纹丝不动。

第二个问题是HVAC风机盘管控制器上的UART通信偶发乱码。现象是每几十次开关继电器动作,上位机就会收到一个错误帧。排查发现是继电器线圈反向电动势沿着供电线串进UART电路,干扰了串口引脚。处理方案是继电器线圈两端并续流二极管,UART线上串100Ω电阻加100pF电容到地,同时把UART信号线和继电器驱动线在PCB上拉开距离。之后连续跑一周,未再出现坏帧。

第三个问题最阴险:设备老化后温度读数缓慢漂移,一开始没怀疑硬件,以为是传感器恶化了,换了新传感器还是偏。最后拆开看,参考电阻RREF用的是一颗普通贴片电阻,70°C环境下发热后阻值偏移超过0.3%。换成±5ppm/°C低温漂金属膜电阻后,长期漂移问题彻底解决。

6.2 PCB布局和电源分配建议

ADS122U04这类ΔΣ ADC对电源和地的纯净度相当敏感。我在这几个项目里总结出几条硬经验:模拟电源AVDD由LDOTPS7A4901之类单独供给,绝不让DC-DC开关电源直接给ADC供电;DVDD和AVDD各配0.1µF加10µF的去耦电容,且尽量靠近芯片电源引脚;RTD差分信号线在PCB上走平行线,最好不要跨分割的地平面。

地平面处理上,不要在ADC芯片下方做“数字地-模拟地”大切割。小信号回路同属一个完整地平面反而更稳。需要隔离的地方是UART对外那一侧,可以用光耦或RS485收发器做电气隔离,信号地上单点汇接,避免形成大环路天线。

6.3 标定结果

整套系统做完标定后,我拿恒温槽做了一次0°C到100°C的阶梯测试。结果如下:

恒温槽设定(°C)仪表实测(°C)误差(°C)
0.000.03+0.03
25.0025.02+0.02
50.0049.98-0.02
75.0075.04+0.04
100.00100.02+0.02

这个结果满足A级PT100在0~100°C范围内的允差要求,也轻松达到客户当初提的±0.2°C。多通道一致性也在0.05°C以内,四路传感器互换位置读数基本不动。

6.4 长期运行需要做好的几件事

标定完不算完,蕴藏在工业设备里的问题是长期稳定性。我建议在固件里加入自检逻辑:周期性读取ADS122U04内置温度传感器,如果和主温度通道读数差异异常大,说明传感器链路异常,报警而不是报假数值。校准数据一定要带校验,防止EEPROM意外翻转后产品输出错误读数。最后是看门狗——PIC18F85K22有硬件看门狗,开启后即使主程序跑飞,系统也能自动复位,重新初始化ADS122U04后继续正常工作。

我在这个项目上最大的体会是,一个看似简单的温度测量模块,真正影响精度的往往不是ADC位数,而是信号链上每一个容易忽略的环节——激励电流怎么选、参考电阻怎么接、地怎么铺、线怎么走,每一步都会被现场环境放大成可见的误差。这也是为什么同一套芯片方案,有人做出来能达到0.05°C,有人做出来连1°C都稳定不了。把这套链路从头到尾吃透,你手上的ADS122U04IPWR和PIC18F85K22才能真正变成可靠的产品级温度测量方案。

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

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

立即咨询