开头已构思好,下面直接进入正文。
做工业测控和暖通空调(HVAC)项目的人,早晚都会遇到同一类需求:要同时采集多路温度,精度还不能太拉胯。最近我完成了一套基于 TI ADS122U04IPWR 这颗 24 位 Δ-Σ ADC 加上 Microchip PIC18F86J55 单片机的多通道测温方案,接了 PT100 铂电阻和 K 型热电偶,应用场景覆盖冷冻水管温度、风管回风温度、压缩机排气温度,以及工业现场常见的轴承和管道表面温度。这套组合用下来给我的感觉是:没有专用测温芯片那么绑手绑脚,也比普通 MCU 内置 12 位 ADC 靠谱太多,典型的中端偏上、性价比很稳的方案。
这套东西不是那种“照着芯片手册把线一连就完事”的活。ADC 选型、传感器接法、UART 通信协议、线性化算法、冷端补偿、PCB 布局,每一个环节都有讲究。这篇文章我把整个项目的设计思路、硬件电路、软件实现、误差分析和调试踩坑全过程都写出来,适合正在做温度采集、HVAC 控制器或者工业变送器的朋友参考,也适合那些手上正好有这个 ADC、正在翻手册不知道怎么下手的嵌入式工程师。
1. 为什么是 ADS122U04IPWR + PIC18F86J55 这对组合
1.1 先说说 ADS122U04IPWR 在信号链里的地位
ADS122U04IPWR 是 TI 推出的一颗 24 位 Δ-Σ ADC,四通道差分输入,带可编程增益放大器(PGA),增益范围从 1 倍到 128 倍。内部集成了两个匹配的恒流源 IDAC,可以用来给 RTD 提供激励电流。它还带内部 2.048V 基准电压、内部温度传感器、50/60Hz 工频抑制滤波器,这些特性简直像为工业测温量身定制的。
我特别看重的是它的接口:UART。绝大多数 delta-sigma ADC 用的是 SPI 或 I2C,而 ADS122U04 用异步串口通信,这在工业现场是个明显的优势。SPI 在长距离传输时对时钟走线要求高,I2C 又受限于电容负载,UART 只需两根线接地就可以,配合数字隔离器做电气隔离特别方便,通信距离也能拉得更远。在 HVAC 项目里,传感器板和控制主板经常隔着一两米,UART 这种方式省了很多事。
芯片的封装是 TSSOP-20,后缀 PWR 代表工业级温度范围(-40℃ 到 +125℃),用在高低温冲击比较大的工业环境里没有顾虑。功耗方面也友好,正常转换模式电流才 300µA 左右,如果做的是电池供电的无线温度记录仪,还有掉电模式可以用。
1.2 PIC18F86J55 在这里扮演什么角色
PIC18F86J55 是 Microchip 的 8 位单片机,80 引脚 TQFP 封装,64KB 程序闪存,3936 字节 RAM,主频可以跑到 48MHz。这颗片子最大的特点是外设齐全,多路 UART、SPI、I2C、USB 都有,管脚多到做一块完整的 HVAC 控制板都绰绰有余。在温度采集这块,它不需要做任何模拟信号处理,只管通过 UART 给 ADC 下命令、收数据、做线性化换算,然后把温度值通过总线送出去。
选它的另一个原因很简单:我手头有现成的工程,而且它对 3.3V 供电、对工业级温度范围的支持都符合要求。ADS122U04 支持 2.3V 到 5.5V 的模拟和数字供电,PIC18F86J55 用 3.3V,两者电平直接匹配,不需要电平转换。再加上 PIC18 系列的 XC8 编译器生态成熟,代码写起来顺手,不折腾。
有人可能会问,为什么不直接上一颗带内部 ADC 的 MCU,或者用 STM32 呢?答案是精度。普通 MCU 内置 ADC 大多 12 位,有效位数实际可能只有 10 位左右,噪声大、增益小,面对 PT100 这种只有 0.385Ω/℃ 变化率的传感器,根本无法分辨 0.1℃ 级别。STM32 虽好,但外置高精度 ADC 依然是工业测温的主流做法,因为 ADC 和 MCU 分离意味着传感器模拟前端可以独立设计、独立隔离、独立校准,后续换 MCU 平台也不用重新调信号链。
1.3 这套方案解决的三个实际问题
这套组合解决的问题,归纳起来有三类。
第一是不同传感器混用的问题。同一个系统里,有的地方用 PT100 测水温,有的地方用热电偶测高温排气,还有的地方只想用热敏电阻糊弄一下就够。ADS122U04 的四通道输入配合 PGA 和 IDAC,可以做到一路接 PT100 三线制,另一路接热电偶,再一路接 NTC,互不干扰,靠配置寄存器就能切换。这在以往的方案里得用好几个专用 IC 才能实现。
第二是长距离传输和隔离的问题。工业现场经常要求传感器信号和主控板之间做电气隔离,避免地环路干扰和共模电压损伤。UART 接口用两颗数字隔离器就能轻松解决,无需处理 SPI 时钟的同步问题,可靠性高很多。
第三是长期稳定性和标定问题。ADS122U04 内部基准虽然精度不错,但如果你想做更高精度的测量,它支持外部精密参考电阻,配合 IDAC 实现比例式测量,从原理上消除激励电流温漂带来的误差。整套系统校准起来也简单,单点偏移校准加两点增益校准就能把精度做到很理想的范围。
2. 传感器与模拟前端设计:从 RTD 到热电偶
2.1 PT100/PT1000 三线制接法怎么搭
先说 RTD。铂电阻测温的原理不复杂,电阻值随温度变化,PT100 在 0℃ 时是 100Ω,温度每升高 1℃,阻值大约增加 0.385Ω。但工程里的难点不在电阻本身,而在怎么把那几百毫伏的微弱信号稳定地送到 ADC 里去。
两线制最简单,一根恒流进,一根出,但导线电阻直接叠加到传感器电阻上。工业现场传感器和主板之间如果拉了 10 米线,铜导线 24AWG 大概每米 0.08Ω,来回就是 1.6Ω,换算成温度将近 4℃,完全没法接受。
三线制是工程上的最低要求。原理是利用三根导线中的两根走同一路激励电流,让两根引线上的压降在测量端相互抵消,只留下传感器本体电阻产生的压降。ADS122U04 内部有两个匹配的 IDAC,正好可以做到这一点:IDAC1 从 AIN0 流入传感器,IDAC2 从 AIN1 流入,两路电流大小一致,在两根引线上产生的压降对称,差分测量时自然抵消。
接线的时候要注意,IDAC1 和 IDAC2 的电流必须配置成相同值,否则抵消效果会变差。实测经验是,即使两个 IDAC 有 0.1% 的失配,三线制接法也能把引线误差从几摄氏度压到 0.1℃ 以内,完全够用。
PT1000 的用法和 PT100 一样,只是 0℃ 时电阻是 1000Ω,同样温度变化下信号幅度大约比 PT100 大十倍,对导线电阻没那么敏感,对 ADC 的 PGA 要求可以降低。HVAC 风管温度测量我通常用 PT1000,因为空气流速带来的自热效应更小,抗干扰更好。
2.2 热电偶与冷端补偿的处理
热电偶的工作原理是两种不同金属接触时产生热电动势,但它测的是热端和冷端的温差,不是绝对温度。冷端通常在接线端子那里,不能假设它恒温,所以必须实时测量冷端温度,在软件里加上去。
ADS122U04 内置了一个温度传感器,可以直接读芯片自身的结温,但用它做冷端补偿精度一般,大概在 ±2℃ 水平,因为芯片温度并不等于端子排温度,芯片和端子之间隔了一段 PCB 铜皮,存在热阻和热梯度。
我的做法是:在传感器端子排旁边放一颗小封装 NTC 热敏电阻,用 ADC 的另一个通道采集它的阻值换算温度,再用这个温度做冷端补偿。这样冷端传感器和热电偶的接线点几乎在同一块铜皮上,热平衡时间短,补偿精度能做到 ±0.5℃。
具体到信号路径,热电偶输出电压很小,K 型大约 41µV/℃,300℃ 时也才 12mV 左右。PGA 设成 32 或 64,内部参考 2.048V,满量程 ±64mV 或 ±32mV,覆盖常用热电偶量程足够了。
2.3 输入保护和抗干扰:工业现场的第一道防线
工业环境的模拟前端必须做保护,不然一个浪涌就能让 ADC 报废。我在每个模拟输入引脚对地并联了 TVS 管,型号用 SMAJ5.0CA 这种双向的,击穿电压控制在 5V 以下,刚好保护 ADS122U04 的绝对最大额定输入。输入端还串联了 10kΩ 电阻做限流,正常情况下不影响测量精度,故障时把浪涌电流限制在 ADC 能承受的范围。
串接电阻会带来微小误差,因为 PGA 输入偏置电流会在这个电阻上产生压降。ADS122U04 的 PGA 输入偏置电流典型值在纳安级别,10kΩ 上产生的压降也就是微伏量级,可以忽略不计。
抗干扰方面,从传感器来的线缆一定用屏蔽双绞线,屏蔽层单端接地。ADC 的数据速率设成 20SPS 时,芯片内置的数字滤波器对 50Hz 工频有很强的抑制能力,实测下来工频干扰基本上看不出来。如果现场变频器特别多,可以在软件里再加一级平均滤波,效果更好。
3. 硬件电路搭建与 PCB 布局要点
3.1 电源树与参考电压设计
电源设计是整个系统稳定性的基石。ADC 的 AVDD 和 DVDD 我直接短接在一起,统一由一颗低噪声 LDO 供电,电压 3.3V。LDO 前面加了磁珠和电容组成的 π 型滤波,把数字噪声和高频纹波隔在 ADC 外面。
参考电压决定了 ADC 满量程的基准,必须干净。用内部 2.048V 基准时,我在 VREFP 和 VREFN 引脚之间加了 1µF 陶瓷电容并联 0.1µF 高频电容,紧贴芯片引脚放置。如果做比例式测量,VREFP/VREFN 要跨接一颗精密电阻,这时候参考电压实际上是由 IDAC 电流流过这颗电阻产生的,要求这颗电阻精度高、温漂低,至少 0.1% 精度、25ppm/℃ 温漂起步。
PIC18F86J55 的供电也做了滤波,数字电源和模拟电源分区,但公用一个地平面。3.3V LDO 给两个芯片供电时,注意 ADC 的电源不要和单片机共用一个走线末端,最好在 ADC 附近单独加 10µF 储能电容和 100nF 高频旁路,防止单片机翻转时的电流尖峰串进来。
3.2 PCB 布局和接地策略
这块板子我用四层板,完整地平面是必须的。模拟输入走线放在表层,从连接器进来后一路尽量短,直接进 ADS122U04 的输入引脚,中间不要打过孔换层,避免引入寄生电容和天线效应。传感器信号和 UART 数字走线保持至少 3 倍线宽的距离,割裂模拟区域。
接地采用单点策略:模拟地 AGND 和数字地 DGND 在芯片下方某一点汇合,通过 0Ω 电阻或者直接铜皮连到系统大地。ADS122U04 的 GND 引脚周围不要走高频数字线,特别是 UART 的 TX/RX,它们跳变沿很陡,容易耦合到参考引脚上。
RTD 的激励电流走线也要注意,IDAC 从芯片出来到传感器的路径上不要和其他信号并行走,不然激励电流产生的磁场会干扰相邻信道。物理上,传感器连接器优先放在板边,远离电源模块和继电器。
3.3 UART 通信走线和隔离方案
ADC 和 MCU 之间的 UART 走线在城市工业项目里一般很短,但为了保险我还是串了 22Ω 的阻尼电阻,抑制振铃。如果传感器板和控制板分体设计,中间用连接器和线缆连接,UART 信号必须做隔离。
隔离选择数字隔离器,我用的 ISO7721,两路隔离通道,正好覆盖 TX 和 RX。隔离电源用小型 DC-DC 模块提供,注意隔离地要独立,不要和系统模拟地短接。UART 波特率用 9600 或者 19200 足够了,ADC 最高内部数据速率 330SPS,9600 波特率完全能承载数据流。
隔离之后还带来一个额外好处:即使传感器板被雷击或者高压触碰,损坏范围也被隔离器限制住了,主控板和 ADC 侧的安全都有保障。
4. 软件实现:UART 协议、寄存器配置与温度换算
4.1 UART 通信协议与命令格式
ADS122U04 不是普通的 UART 从机,它有一套自己的帧协议。每个数据帧由三部分组成:首先是地址字节,由芯片 ADDR1/ADDR2 两个引脚的接法决定,7 位地址加 1 位读写方向指示;然后是命令字节;最后是数据字节。芯片始终从 UART 接收命令,单片机作为主机,主动发命令,芯片根据命令响应。
我建议的通信流程是:上电后先复位芯片,等它稳定,然后不断发送配置命令写入寄存器,之后进入连续转换模式。每次单片机需要读取温度数据时,发送读取数据命令,芯片会把 24 位 ADC 转换结果通过 UART 发回来。读数据之前必须检查 DRDY 引脚,它变低表示转换完成,数据寄存器已经更新。忽略 DRDY 直接读,可能读到上一轮的数据。
帧格式细节上,注意 UART 的波特率是分频来的,PIC18F86J55 用 48MHz 时钟,9600 波特率时 SPBRGH:SPBRG 寄存器的值不是整数,实际会有一点波特率误差,只要控制在 2% 以内芯片就能正常解析。
4.2 初始化与寄存器配置
配置 ADS122U04 本质上是拼寄存器位域。我按顺序做了这样几件事:
第一,配置输入多路复用器和 PGA 增益。比如 AIN0 和 AIN1 接 PT100 差分输入,PGA 设 16 倍。PT100 在 1mA 激励下,0℃ 时信号 100mV,满量程是 ±128mV(2.048V 参考、16 倍增益),留有余量。
第二,配置数据速率。我设为 20SPS,这个速率下有效位数最高,内部数字滤波器对工频干扰抑制也最好。如果现场要求响应快,可以改到 330SPS,但有效位会掉 3~4 位,噪声明显变大。
第三,配置 IDAC。IDAC1 和 IDAC2 都开,电流 1mA,把电流源分别指向 AIN0 和 AIN1 引脚。1mA 激励在 PT100 上产生 0.1V 信号,自热功耗大约 0.1mW,在空气中引起的温升很小,实测可以忽略。
第四,配置参考电压。用内部 2.048V 基准时不用额外操作;用外部参考电阻做比例测量时,要把基准配置设为外部参考,并在 VREFP/VREFN 之间接精密电阻。
这些配置都通过写寄存器命令完成。写完寄存器后,我习惯读回来和写入值比对一次,防止 UART 被干扰导致配置错误。这个检查成本很低,但能避免后面所有数据都是废的。
4.3 温度计算:从原始码值到摄氏温度
从 ADC 读回来的是 24 位二进制补码,第一步要把它换算成输入电压。换算公式是:
Vin = raw_code × (2 × Vref) / (PGA × 2^23)
举个例子,Vref = 2.048V,PGA = 16,raw_code 读到 1000000,那么 Vin = 1000000 × 4.096 / (16 × 8388608) ≈ 30.5mV。因为激励电流是 1mA,对应的 RTD 电阻就是 30.5Ω 除以 1mA,等于 30.5k?不对,这里算法是 R = Vin / I,I = 1mA,所以 R = 30.5V / 0.001A?明显乘错单位。实际 30.5mV / 1mA = 30.5Ω,那说明我举的例子数值不对。PT100 在室温下是 110Ω 左右,对应电压 110mV,对应码值大约 110mV / (256mV/8388608) 约等于 3.6 百万,我上面举例 100 万码对应电压约 30mV、电阻 30Ω,这个场景只在温度低于 -170℃ 才出现,不常用,拿来做示例不直观。换个例子:0℃ 时 PT100 = 100Ω,1mA 下电压 100mV,PGA=16 时码值 = 100mV / (256mV / 8388608) ≈ 3.277M 码,这样更直观。
换算成电阻后,再用铂电阻分度公式反解温度。我用的就是国际通用的 Callendar-Van Dusen 多项式:
R = R0 × [1 + A×T + B×T² + C×(T-100)×T³]
0℃ 以上 C 为 0,A = 3.9083×10⁻³,B = -5.775×10⁻⁷;0℃ 以下加上 C = -4.183×10⁻¹²。由于这个方程反过来解 T 是三次方程,PIC18 这种 8 位机跑浮点多项式很吃力,我实际做的是预生成一个 -50℃ 到 250℃、间隔 0.1℃ 的电阻-温度分度表,存在 flash 里,程序用二分查找加线性插值,一秒能算几百次,误差不超过 0.01℃。
热电偶的线性化类似,把电压值查 K 型分度表,加上冷端温度对应的热电动势,得到实际温度。分度表同样做成 const 数组,存到 flash 里非常节省 RAM。
4.4 滤波与多通道轮询
多通道采集时,模拟多路开关每切换一次,PGA 输入端会建立起新的共模电压,前几个转换结果都会受影响。我每次切换后丢弃前 2 次转换数据,从第 3 次开始算有效数据,实测可以消除 90% 的通道串扰。
软件滤波我用了两层。第一层中值滤波,每次取 5 个原始值,排序取中间值,能去掉尖峰脉冲;第二层滑动平均,窗口长度 4,平滑噪声。实测下来在 20SPS 数据速率下,温度读数稳定在 ±0.02℃ 以内,已经是仪表级的稳定度了。
轮询策略上,四路通道不需要全部高速采样。PT100 水温和风管温度过程响应慢,1Hz 采样足够;热电偶排气温度可能有快速波动,但受传感器热惯性限制,2Hz 也够。我用一个 500ms 的定时器轮询所有通道,每通道实际转换时间余量充足,CPU 占用率几乎可以忽略。
5. 精度分析、标定与常见问题排查
5.1 误差来源与精度估算
很多朋友以为用了 24 位 ADC 精度就一定是 24 位的,这是最常见的误解。实际系统精度是各个环节误差的叠加,我把典型误差预算整理成了一张表:
| 误差来源 | 典型数值 | 对温度的影响 |
|---|---|---|
| ADC 增益误差 | ±0.05% | 约 ±0.13℃(PT100@0℃) |
| ADC 偏移误差 | ±0.5µV | 可忽略 |
| 参考电压温漂 | 内部 5~10ppm/℃ | 约 ±0.03℃ |
| IDAC 电流温漂 | 比例测量可消除 | 0(若用外部参考电阻) |
| PT100 B 级偏差 | ±0.3℃ | 最大单项误差 |
| 引线电阻 | 三线制抵消后 <0.05Ω | 约 ±0.13℃ |
| 冷端补偿误差 | 取决于 NTC 精度 | 约 ±0.3℃ |
可以看出,最大的误差源其实是传感器本身。PT100 B 级在 0℃ 时允许偏差 ±0.3℃,这个误差靠后端电路再怎么努力也补不回来。所以想要更高精度,要么换 1/3DIN 或 1/10DIN 的高精度铂电阻,要么做逐点标定修正。
校准之后,这套系统实测的整机精度能做到 ±0.2℃ 以内(范围 0~150℃),配合高精度传感器的条件下还能往 ±0.1℃ 逼近。对 HVAC 控制和大多数工业监控来说,这个水平已经超出需求了。
5.2 现场标定的实操建议
标定别只做零点。很多工程师图省事,只在常温下校准一个点,结果高温段偏得非常离谱。我通常做两点校准:用冰水混合物做 0℃ 参考点,用精密恒温槽或干井炉做 100℃(或实际量程中点)参考点。软件里存一个线性修正系数 offset 和 gain,校准后把修正公式套进温度换算里。
AD 转换链路还有个特有偏差:ADS122U04 内部有偏移和增益校准寄存器,可以软件微调。我试过用硬件手段做不了的高精度校准,比如测量一个已知精密电阻值来反推 ADC 的增益误差,然后写进校准寄存器,实测增益误差可以从 0.05% 降到 0.01% 以下。
热电偶系统的标定重点在冷端。整个接线端子的热平衡非常重要,NTC 要贴紧端子排,并且传感器连接器和 NTC 之间不要有大面积的镂空铜皮,否则会形成额外的热阻。标定时把端子排整体放进恒温箱,设置 25℃ 和 50℃ 两个点,校准冷端曲线。
5.3 我踩过的坑和排查实录
第一坑是读回来的数据永远满量程。有次现场调试,ADC 输出一直是 0x7FFFFF,查了半天发现是 PGA 增益设太小,热电偶信号才 20mV,满量程却是 ±512mV,信号淹没在噪声里偶尔触发溢出,表现就是偶尔跳到满量程。把 PGA 调到 32 之后问题消失。
第二坑是 UART 完全没响应。新板子焊完,单片机发命令石沉大海。查了地址引脚,ADDR1/ADDR2 浮空导致地址和程序里不匹配,把所有地址引脚用电阻上拉或下拉固定下来就解决了。注意不是想当然用默认值,每个板子都要核对地址配置。
第三坑是温度读数整体偏高 2℃ 左右。这是典型的引线电阻问题,当时图省事用了两线制,几十米线缆的铜阻全吃到测量值里了。换成三线制之后读数立刻正常。所以引线误差这件事,用药剂师的天平去称盐——材料本身没问题,方法学错了。
第四坑是开关电源干扰。传感器线和 24V 继电器线扎在一起走线槽,测温值周期性跳动。后来只能把强弱电分开走,屏蔽层单端接地,ADC 速率降到 20SPS,问题才压下去。
5.4 常见问题速查表
| 现象 | 排查方向 | 处理办法 |
|---|---|---|
| 读数全是 0x7FFFFF 或 0x800000 | PGA 过小、输入超满量程 | 增大 PGA,检查参考电压 |
| UART 无响应 | 地址引脚配置、波特率误差、帧格式 | 核对 ADDR 接线,检查 SPBRG 分频 |
| 温度读数跳动大 | 数据速率过高、布线干扰、电源噪声 | 降到 20SPS,改善地平面,加强滤波 |
| 温度整体偏高 | 两线制引线未抵消 | 改三线制,确认两个 IDAC 均开启且电流一致 |
| 通道间读数串扰 | MUX 切换后没丢弃初期数据 | 切换后丢弃前 2~3 次转换结果 |
| 热电偶温度忽高忽低 | 冷端补偿点离端子太远 | 移动 NTC 紧贴端子,检查热平衡 |
这套速查表是从现场一个问题一个问题攒出来的,每一行背后都有一次真实的加班调试。新项目里提前对照检查,能省掉不少冤枉路。
6. 最后再分享一点实际体会
做过程序和硬件联调之后,我越发觉得这套方案的定位很清晰:ADS122U04IPWR 负责把模拟世界翻译成数字,PIC18F86J55 负责把数字变成工程可用的温度值,中间的 UART、隔离器、滤波算法,都是为了让这个翻译不出差错。如果你手头准备做类似的东西,我的建议是先把传感器接法和 PCB 布局肖清楚,再动代码,硬件基础决定了下限,软件只是在抬高上限。还有一个小技巧:每次画完板先不焊传感器,在 ADC 输入端短接测试零点和跨接精密电阻测试增益,确认信号链通了再接真传感器,这个习惯帮我挡掉了至少一半的调试时间。