ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于ADS122U04IPWR与PIC18F4620的高精度温度采集系统设计

基于ADS122U04IPWR与PIC18F4620的高精度温度采集系统设计

最近在改一套温度采集前端,原来的板子用的是单片机内置 ADC,分辨率只有 10 位,低温漂工况下根本不够看。这次直接上了 TI 的 ADS122U04IPWR,主控还是 PIC18F4620,应用场景是 HVAC 管道风温监测和工业设备表面温度测量。这套方案做下来效果还行,我把从选型到软硬件细节完整记录一下,供做温度采集、仪表和控制器的小伙伴参考。

这套组合适合谁?如果你正在做工业数据采集、暖通控制器、温度变送器,或者只是想把 PT100 / 热电偶 / NTC 的测量精度从“能看个大概”提升到“高分辨率稳定读数”,同时主控又不想换 32 位平台,那这篇文章值得看完。ADS122U04IPWR 最大的特点是自带 24 位 Δ-Σ ADC、PGA、IDAC 电流源和 UART 接口,PIC18F4620 只负责发指令、收数据和换算,两边分工很干净。

1. 选型逻辑与整体方案

1.1 为什么是 ADS122U04IPWR

这颗芯片在 TI 的产品线里算是一棵“老常青树”。24 位分辨率、内部可编程增益放大器、两个激励电流源、内部温度传感器、单周期建立等特性,几乎就是为工业温度测量量身定做的。我最早用过 ADS1220,那是个 SPI 接口的版本,也很好用,但问题在于很多 HVAC 控制器平台早期是为了空调控制设计的,SPI 引脚往往被 LCD、EEPROM、按键占得七七八八,剩下几个普通 IO 还得慢慢软件模拟时序,麻烦。

换成 ADS122U04IPWR 之后,通信线变成一根 TX、一根 RX、一根 DRDY,对 8 位机来说非常友好。UART 是几乎所有单片机都会有的资源,PIC18F4620 的 EUSART 模块直接就能用,不需要额外消耗 IO 去模拟协议时钟。对于已经跑着 Modbus、继电器控制逻辑和显示刷新的主控来说,压力小很多。

另外让我坚定选它的原因是内部集成了两个 IDAC 电流源。以前用普通 ADC 测 PT100,还得在外部搭恒流源电路,低温漂的恒流源芯片加运放加精密电阻,成本和面积都上去了,而且每一个环节都会引入误差。ADS122U04 直接用一个寄存器配置电流大小,配合外部参考电阻就能组成比率式测量,电流源波动几乎不影响最终结果,这一点在后面会详细说。

还有一点容易被忽略:它内置温度传感器和内部参考电压。做热电偶冷端补偿时可以直接读芯片结温,或者用外部 NTC 做更精确补偿,灵活性大。我这一版做了双通道输入,一路 RTD 一路热电偶,靠切换通道来完成,硬件上只加了一个模拟开关,整体 BOM 成本比以前的“运放 + 恒流源 + 12 位 ADC”方案没有高太多,精度却跨了一个数量级。

1.2 PIC18F4620 在这里扮演什么角色

PIC18F4620 是 Microchip 的经典 8 位 MCU,40 引脚 DIP/TQFP 封装,自带 4KB RAM 和 64KB Flash,一个 EUSART 模块,工业级温度范围。很多老 HVAC 控制器、楼宇自控面板都在用它,产品生命周期长,资料也多。

在这个方案里,它不直接碰模拟信号,只负责三件事:

  • 上电后通过 UART 对 ADS122U04IPWR 写配置寄存器,设置通道、PGA、IDAC、数据速率和转换模式;
  • 等待 DRDY 信号,随后通过 UART 读回 24 位转换结果;
  • 把原始码换算成电阻 / 热电势 / 温度,再送给显示、Modbus 从站或者继电器逻辑。

之所以把主控和模拟前端分开,是考虑到工业现场强电干扰多。如果把 ADC 和 MCU 做在同一块板子上,数字信号噪声会直接影响模拟测量;ADS122U04 通过 UART 和主控通信,物理上可以把模拟前端独立成一个小板,靠近传感器安装,主控板放在配电箱里,用长线连接,实践下来干扰明显小很多。

