在工业现场和HVAC系统里,测温度是最常见但也最容易翻车的活儿。热电偶、RTD、热敏电阻各有脾性,而信号调理和采集这一环,偏偏又决定了整个系统的测量精度。去年做了一套多通道温度采集板,用于工业管道和HVAC风管温度监测,核心就两个器件:TI的ADS122U04IPWR(24位Δ-Σ ADC,带UART接口)和Microchip的PIC18F97J94单片机。这套组合做出来的板子,精度做到±0.1℃级别,长期稳定性也不错。这篇分享就围绕这个方案,把选型理由、硬件设计、软件驱动、校准和踩坑都摊开讲。适合正在选型温度采集方案,或者打算用串口ADC配合单片机做温度测量的工程师参考。
先说说这个项目最初的背景。我们要测的地方包括工业管道表面温度、HVAC送风温度和回水温度,传感器探头有的已经接好了,有的还需要现场配线。信号线从探头到采集板,最短几十厘米,最长能到十几米。现场动力设备一开,电压波动和电磁干扰都挺厉害。这种工况下,如果直接用MCU内部ADC去采,误差大得没法看;如果用分立仪表放大器加外部恒流源,又太占面积,调试成本高。ADS122U04IPWR正好把模拟前端那点事都做了,而PIC18F97J94则负责协议解析、数据处理和传参给上位机。
1. 方案选型:为什么是ADS122U04IPWR+PIC18F97J94
1.1 需求拆解与应用场景定位
这套系统的具体目标是:测量-40℃~+150℃范围的流体与管道温度,传感器包括PT100三线制RTD,以及少量K型热电偶;数据刷新率要求2Hz~20Hz;工作环境是工业现场和HVAC风管,电磁干扰不少,供电电压可能有波动。这些约束直接决定了器件选择方向。工业温度测量并不需要ADC疯狂跑采样率,24位、2kSPS的ADS122U04IPWR完全够用,关键是它集成了两个可编程激励电流源(IDAC)、一个低噪声PGA、以及内置的50Hz/60Hz陷波滤波,光这几样就省掉了外部恒流源和仪表放大器的大部分设计工作。PIC18F97J94则是一颗带两个UART、大量GPIO和LCD驱动的80引脚单片机,Flash有128KB,RAM约4KB,跑这类数据处理程序绰绰有余。
当时也犹豫过要不要用ARM Cortex-M核的MCU,后来发现PIC18F97J94的优势在于外设丰富且简单,开发环境稳定,成本也低。温度采集这种任务,MCU主要做状态机、查表和浮点运算,对主频要求并不高。反而是一些老工程师熟悉的PIC还能更快上手,后续维护的人也好找。ADS122U04IPWR的寄存器表并不复杂,总共就那么十几个寄存器,MCC图形化配置工具里也能找到对应驱动,但为了更可控,最后还是选择手写驱动。
1.2 为什么选用UART接口的ADC
ADS122U04IPWR最特别的地方是串行接口。它和常见ADC的SPI接口不同,使用UART命令协议,DOUT/DIN两颗引脚接到单片机的RX/TX即可。刚开始我不太喜欢这个设定,总觉得多了一个异步串口要配置。但实际做下来发现,UART接口在工业现场反而有优势:走线少,适合长距离传输;而且ADC自带CRC校验和分组报文,抗干扰能力比裸SPI要好。PIC18F97J94有两个EUSART,一个负责和上位机通信,另一个正好用来和ADC打交道,完全不吃力。
如果非要用SPI版本的ADS122Q04,也可以,但PCB布线上就要更小心SCLK的频率和回流路径,而UART方式对布线的宽容度明显更高。不过,UART方式下你得自己处理波特率匹配、帧格式和命令超时。我的做法是把ADC当作一个“串口从机”来管理:每条命令固定帧头、命令码和校验,回复帧增加一个状态字节。这样即便通信出错,也能在软件层快速识别并重发。
| 对比项 | SPI版ADC | 本方案UART版ADS122U04IPWR |
|---|---|---|
| 引脚数 | SCLK/MISO/MOSI/CS四根 | TX/RX两根 |
| 命令协议 | 线性移位寄存器写读 | 命令/回复报文,带CRC |
| 抗干扰能力 | 中,SCLK易受耦合 | 优,长线传输更稳 |
| 软件复杂度 | 中 | 略高,但可控 |
注意事项:UART模式下的ADS122U04IPWR波特率可以通过配置寄存器调整,不要在跑起来之后随意改,否则容易出现帧同步丢失。每次上电后建议先发送一组同步命令(SYNC),再读取器件ID确认握手成功。这一点看起来微不足道,但在维护多块板卡时,能省掉不少“查线查半天”的事。
1.3 备选器件的横向对比
预研时我也对比了其他方案,比如用MAX31865(专门测RTD)加一个普通MCU,或者用ADS124S08 SPI接口版本。下面这个表格是我当时的对比结论:
| 方案 | 分辨率 | 集成度 | 接口 | 适用传感器 | 备注 |
|---|---|---|---|---|---|
| ADS122U04IPWR | 24位 | PGA+IDAC+UART | UART | RTD/热电偶 | 本方案采用 |
| ADS124S08 | 24位 | PGA+IDAC+SPI | SPI | RTD/热电偶 | 不支持UART |
| MAX31865 | 15位 | IDAC+放大器+SPI | SPI | 仅PT100 | 不支持热电偶 |
| 16位Σ-ΔADC+MCU | 16位 | 中 | SPI/I2C | RTD勉强 | 分辨率不够 |
ADS122U04IPWR在“一芯片通吃RTD和热电偶”这一点上确实省心。HVAC项目后期可能会接入更多传感器类型,选这颗芯片就不用重新画板子。
2. 硬件电路设计:RTD和热电偶的接入方式
2.1 传感器类型与接线方式选择
温度传感器选型上,主要用了两种:PT100铂电阻和K型热电偶。PT100的优点是信号线性度、长期稳定性和互换性都很好,适合测量-50℃~+200℃的管道和风管温度;缺点是响应慢,且需要外加激励电流。K型热电偶测温范围宽,但冷端补偿和线性化比较麻烦,热电势只有几十微伏每℃,走线稍长就容易耦合噪声。在HVAC这种室内风管场景,PT100通常是首选;在工业管道表面如果温度超过200℃,或者探头安装空间实在太小,就上K型偶。
ADS122U04IPWR有两个IDAC电流源,每个电流源可以从一组IO中选择输出。这个设计里,IDAC1给PT100提供激励,IDAC2备用。PT100的接线方式直接影响精度:两线制最省线,但引线电阻会直接串进测量结果;三线制是工业最常见的方式,利用两个相同电流源的原理,能抵消大部分引线电阻;四线制最准,但线缆成本高,探头也不一定支持。HVAC现场很多探头是按三线制出的,所以板子上按三线制设计,同时兼容两线制跳线。
温度测量里有个“自热效应”要特别注意。激励电流流过RTD时会产生焦耳热,电流越大信号越好采,但探头自身会升温,导致示值偏高。以PT100为例,假设功耗0.1mW,在静止空气中自热误差可能在0.1℃上下,在流动空气中会小一些。所以将IDAC设置成250μA,而不是常见的1mA。250μA在100Ω上产生25mV满量程电压,再配合PGA×4增益,ADC输入约100mV,信噪比足够,自热却小得多。如果你偏要追求更快的刷新率,可以用1mA,但采样时间要缩短,并做好导热设计。
2.2 供电、滤波与PCB布局
ADS122U04IPWR的数字供电(DVDD)和模拟供电(AVDD)是分开的,但数据手册允许它们共用同一个电源,实际上很多应用也这么干。为了稳妥还是用了两路LDO:一路3.3V给MCU和数字部分,另一路3.3V单独给模拟前端。两个LDO的输入都加了磁珠和一个10μF钽电容,有效把开关电源的纹波挡在外面。模拟地(AGND)和数字地(DGND)在ADC封装下方的单点相连,其他区域不再连接。这样做虽然只是普通做法,但在试产第一批板卡时,ADC输出噪声明显比之前共用电源的样板低。
每一个传感器输入通道都在ADC引脚附近放了一组RC滤波,10Ω电阻加100nF电容,截止频率约160kHz。别小看这个廉价滤波器,它能滤掉从长线缆耦合进来的RF噪声,而不影响低频温度信号。另外,在ADS122U04IPWR的AVDD、VREF引脚上各放一个100nF+10μF的组合,VREF引脚尤其重要,参考电压一个毛刺就会被ADC当作真实信号采进去。
PCB上的教训:一开始把参考电压用MCU的3.3V直接供电,结果数字开关噪声全进来了,读数跳了十多个LSB。后来换用REF5025(2.5V基准)作为外部参考,并将MCU的I/O配置为推挽低噪声模式,跳变才压下去。如果你追求性价比,也可以直接用ADC内部的2.048V参考,但要注意内部参考的温漂系数,工业级场景建议用外部基准。另外,在传感器输入连接器旁边加一个ESD保护阵列(比如BGA0402封装的双向TVS管),防止现场拔插线缆时打坏ADC,这在整个系统可靠性上非常划算。
2.3 冷端补偿的实物处理
K型热电偶测量需要知道冷端温度。传统做法是接一个热敏电阻在接线端附近,但热敏电阻精度有限。板子上预留了一个小封装PT100,贴在ADC端子排边上,并用导热硅脂和一小片铜皮把PT100和热电偶接线端子热耦合。这样冷端温度读得比较准,软件里再配合查表补偿。HVAC风管现场温度变化不像工业炉子那么剧烈,只要避免把冷端传感器放在发热元件或散热风道口附近,误差就可以控制在±0.2℃以内。
冷端补偿还有一个容易被忽略的点:热电偶延长线要用对应的补偿导线,而不是普通铜线。否则在接线端子处会产生新的异种金属结,引入不确定热电势。实际项目里我看到不少安装师傅图省事直接用了普通线,温度一波动,读数就跟着飘。如果你发现热电偶显示温度整体偏一个常数,多半就是接线端的冷端温度没补偿对,或者延长线不对。
3. 软件实现:寄存器配置、UART驱动和温度换算
3.1 ADS122U04IPWR初始化流程
软件这一块,核心是状态机。主循环里每100ms做一次采样,流程是:发送START命令→等待DRDY变低→发送RDATA命令读3字节数据→切换通道→重复。ADS122U04IPWR内部有输入多路复用器,所以一个ADC就能测多路传感器。这里一共接了4路PT100和2路热电偶,靠MUX切换通道。切换通道需要重新配置寄存器,并且要等待稳定时间,这个稳定时间取决于输入滤波电容和传感器阻值,我实测最少要等250ms,保险起见主循环设了300ms。
初始化时,先通过UART发送同步字节序列,然后读取寄存器ID。ADS122U04IPWR的寄存器ID响应如果不对,直接报“模块未就绪”。随后依次配置:配置寄存器0(选择MUX、PGA增益、转换模式)、配置寄存器1(数据速率、连续转换模式)、配置寄存器2(IDAC电流和参考电压源)、配置寄存器3(IDAC输出引脚)。代码大致如下:
uint8_t adc_config[5]; // 配置寄存器0:AIN0-AIN1差分输入,PGA增益=4,连续转换模式 adc_config[0] = 0x02; // MUX[3:0]=0001, PGA[2:0]=001, 开启PGA // 配置寄存器1:数据速率20SPS,工作在连续转换模式 adc_config[1] = 0x30; // 配置寄存器2:IDAC1=250uA,IDAC2=250uA,参考电压选择内部参考 adc_config[2] = 0xE4; // 配置寄存器3:IDAC1从AIN2输出,IDAC2从AIN3输出 adc_config[3] = 0x62; ADS122U04_WriteReg(0x00, adc_config, 4);这段代码里的具体位域值,需要对着数据手册里的表来换算。每个寄存器含义不太一样,尤其是MUX的编码,差分输入和单端输入的排列容易搞错。建议把寄存器值做成宏定义,下面注释写清楚通道和增益,别靠记忆填数字。软件写完记得跑一次“读所有寄存器”功能回读校验,防止I/O初始化瞬间UART发送不完整导致配置写一半。
3.2 UART报文解析与数据读取
ADS122U04IPWR的UART报文有两种形态:一种是单字节命令(比如START、RDATA),另一种是带参数的命令(WREG)。所有命令都有一个8位命令字节,其中高4位是命令类型,低4位是参数长度。回复数据会在命令后发回来,也可能在下一个RDATA命令后由DOUT引脚发出。这里有一个细节:连续转换模式下,每次RDATA返回的都是最新转换结果;单次转换模式下,必须先发送START,等DRDY,再发RDATA。两种模式差别很大,工程上如果忘了重新发START,会读到旧数据。
读取三字节原始码的代码,写在中断回调里:
uint8_t sample[3]; uint8_t idx = 0; void UART1_Receive_ISR(void) { uint8_t byte = UART1_Read(); sample[idx++] = byte; if (idx == 3) { value = (sample[0] << 16) | (sample[1] << 8) | sample[2]; // 如果是24位二进制补码,需要符号扩展 if (value & 0x800000) value |= 0xFF000000; idx = 0; } }注意,ADS122U04IPWR的24位数据格式是二进制补码,符号位是最高位。直接无符号左移会得到很大的错误值,尤其是负温度时。举个例子:-0.1℃对应的转换码是0xFFFFF6,如果不做符号扩展,算出来会变成一千多万的“正数”,后面温度公式全乱套。这个问题我真是吃了亏才记住,当时找了两天原因,最后用逻辑分析仪抓数据才发现。
3.3 PT100温度换算与热电偶线性化
拿到ADC原始码之后,第一步要换算成电压。以PGA增益为4,参考电压为2.048V为例,满量程差分输入是±0.512V,那么一个LSB对应电压为2.048V/(2^23×4)≈0.0610μV。电压 = 原始码×0.0610μV。然后根据激励电流和RTD阻值,算出电阻:R = V / I。这里有个坑:三线制PT100测量时,ADC测的是两个通道的差分电压,而IDAC电流会同时流过引线电阻和RTD,只要两条引线电阻对称,引线电阻的影响就基本抵消。但实际线缆电阻不可能完全一致,所以还是要通过校准去修正。
PT100电阻转温度,我用的是查表加线性插值,而不是每次都去解二次方程。这张表是-50℃到+250℃,每1℃一个点,存放在PIC的Flash里。每次查表就是找到相邻两个温度点,然后按R做线性插值,误差不超过0.01℃。为什么不用Callendar-Van Dusen方程直接算?因为PIC18F97J94的4KB RAM虽然够用,但浮点开根号会拖慢主循环,而且方程里的立方项在资源受限的MCU上很容易写错。查表法虽然代码看着“笨”,但稳定可靠,查表区间外还能报传感器异常,何乐而不为?
热电偶的换算要分两步:首先对热电偶电压做线性化查表得到“参考端0℃时的温度”,然后加上冷端温度。K型热电偶在0℃~1000℃范围内,热电势大约40μV/℃;在HVAC应用里温度不高,所以对0~300℃做了查表,每25℃一个点。如果现场换了其他分度号(比如J型),只要替换常量表即可,软件结构不用改。
4. 校准、实测与精度验证
4.1 校准流程和参数计算
再好的ADC也需要校准,尤其是项目里有三线制PT100时,引线电阻残差和器件失配都会带来误差。校准分三步:零点校准、增益校准和冷端补偿校准。
零点校准:把传感器接到精密电阻箱(模拟0℃时的100Ω),看ADC读数,记录偏差。比如理论上100Ω对应电压25mV,但实际测到的电压是24.998mV,那么这个差就记为offset。增益校准:换一个150Ω和200Ω的精密电阻,分别记录ADC换算出的电阻值,计算出增益系数。校准公式放在上位机里,每次开机时做一次“单点自校”,采集板上用50Ω精密电阻作为基准源,然后计算缩放系数,存到EEPROM里。
校准系数怎么算?假设标准电阻Rstd=100.000Ω,ADC实测电压换算出的电阻Rmeas=100.083Ω,那么偏移量offset=Rmeas-Rstd=0.083Ω。实际测量时,Rcorr=Rmeas-offset。增益误差则通过两个不同电阻(比如R1=100Ω,R2=200Ω)来计算gain=(R2_std-R1_std)/(R2_meas-R1_meas),最终的Rcorr=(Rmeas-offset)*gain。虽然PT100电阻-温度曲线本身是非线性的,但校准只修正电阻测量值,不修正温度系数。
冷端补偿校准也类似,把热电偶探头和标准温度计放到同一个恒温块中,记录读数差,然后写进冷端温度偏移量。这里要求板子先通电预热半小时,让板上温度稳定下来。发现很多人的冷端补偿不准确,就是因为刚上电就校准,热电偶接线端子的温度还没与PT100传感器达成平衡。
4.2 实测数据与误差分析
把校准后的板子放在恒温槽里做0℃、25℃、50℃、80℃四组点测试,同时用六位半万用表读PT100电阻作为参考。实测结果如下:
| 标准温度 | PT100参考电阻 | 本系统采集电阻 | 折算温度 | 误差 |
|---|---|---|---|---|
| 0.00℃ | 100.000Ω | 100.011Ω | 0.03℃ | +0.03℃ |
| 25.00℃ | 109.735Ω | 109.712Ω | 24.94℃ | -0.06℃ |
| 50.00℃ | 119.397Ω | 119.361Ω | 49.91℃ | -0.09℃ |
| 80.00℃ | 131.071Ω | 131.103Ω | 80.08℃ | +0.08℃ |
这个结果基本达到预期。误差来源主要有三块:一是IDAC电流的实际值不可能完全等于250μA,会导致电压/电阻换算产生比例误差;二是外部基准电压的温漂;三是三线制引线电阻不完全匹配。要再往0.02℃压,就得每个通道单独做完整两点校准,并且使用温漂系数更低的基准。
热电偶通道实测误差略大,在±0.3℃左右,主要差在冷端补偿。HVAC现场设备启动后,控制柜内部温度会缓慢攀升,如果冷端传感器只是简单地贴在PCB上,读数会追随板温波动。后来加了铜皮均温和一颗小散热片,实测冷端温度与端子排表面的温差降到0.1℃以内,系统误差才下来。
4.3 长期稳定性观察
校准是短时间精度,长期稳定性是另一回事。我把板子放在室温环境中连续跑了两周,每10分钟记录一次风扇开关前后的数据。结果发现,PT100通道的最大漂移约0.05℃,热电偶通道约0.1℃。主要漂移来自外部基准电压随时间的微小变化,以及冷端PT100传感器自身的老化。如果项目要求年漂移小于0.1℃,我会建议每年做一次现场校准,并在上位机里保存校准日期和最近一次校准系数,方便追溯。
5. 常见问题排查与工程心得
5.1 UART通信异常:同步失败或随机丢帧
这个项目里碰到的头号问题就是UART通信。ADS122U04IPWR上电后,如果MCU复位而ADC没复位,两边波特率即使设置一致,也可能处于非同步状态。一开始按数据手册初始化后直接读ID,结果十次有六次读不到,剩下几次数据还错位。后来解决办法是:在上电后的初始化序列里,先连续发送0x00、0x00、0x55这样的同步字节,并等待至少两个字符时间,然后再发RREG命令读ID。如果ID不对,重复三次同步。这样做的原理是让ADC的UART接收器根据起始位重新对齐帧边界。
另外,PIC18F97J94的UART波特率来自内部振荡器或外部晶振,误差要控制在±2%以内。用内部8MHz振荡器时误差不大,但到了高温现场,内部振荡器的漂移会变大,所以最终改用了16MHz外部晶振,并且UART1和UART2都配置成同一时钟源,避免两边频差导致偶发错帧。
5.2 采样值漂移或跳变:先查基准和地
还有一个典型问题:采样值不稳定,算出来的温度来回跳0.3℃甚至更多。最初怀疑是ADC坏了,后来发现是参考电压VREF引脚上的去耦电容焊得不牢固,导致参考电压在高频纹波下抖动。Δ-Σ ADC对参考电压非常敏感,参考电压纹波会直接以百分比乘到输入信号上。以后排这种问题,建议先拿示波器量VREF引脚,看有没有超过10mV的纹波;其次查AGND/DGND有没有单点连接;再看输入RC滤波是否空缺。三层查完,基本能解决90%的跳变问题。
排查时还可以用“短路测试”快速定位:把ADC输入端直接短接,如果读数接近零且稳定,说明ADC本身没问题,问题在传感器或前端电路;如果短接后仍然大幅跳变,就要怀疑VREF或电源。这个法子简单有效,我几乎每次排查都用。
5.3 RTD自热和引线电阻混叠
前面说过,激励电流不能贪大。实际项目里,有人为了省事把IDAC设成1mA,PT100本身功耗就是0.1mW,如果探头装在风速很高的风管里,气流会带走部分热量,自热误差还好;但如果探头被包在保温层里或者管壁热阻大,示值可能偏高0.2℃以上。HVAC和工业现场对绝对温度要求没那么高,但长期监测时,这0.2℃足以影响判断。所以坚持用250μA。
三线制PT100虽然能抵消引线电阻,但有个前提:两根激励线电阻相等。如果现场用不同型号线缆接了其中一根,或者端子老化氧化,就会产生零点几欧的差异,相当于零点几度的误差。遇到这种情况,要么换成四线制探头,要么在做校准时把这个残差并进offset里。在验收测试里,我给每条通道都做了“引线电阻失衡测试”,人为串入2Ω电阻,观察误差是否超过阈值,以此判断现场接线质量。
5.4 HVAC现场的布线与屏蔽
最后聊聊现场环境。HVAC风管温度测量,传感器线缆会经过强电桥架、变频器柜附近,这些地方的电磁干扰比实验室大得多。处理办法是:所有模拟信号线都用屏蔽双绞线电缆,屏蔽层在采集板一端接地;线缆长度超过5米时,建议在ADC输入前加一个共模扼流圈。ADC的输入RC滤波电阻从10Ω提高到33Ω,电容保持100nF,实测RF干扰从原来能引起±0.15℃波动降到几乎看不到。还有一个容易忽略的是,薄膜电容比陶瓷电容在吸收高频噪声上更好,所以输入滤波电容统一用了C0G材质,虽然贵一点,但长期稳定性更好。
抽风管道里湿度大,端子排容易结露,导致绝缘电阻下降,这会让高阻源的电平拉低。在接线端子表面涂了一层三防漆,并在机壳底部留了排水孔,后续再没有出现绝缘异常报警。
踩过这些坑之后,我自己总结出一个体会:ADS122U04IPWR+PIC18F97J94这套方案,真正的复杂度不在芯片本身,而在于模拟前端怎么和真实传感器、现场环境相处。做温度测量时,先把传感器类型、接线方式、校准手段想清楚,再去看数据手册配寄存器,就会顺手很多。如果后续项目要把采样率提高到1kSPS以上,或者同时接更多热电偶,可以考虑换用SPI接口的ADS124S08,并配合DMA,但就目前HVAC和大部分工业温度监测来说,UART接口的ADS122U04IPWR已经能给到足够满意的结果。