1.3 系统架构和信号流

整体信号流是这样的:传感器(PT100 或热电偶) → 输入滤波和保护电路 → ADS122U04IPWR 内部 PGA 放大 → Δ-Σ 调制器 → 数字滤波器 → UART 输出 → PIC18F4620 接收并计算 → 显示/RS485 上传。

这样分层有个明显的好处:模拟前端和数字处理之间有天然的隔离边界。PIC 侧只处理数字字节,即使主控复位或者跑飞,也不会反向干扰到 ADC 测量,排查问题的时候思路清楚,不像以前模拟链路和数字链路混在一起,出了问题到处猜。

2. 硬件电路与关键设计

2.1 供电与最小系统

ADS122U04IPWR 支持 2.3V 到 5.5V 供电,我的板子为了和 PIC18F4620 共用 3.3V,直接统一用一片 LDO 从 12V 降压到 3.3V。这里要特别提一句:模拟供电 AVDD 和数字供电 DVDD 虽然都接 3.3V,但 PCB 上要分开走线,汇合点放到 LDO 输出电容附近,中间加磁珠隔离,不然数字部分开关噪声会顺着电源线串进模拟部分。

去耦电容不要省。AVDD 管脚放 10µF 钽电容 + 0.1µF 陶瓷电容,DVDD 至少放 0.1µF,每个电源引脚附近都尽量靠近放置。参考电压我用了外部 REF5025,输出 2.5V 接到 REFP 和 REFN 之间,比内部参考稳一些。如果对绝对精度要求没那么高,用内部 2.048V 参考也能跑,只是温漂稍微大一点。HVAC 应用里常年 0~50℃ 环境,外部参考带来的好处很明显。

还有一个容易踩的坑:ADS122U04IPWR 的复位和上电时序。如果 PIC18F4620 比 ADC 先上电完毕,PIC 立刻发配置命令,ADC 可能还没准备好,第一条命令会丢。解决方法是上电后延时 50~100ms,再开始发命令;如果频繁复位系统,建议用复位引脚或经过 74LVC1G17 整形后的复位信号同时复位两颗芯片。

2.2 RTD 比例测量电路

我这次用的是 PT100 三线制。二线制虽然接线少,但导线电阻直接串进测量回路,现场 10 米线就有 0.2~0.5Ω 误差,折合温度 0.5~1.3℃,不能忍。三线制可以抵消大部分导线电阻影响,是工业测温最常用的折中方案。

ADS122U04IPWR 内部两个 IDAC 可以这样配置:IDAC1 接到包含了 RTD 的支路,给 RTD 提供 1mA 激励电流;同一股电流流经参考电阻 RREF,产生 ADC 的参考电压。比例式测量的优点是,即使 IDAC 电流随温度有漂移,RTD 电压和参考电压是同一个电流产生的,它们的变化是同步的,最后的 A/D 转换结果基本不受电流源漂移影响。这就是“比率测量”的核心,能让系统在很宽温度范围内保持稳定。

具体参数我选的是:IDAC = 1mA,RREF = 1.8kΩ,PGA = 4。算一下:

  • PT100 在 0℃ 时约 100Ω,1mA 激励产生 100mV;
  • 150℃ 时约 157.33Ω,电压 157mV;
  • PGA = 4 时,满量程输入范围约 ±0.45V(以 2.5V 参考折算),150℃ 对应的 157mV 远小于满量程,留了足够余量;
  • 灵敏度为 0.385Ω/℃ × 1mA = 385µV/℃,换算成 24 位原始码,理论分辨率远高于 0.001℃,实际噪声限制在 0.01℃ 级别。

RREF 建议选 0.1% 精度、25ppm/℃ 温漂的金属膜电阻。实测下来这个电阻的精度直接决定全量程的精度,因为整个比例计算的基准就是它。我最初手头只有 1% 电阻,校准前误差到 0.5℃,换 0.1% 电阻后同一套补偿参数误差降到 0.1℃ 以内。这个钱不值得省。

输入端的 RC 滤波也要说一嘴。在 RTD 和 ADC 输入之间加串联电阻和并联电容可以滤除高频噪声,但电容值如果太大,PGA 输入端会变成低通,反而影响建立时间。我用的是 RFILT=1kΩ、CFILT=1nF,截止频率约 159kHz,既不影响 20SPS 的采样,又能挡住射频干扰。如果传感器线特别长,可以并联 1nF 和 10nF 两级,但需要在建立时间和噪声之间做权衡。

2.3 热电偶测量与冷端补偿

另一路做了 K 型热电偶。热电偶的热电势很小,比如 K 型在室温附近大约 41µV/℃,如果 PGA=1,24 位 ADC 也浪费。我把 PGA 设到 128,可以分辨亚 µV 级别信号,同时把热电偶输入范围限制在 -200℃~1300℃ 对应的电势以内,避免 PGA 输出饱和。

热电偶的难点从来不是放大,而是冷端补偿。热电偶测的是热端和冷端的温差,冷端所在位置温度必须被准确测量,再叠加到热电势上。我的板子把 ADS122U04IPWR 的冷端接头放在 PCB 边缘的接线端子上,尽量远离电源模块和 DC-DC 电感,然后用芯片内部温度传感器读结温来估算冷端温度。内部温度传感器绝对精度大约 ±1℃ 左右,对于暖通应用够用,但如果是工业高精度场合,我建议在接线端子旁边加一个 NTC 或 DS18B20,补偿效果会更好。

勘误提示:如果你用内部温度传感器做冷端补偿,注意芯片结温和端子温度并不严格相等。板卡发热越严重,误差越大。我后来把 ADC 芯片位置挪到板子角落,下方开了铜皮散热窗,结温和端子温度差距控制在 2℃ 以内,否则冷端补偿的偏差会变成零点漂移,很难校准。

2.4 电源、地与抗干扰

这部分是工业现场最容易翻车的地方。我第一版样板直接被变频器干扰到读数跳动,后来做了几个改动:

  • 模拟地与数字地单点连接,连接点放在 ADC 底部的焊盘下方,不要形成环路;
  • PIC18F4620 的 UART 走线不要和模拟输入走线平行,中间加地线隔离;
  • ADC 输入端对地并联 TVS 管,型号选低电容的,比如 ESD9B5.0ST,防止静电打坏芯片;
  • 传感器长线(超过 5 米)输入端加共模电感,或者至少用屏蔽双绞线,屏蔽层单端接地,不要两端都接地,否则现场地电位差会变成共模干扰;
  • UART 长距离传输再加隔离。板级之间距离超过 30cm,我直接用了数字隔离器,型号 ISO7721,保证 RS485 上来回的电平冲击不会损坏主控。

还有一个容易被忽略的点:如果 HVAC 系统里有风机、压缩机或变频器,电源线上会有大量共模噪声。LDO 前级最好加 π 型滤波器,用 22µH 电感和两个 10µF 电容配合,能把高频噪声压下去几十 dB,成本不高,收益很大。

3. UART 通信与软件配置

3.1 通信协议与数据时序

ADS122U04IPWR 的 UART 接口是标准的 8 位数据、无校验、1 停止位,波特率我设成 19200,这样在 3.3V 下干扰容限也好一些。协议上支持读寄存器、写寄存器、读取数据、启动转换、进入掉电等命令。写配置命令的大致格式是先发送命令字节,再发送目标寄存器地址和字节计数,最后跟数据;读数据命令则是指定寄存器地址,然后读取返回字节。

我这里不打算给完整寄存器表,毕竟不同批次芯片的地址定义可能略有差异,大家做项目时一定要以最新手册为准。但通信流程是通用的:

  1. 上电延时后,用 WREG 写配置寄存器;
  2. 发送 START 启动转换;
  3. 等待 DRDY 信号变低,或查询状态位;
  4. 发送 RDATA 指令,读取 24 位数据;
  5. 将原始码换算成电压或电阻。

DRDY 信号我接到了 PIC18F4620 的外部中断脚。这样主控可以在转换结束时立刻被唤醒去读数据,不会因为轮询而错过数据,实时性更好。如果不用中断,也可以把 DRDY 当普通 GPIO 轮询,只是高数据速率时 CPU 占用偏高。

有一个细节需要注意:ADS122U04 的数据输出可能是三字节原码,也可能带状态字节。我的做法是把状态字节和 24 位数据一起读回来,状态字节里包含通道标识和转换信息,可以校验当前读到的数据是不是目标通道的。这点在通道切换时特别重要,否则可能读到切换前的旧数据。

3.2 寄存器配置实例

我项目的配置目标:通道 1 接 PT100,PGA=4,IDAC=1mA,内部参考关闭、外部参考 2.5V,数据速率 20SPS,连续转换模式,CRC 关闭。伪代码如下:

// 基于 PIC18F4620 的 EUSART void ads_write_reg(uint8_t addr, uint8_t value) { putch(0x40); // WREG 命令 putch(addr); // 寄存器地址 putch(0x00); // 只写一个字节 putch(value); } // 初始化配置 void ads_init(void) { DelayMs(100); // 等 ADC 上电稳定 ads_write_reg(0x01, 0x30); // IDAC=1mA, 外部 VREF ads_write_reg(0x02, 0x08); // AIN0=INP, AIN1=INN, PGA=4 ads_write_reg(0x03, 0x22); // 20SPS, 连续转换模式 ads_write_reg(0x04, 0x10); // 关闭CRC, 数据格式为直接显示 putch(0x08); // START 启动转换 }
// DRDY 中断服务程序里读取数据 void __interrupt() highVector() { if (INT0IF) { INT0IF = 0; putch(0x1A); // RDATA unsigned char b0, b1, b2; b0 = getch(); b1 = getch(); b2 = getch(); raw_code = ((int32_t)b0 << 16) | ((int32_t)b1 << 8) | b2; // 注意如果配置了带符号输出,raw_code 要转成 signed 处理 data_ready = 1; } }

注意这里寄存器值只是示意,你用的时候一定要对着手册核对每一位的含义。我刚开始就是不看手册直接照抄网上的例程,结果 IDAC 配置错一位,激励电流变成 500µA,RTD 电压少了一半,算出来的温度偏了十几度。

3.3 原始码如何换算成温度

把原始码转换成温度是整个软件里最需要严谨的部分。RTD 通道先用比例关系算电阻:

R_RTD = (raw_code / (2^23 - 1)) × (RREF / PGA)

其中 raw_code 要按带符号数处理。由于我用 PGA=4,得到的原始码实际上是 PGA 放大后的值,所以分母要除以 PGA。算完电阻再转温度。

PT100 转温度比较准确的方法是 Callendar-Van Dusen 公式。T > 0℃ 时,用 R = R0 × (1 + A·T + B·T²),其中 A = 3.9083e-3,B = -5.775e-7;T < 0℃ 时公式多了三次项,系数 C = -4.183e-12。直接解二次方程就能得到温度,没必要用大表插值。表格插值在 8 位机上占用 Flash 太多,而且 MCU 换算的时候还要处理分段线性误差。

热电偶更麻烦,K 型热电偶电势-温度关系是非单调曲线,最省事的办法是做一张 1℃ 间隔的分度表存在 Flash 里,然后线性插值。PIC18F4620 的 64KB Flash 放一张几百条的表毫无压力。先把 ADC 原始码转成电势 E,再根据冷端温度加上对应冷端电势 E_cold,最后用 E_total = E_hot + E_cold 查表得到热端温度。

用内部温度传感器做冷端补偿时,传感器读出来的还是电压,需要先通过芯片手册的转换公式把它变成温度,再查表得到冷端电势。这一步一旦漏掉,热电偶通道整体会偏移几十度。我调试时就是一个典型的例子:热端温度 100℃,冷端 25℃,我忘了加冷端电势,查表出来只有 75℃,当时还以为热电偶断线了,排查了很久才发现是补偿逻辑写反了。

4. 校准与实测结果

4.1 校准流程

再好的芯片也会存在失调和增益误差,校准是必须做的一步。我的校准流程分成 RTD 和热电偶两套:

RTD 通道,用精密电阻箱代替 PT100。先在 0.01% 精度下设置 100Ω 作为零点,再把电阻箱调到 200Ω 作为满度。程序里记录两组原始码,计算出增益误差系数和失调量,存到 PIC18F4620 的 Data EEPROM 里。之后每次开机读回来,对原始码做线性校正。如果现场使用范围跨度大,可以做三点校准,比如 50Ω、100Ω、150Ω,用最小二乘拟合,效果更好。

热电偶通道的校准要麻烦一些。我用一个干井炉把热电偶探头放在已知温度(比如 100℃),同时记录 ADC 输出的热电势。由于冷端补偿已经算过,正常情况误差会很小。如果补偿有系统偏差,需要检查内部温度传感器读到的是不是真实冷端温度;如果是外部 NTC,还需要标定 NTC 的 B 值或者做两点补偿。

校准时还要注意环境温度稳定。我吃过一次亏:白天校准好,晚上环境温度降了 10℃,第二天早上起来偏差 0.4℃。后来把校准温度点放到 25℃ 恒温室里重新做,全天稳定性立刻好了很多。所有高精度测量系统校准时的环境温度,会直接影响最终现场表现。

4.2 实测数据与表现

在我的测试台上,用 Fluke 5522A 校准源模拟 PT100,室温 25℃ 左右,数据速率 20SPS 时,温度读数稳定在 ±0.01℃ 波动。用干井炉从 -20℃ 到 200℃ 测试,最大误差在 ±0.15℃ 以内,这还是没做 0.1℃ 以下高精度校准的结果,工业 HVAC 已经是绰绰有余了。

不同数据速率下有效分辨率差别很大,实测大概如下:

数据速率有效分辨率 (ENOB)读数波动(PT100)
20 SPS约 20.5 bit±0.008℃
100 SPS约 18.5 bit±0.02℃
400 SPS约 17 bit±0.05℃
1000 SPS约 15.5 bit±0.15℃

所以做暖通这种变化缓慢的场合,我强烈建议把数据速率设低,比如 20SPS 或 50SPS。响应速度虽然慢了一点,但稳定性和抗噪能力都强很多。HVAC 又不是控制导弹,温度本来就几分钟才变一次,高数据速率纯属给自己找麻烦。

热电偶通道的实测:K 型热电偶在室温下波动大约 ±0.02℃,干井炉上 100℃ 时误差 0.2℃ 左右。这个精度主要受冷端补偿限制,如果换成外部 NTC 并标定好,可以把误差压到 0.1℃ 以内。

4.3 HVAC 现场的应用心得

这套方案在 HVAC 里最典型的应用是冷冻水管温度和风管风温监测。现场管道外面包着保温棉,探头安装时要注意探头不能直接贴在管道外皮上,要插到测温和金属套管里,并且保证探头和管壁充分接触,否则会测到保温层空气的温度,而不是实际介质温度。

工业设备表面测温时,传感器线比较长,必须使用屏蔽线,屏蔽层在设备端单端接地。如果现场没有独立的接地桩,不要乱接地线,尽量就近接到设备金属外壳的同一个接地点上,避免形成地环路。地环路是工业现场很多莫名跳动问题的根源,我之前在一台变频器旁边调试,只要把屏蔽层两端都接地,读数就跳 0.3℃;改成单端接地后立刻安静。

还要注意主控板如果放在配电箱里,ADC 小板尽量靠近传感器布置。我的方案是把 ADS122U04 小板直接装在传感器接线盒附近,通过 UART(隔离后)把数据送到几十米外的 PIC18F4620 主控板。数字信号经过隔离和差分传输后抗干扰能力很强,而模拟信号如果走几十米线,早就被环境噪声淹没了。

5. 常见问题与排查技巧

5.1 读数一直跳动,怎么排查

如果 ADC 读数像心电图一样跳,先别怀疑芯片,大概率是这几个原因之一:

首先看输入和基准走线是否有长距离平行。数字信号线跨过模拟区域会耦合噪声,特别是 UART 的 TX/RX 线速率为 19200 时,上升沿很陡,如果和模拟输入线走得很近,跳字就特别明显。解决办法是 PCB 上把模拟输入和 UART 走线分开,中间加地线隔离。

其次看 RREF 和输入回路是否用了线绕电阻或含电感成分的元件。线绕电阻在工业环境下电感效应强,高频噪声会直接在参考电压上产生波动。改成薄膜电阻或金属膜电阻后跳字明显改善。

再检查 PGA 输入端的滤波器电容。电容太大会造成 PGA 环路建立问题,尤其在 128 增益下,振荡会让转化结果不稳定。关掉 PGA 试试,如果结果稳定,说明是前端电容过大的问题。

5.2 UART 通信失败或数据错乱

这个问题调试时几乎人人都会遇到。UART 通信失败,首先要确认电平。PIC18F4620 工作电压如果 5V,而 ADS122U04 是 3.3V,直接用 MCU 的 TX 去驱动 ADC 的 RX 可能会超出耐压,需要用分压电阻或电平转换芯片。RX 返回方向给 5V MCU 则没问题,但最好也做下电平适配,确保高电平能到 2.0V 以上。

其次是波特率误差。PIC18F4620 如果用的是内部振荡器,误差可能达到 ±2% 甚至更大,在较长数据帧下就会产生校验错误。建议使用外部晶体或对内部振荡器做校准,波特率尽量用 9600 或 19200,不要跑到 115200,8 位平台在 3.3V 下高速 UART 抗干扰能力会变差。

还有一种情况:ADC 在启动命令之后没有等 DRDY 变低就读数据,读回来的是上次的旧数据。通道切换时尤其容易踩坑,我建议每次读数据前都检查状态字里的通道 ID,不吻合就丢一帧,防止把旧通道数据当成当前通道。

5.3 冷端补偿偏差很大

热电偶通道读数整体偏移,先检查内部温度传感器读出来的温度是不是和实际冷端温度一致。我用热成像仪看过自己的板子,DC-DC 模块附近温度能比环境高 5℃,如果你把 ADS122U04 放在电源旁边,内部传感器读出来的温度会明显偏高,补偿出来就会偏。解决方法是把 ADC 芯片放在远离发热源的位置,或者在软件里对冷端温度做校准偏移修正。

另外,如果冷端放的是大型接线端子,端子本身是一个巨大的散热片,上电预热后温度会慢慢上升,补偿值也会随之变化。这就要求系统首次上电后稍微等几分钟再进入运行状态,等热平衡后再采样;否则开机头几分钟误差特别难看。

5.4 快速排查表

现象可能原因处理方法
读数持续跳动输入/参考信号受干扰屏蔽线单端接地,PCB 走线分隔
读数偏高/偏低固定偏置失调未校准做零点校准,写入 EEPROM
全量程误差成比例RREF 精度不够换 0.1% 25ppm 精密电阻
UART 完全不通电平不匹配或波特率超差加电平转换,校正晶振
热偶读数差几十度冷端补偿逻辑漏算加上冷端电势再查表
校准后温度漂移大板卡发热导致冷端变化远离热源,增加热平衡时间

这份表是我在项目现场排查问题时的速查清单,基本覆盖了绝大多数“看起来像是芯片坏了”的故障。实际上 90% 的问题都是布局、地线、滤波和理解错误导致的,真正芯片损坏的情况极少。

最后再分享一点实际操作的体会:如果让我重新做一遍,我会在硬件上预留两路传感器切换的焊盘,一路默认 RTD、一路默认热电偶,这样同一块板子既能做温度变送器也能做热电偶输入模块,给后续产品复用留足弹性。软件上我会从一开始就启用 UART 的 CRC 校验,尽管 8 位机计算 CRC 会占运行时间,但工业现场长距离数字传输,多几个校验字节真的能省下大量排查时间。ADS122U04IPWR 和 PIC18F4620 这套组合,对我来说是把老平台重新激活的典型例子,希望这些记录能帮你少踩一些我踩过的坑。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进