基于ADS122U04与PIC32的高精度工业温度采集系统设计

发布时间:2026/11/4 6:01:47
基于ADS122U04与PIC32的高精度工业温度采集系统设计

很多年前我刚接触工业测温项目时,觉得“测温度”这件事特别简单:找个传感器,接个单片机,读个ADC不就完事了吗。可真到了现场,发现完全不是那么回事——长线上信号衰减、工业环境里的共模干扰、传感器本身的非线性、冷端补偿没做好导致的几度漂移,每一项都能让你在调试台前坐到半夜。后来我慢慢总结出一条经验:测温系统的瓶颈往往不在 MCU,而在模拟前端和数据采集链路。今天想借一个实际做过的项目来聊聊这套链路:用 ADS122U04IPWR 这颗带 UART 接口的 24 位 ΔΣ ADC,配合 PIC32MX764F128L,实现工业和 HVAC 场景下的高精度温度采集。这篇文章适合正在做温度采集、传感器信号调理、或者想了解 ΔΣ ADC 实际工程用法的朋友,内容会覆盖方案选型、硬件设计、寄存器配置、线性化处理,还有调试现场踩过的坑。

1. 方案选型与整体思路:为什么是这两颗芯片

1.1 先看应用场景的需求

工业和 HVAC 的温度测量,和实验室里搭个测试台有本质区别。HVAC 系统里,你要测的是风管送风温度、冷冻水供回水温度、压缩机吸气排气温度;工业现场更复杂,可能是管道表面温度、反应釜介质温度、电机轴承温度。这些场景有几个共同特点:

  • 传感器离控制器远,线缆长度从几米到几十米不等,信号容易衰减和引入噪声。
  • 现场存在强电设备、变频器、继电器,电磁干扰是常态。
  • 温度范围跨度大,有些点要求 0.1°C 级的分辨率,有些点只需要 ±0.5°C 的精度。
  • 系统往往不止一路测温,一个控制器可能要挂十几个甚至几十个传感器。

在这些约束下,测温方案的核心矛盾就出来了:既要高分辨率、低噪声,又要抗干扰,还要支持多通道。普通的 12 位或 16 位逐次逼近型 ADC 根本扛不住长线传感器的小信号,这时候就得请出 ΔΣ ADC。

1.2 ADS122U04 在信号链里的角色

ADS122U04 是 TI 推出的一款 24 位 ΔΣ ADC,但它的特殊之处不在于“24 位”这个参数,而在于它的接口:UART。这和我以前用过的 ADS1220(SPI 接口)有本质差异。UART 接口的 ADC 在工业场景里有一个天然优势——远距离传输。SPI 是同步串行接口,时钟线和数据线必须同步工作,线一长就容易出时序问题;UART 是异步接口,只要波特率对得上,两根线就能跑,而且可以直接转成 RS-485 做长距离传输。

这颗 ADC 内置了可编程增益放大器(PGA)、基准电压源和两路激励电流源,这些资源对于直接驱动 RTD 和热电偶来说非常关键。后面我会专门讲怎么配置这些内部资源,这里先记住一个结论:ADS122U04 基本上把模拟前端的大部分工作都接了下来,MCU 只负责通过 UART 发指令、收数据,做软件层面的处理。

1.3 PIC32MX764F128L 为什么够用

PIC32MX764F128L 属于 Microchip 的 PIC32MX 系列,MIPS M4K 内核,主频 80 MHz,Flash 128 KB,RAM 32 KB。做温度采集这种任务,这个配置绰绰有余。很多人有个误区,觉得主频越高越好,其实在数据采集系统里,MCU 的实时响应能力、外设的灵活性、开发工具链的成熟度,往往比绝对算力更重要。

PIC32 系列的优势在于它的外设组合很丰富,尤其是 UART 模块。这个项目里我用了两路 UART:一路和 ADS122U04 通信,另一路跟触摸屏或者上位机通信,互不干扰。另外,PIC32 的 DMA 控制器可以直接把 UART 收到的数据搬到内存缓冲区,CPU 不用频繁进中断,这在多通道连续采样时能省下不少开销。关于 DMA 的用法,后面我会给一段可以直接抄的配置代码。

1.4 为什么不选分立方案

刚开始我也考虑过另一种方案:用仪表放大器加独立 ADC,再配一个基准源,全部自己搭。这样做的好处是每一级都能自己控制,但坏处也明显:元件多、成本高、PCB 面积大、调试周期长。尤其在批量产品里,分立方案的温漂一致性很难控制,每一块板子都要单独校准。

ADS122U04 这种高集成度方案,把 PGA、基准、激励电流源、温度传感器都塞进一颗芯片里,板子上省掉了一大片外围电路。而且模拟前端在芯片内部,布局布线的一致性比手工搭的好很多,长期稳定性也更有保障。对于工程产品来说,“少一个元件就少一个故障点”这句话永远是金科玉律。

2. 硬件设计要点:从传感器到 ADC 再到 MCU

2.1 RTD 和热电偶的信号特征差异

硬件设计的第一步,是先搞清楚你手里的是什么传感器。这个项目里我同时用到了 Pt100 铂电阻和 K 型热电偶,它们的信号特征完全不同。

Pt100 属于电阻型传感器,0°C 时阻值 100 欧姆,温度每升高 1°C 阻值大约增加 0.385 欧姆。它的输出是电阻值,需要给一个恒定电流激励,把电阻变化转换成电压变化再送给 ADC。激励电流的选择有讲究:电流太小,信号幅度低,信噪比差;电流太大,自热效应会让测量值偏高。我用的 500 μA 激励电流,在 Pt100 上满量程压降也才几百毫伏,自热误差可以控制在 0.02°C 以内。

热电偶就完全不同了。它输出的是电压,K 型热电偶大约 40 μV/°C,信号极其微弱。而且热电偶本身就是个差分信号源,它的参考端(冷端)需要做温度补偿。这个项目里我把冷端补偿用的热敏电阻就近贴在接线端子上,通过 ADS122U04 的内部温度传感器读取结温,再在软件里做补偿计算。这部分后面专门讲。

2.2 输入通道分配与接法

ADS122U04 有 4 个差分输入通道,我用通道 1 接 Pt100,通道 2 接 K 型热电偶,剩下的通道作为备用扩展。这里有一个硬件设计上最容易踩的坑:RTD 用了几线制接法。

三线制 RTD 是工业里最常见的接法,它能抵消导线电阻带来的误差。接线方式是这样:一根激励电流线从 ADC 的 IDAC 引脚出来,经过 RTD 再回到公共端;另外两根线分别接到 ADC 的正负输入端。由于两根导线上的电压降方向和激励电流方向的关系,测量结果里导线电阻的影响可以相互抵消。这个原理我以前没细想,直到有一次用两线制接法做长线测试,实际读数和现场温度计差了差不多 1.5°C,才真正意识到三线制的意义。

ADS122U04 的差分输入通道 AINP 和 AINN,接法上还要注意一点:AINN 端不能简单地接地,要让整个差分输入对都处于一个合适的共模电压范围内。这颗 ADC 的内部 PGA 在增益大于 1 时,共模输入范围是有限制的,参考输入电压和激励电流源的设置都会影响可测范围,需要按数据手册的公式仔细算一遍,不能拍脑袋接。

2.3 数字接口的连接与电平匹配

ADS122U04 的 UART 接口支持 1.8V 到 3.3V 逻辑电平,PIC32MX764F128L 的 GPIO 供电是 3.3V,可以直接互连,不需要电平转换芯片。

不过有一个细节必须注意:ADS122U04 的 UART 是半双工还是全双工?实测下来它的 DIN 和 DOUT 是两个独立引脚,可以做成全双工,但工程上我更推荐用半双工结构——MCU 通过 DOUT 发送命令,ADC 在同一个引脚上回数据,这样只用一根数据线和一根参考地线就能完成通信。接线方式上,我在 DOUT 线上串了一个 1 kΩ 电阻做阻尼,防止信号反射;在靠近 ADC 一侧放了一个 100 nF 的去耦电容,两端的电源引脚都按数据手册要求放了 10 μF 和 100 nF 组合。

2.4 PCB 布局的几条硬经验

模拟电路的 PCB 布局,有时候比原理图更决定成败。这个项目里我踩过一次教训:第一版 PCB 为了布线方便,把 ADS122U04 放在板子边缘,下面就是一颗开关电源芯片的走线。结果上电后温度读数总是在最后几位跳动,怎么看都不稳定。后来把 ADC 换到远离开关电源的位置,地平面做了完整铺铜,模拟地和数字地单点连接,噪声立刻降了一个数量级。

有几条经验可以分享:

  • ADC 的模拟电源和数字电源要分开走线,各用一颗磁珠串联,防止数字噪声窜到模拟电源上。
  • 基准电压引脚旁边的去耦电容要尽量靠近引脚,走线短而粗。
  • 传感器信号线进入 PCB 后,最好走内层或者用地线包住,不要在板子表面长距离平行走线。
  • 所有接地的过孔要尽量多打几个,降低地回路的阻抗。

2.5 抗雷击与静电防护

工业现场的传感器线缆经常暴露在外部环境里,感应雷和静电是绕不开的问题。温度传感器接口处我加了一级保护电路:TVS 管加上 PTC 自恢复保险丝。信号输入端分别对地接了一颗双向 TVS,限制共模电压;差分线之间再接一颗,限制差模电压。PTC 的作用是当 TVS 导通后,把短路电流限制在一个安全范围里,保护 ADC 内部的 ESD 结构。

这个保护电路看起来很简单,但实际效果非常明显。有一次客户现场打雷,隔壁设备都被打坏了,这块测温板只是保险丝烧断,换上之后恢复工作。做工业产品,别舍不得这几个元件。

3. 软件设计与核心实现:寄存器、命令帧与数据处理

3.1 设备地址与 UART 通信协议

ADS122U04 支持最多四颗芯片挂接在同一条 UART 总线上,通过地址位来区分。这个设计比较特别,它不能用普通的 UART 发送方式直接驱动,而是要在发送一个字节之前,先把引脚拉低一段时间表示起始条件,再发送地址字节。

工程上我建议一条总线上只挂一颗 ADC,原因很简单:当多颗 ADC 共线时,调试难度直线上升,而且一旦其中一颗芯片出问题,整条总线都瘫了。项目里我用了 4 颗 ADS122U04,每个处理器带一颗,用独立 UART 通信,稳定性和可维护性都好很多。

命令帧格式按照数据手册定义,最常用的三条命令:

  • 写寄存器命令:从某个寄存器地址开始连续写入若干字节
  • 读寄存器命令:从某个寄存器地址开始连续读取若干字节
  • 启动转换命令:告诉 ADC 开始一次新的转换

每条命令都由地址字节、命令字节和数据字节组成。实际项目中,我先用示波器抓了波形,确认起始条件和波特率都匹配后,才开始写驱动代码。

3.2 寄存器配置详解

ADS122U04 的寄存器配置,决定了整个测量系统的性能边界。我把每次初始化时要写的寄存器整理成了一张表,按地址顺序排列:

寄存器地址寄存器名称关键配置说明
00h配置寄存器 0通道选择、增益设置、输入模式我设为通道 1,增益 16 倍
01h配置寄存器 1数据速率、滤波器模式、转换模式20 SPS,连续转换
02h配置寄存器 2基准源选择、基准电压、IDAC 设置内部基准,IDAC 500 μA 接到通道 1
03h配置寄存器 3IDAC1/IDAC2 路由、内部温度传感器温度传感器开,用于冷端补偿
04h配置寄存器 4电流源大小、比较器设置500 μA,关闭比较器
05h配置寄存器 5输入偏置、系统监控、数据编码二进制补码,关偏置

寄存器 0 的增益配置要结合具体传感器来定。热电偶信号只有几十微伏每度,满量程也就几十毫伏,所以我把 PGA 增益设为 16 倍;而 Pt100 在三线制接法下,500 μA 激励产生的压降在 0°C 时只有 50 毫伏左右,16 倍增益后即使用 24 位分辨率,也还有很大的余量。

寄存器的写入顺序也有讲究。我第一次调试时上来就写寄存器 0 配置通道,结果数据一直读不对。后来查阅手册发现,ADS122U04 在上电后要先让芯片进入空闲状态,才能安全地写入配置。所以初始化代码的统一顺序是:发复位命令,延时 10 ms,写配置寄存器,再次延时,发启动转换命令。顺序乱一步,结果就是数据乱码或者芯片不响应。

3.3 PIC32 端的 UART 驱动和 DMA 接收

PIC32 的 UART 初始化,重点在于波特率发生器的设置。80 MHz 的外设时钟下,要得到 115200 波特率,需要计算分频系数。PIC32 的 UART 波特率计算还有些特殊,它有一个小数分频位,可以更精确地设置。

// UART1 初始化,用于和 ADS122U04 通信 void UART1_Init(void) { U1MODE = 0; U1MODEbits.STSEL = 0; // 1 位停止位 U1MODEbits.PDSEL = 0; // 8 位数据,无校验 U1MODEbits.BRGH = 1; // 高频模式 U1BRG = 42; // 80 MHz / (16 * (42 + 1)) ≈ 116279,接近 115200 U1STAbits.UTXEN = 1; U1STAbits.URXEN = 1; U1MODEbits.ON = 1; } // DMA0 配置:UART1 接收数据自动存入缓冲区 void DMA0_Init(void) { DMA0CON = 0; DMA0CONbits.SIZE = 0; // 字节传输 DMA0CONbits.DIR = 0; // 外设到内存 DMA0INTbits.DMAIE = 1; // 使能 DMA 中断 DMA0INTbits.CHCIE = 0; DCS0 = 0; DCRS0 = (unsigned int)rxBuffer; DMA0CNT = sizeof(rxBuffer) - 1; DPTR0 = (unsigned int)&U1RXREG; DMACONbits.ON = 1; DMA0CONbits.CHEN = 1; // 使能 DMA 通道 }

这段代码里有一个地方要特别注意:PIC32 的 DMA 外设地址一定要指向U1RXREG,不是U1RXREG的指针地址。我第一次写的时候用了&U1RXREG,结果 DMA 把内存地址当成了外设地址,数据全部乱了。这个细节值得记住。

3.4 温度数据读取与线性化处理

每次转换结束后,ADS122U04 的 DRDY 引脚会拉低,表示数据准备好。我在中断里检测到这个下降沿后,通过 UART 发送读数据命令,然后 DMA 自动把 24 位的数据搬到缓冲区。CPU 再从缓冲区解析数据。

从原始码值换算成温度,第一件事是把二进制补码转成有符号整数:

int32_t raw24 = (data[0] << 16) | (data[1] << 8) | data[2]; if (raw24 & 0x800000) { raw24 |= 0xFF000000; // 符号扩展 }

然后根据增益和基准电压计算实际电压:

double voltage = (double)raw24 * VREF / 8388608.0 / PGA_GAIN;

Pt100 的温度和电阻的关系非常接近线性,但在 0°C 以下和 150°C 以上,二次项的影响就不能忽略了。我用的是 Callendar-Van Dusen 方程,分段处理:

  • 0°C 以上:Rt = R0 * (1 + At + Bt^2)
  • 0°C 以下:Rt = R0 * (1 + At + Bt^2 + C*(t-100)*t^3)

代码里用迭代法求解温度,从 25°C 初始值开始,迭代 5 次就能收敛到 0.01°C 以内。这个方法比查表法省内存,比直接线性近似更准,在缺乏浮点单元的 MCU 上也能接受计算量。

3.5 热电偶冷端补偿的完整实现

热电偶测的是热端和冷端的温差,Cold Junction Compensation 是整个测量链路里最容易出错的一环。我采用两层方案:

第一层,用 ADS122U04 内部的二极管温度传感器测芯片的结温。这个温度基本等于 PCB 上接线端子附近的温度,作为冷端温度的一个初始近似。第二层,在接线端子附近再贴一颗高精度 NTC 热敏电阻,用另一个 ADC 通道读取,做更精确的冷端修正。

两层数据在软件里取加权平均,然后查 K 型热电偶的多项式系数,把冷端温度换算成对应的毫伏补偿量,加到热电偶的测量电压上,再用反多项式求出热端温度。

这里有一个很多人会忽略的坑:冷端补偿的传感器必须离热电偶接线端子足够近,而且是热耦合良好,不是简单地放在同一块 PCB 上就行。有一次我把 NTC 放在板子另一角,和接线端子隔了几厘米的距离,结果冷风一吹,补偿值和实际端子温度差了四五度,热电偶读数直接偏了 2°C 多。后来把 NTC 移到端子正下方,用导热胶填充缝隙,数据立刻稳定了。

4. 实际调试中的问题与排查

4.1 UART 通信不稳定的排查过程

第一次上电调试,最典型的故障就是读不到数据,或者读到一堆乱码。我用示波器量了 DIN 引脚的波形,发现起始条件的低电平宽度不对。ADS122U04 要求起始条件至少保持 tSTP 的时间,而我单片机里的延时函数在高优先级中断的影响下产生了抖动,导致时序不满足。

解决方案是关掉中断再发命令,或者用忙等的方式执行延时。PIC32 的中断优先级配置也要注意,UART 接收中断的优先级不要设太高,避免频繁打断其他任务的时序。

如果数据偶尔错乱,优先检查两个方面:波特率误差和参考地电位。UART 对波特率误差容忍度有限,我实测下来,如果两端的波特率误差超过 2%,数据出错率就会明显升高。

4.2 温度读数跳动的常见原因

温度读数最后两位跳动,是几乎所有 ADC 系统都会遇到的问题。我遇到的情况分三类:

第一类是电源噪声,最典型的特征是跳动频率和开关电源的开关频率一致。解决方法是给 ADC 的电源加 LC 滤波,同时把 PGA 增益从 16 倍降到 8 倍试试,有时候信号余量足够,降低增益反而能减少跳动。

第二类是基准电压不稳定。ADS122U04 的内部基准精度不错,但负载变化会影响它。排查方法很简单:把输入端短接,看输出码值是否稳定。如果不稳定,说明噪声源在 ADC 内部或者基准,不在传感器信号链上。

第三类是真信号噪声。热电偶的电压本来就小,长线分布电容和共模电压会导致 ADC 输入端的有效信号产生毛刺。我把采集速率从 20 SPS 降到 5 SPS,配合数字滤波器的 50/60 Hz 抑制功能,跳动幅度从 0.3°C 降到了 0.05°C 以内。

4.3 校准与验证方法

做温度测量产品,校准是逃不掉的一步。我的做法是在生产阶段用精密电阻箱和标准温度计做两点校准,然后在软件里存一个偏移量和增益系数,对最终温度值做修正。

具体校准流程:

  • 把高温探头放进冰水混合物,读到的温度记为 offset
  • 把探头放进恒温槽,设定一个标准温度,再读一次,计算出增益误差
  • 把增益系数和偏移量写入 EEPROM,每次初始化时加载

这个流程虽然简单,但能覆盖传感器和 ADC 的整体偏差。如果要求更高的精度,建议做多点校准,用最小二乘法拟合一个修正曲线。

4.4 一张实用的问题排查表

我把调试过程中遇到的高频问题整理成了表格,方便排查:

问题现象可能原因排查方法
数据全零或全满转换未启动、通道配置错误检查寄存器 0 的通道选择,检查启动命令
数据乱码起始条件时序不对、波特率不匹配示波器抓波形,检查起始条件和 UART 分频
室温附近跳动大电源噪声、基准不稳短接输入测试,给电源加滤波
读数整体偏高激励电流偏大、自热效应降低 IDAC 电流,减少激励时间
读数受环境温度影响冷端补偿不到位确认补偿传感器贴近接线端子
长线时读数漂移线缆电阻不一致、屏蔽层接地换三线制接法,屏蔽层单端接地

5. 后续扩展与经验总结

这个项目做完之后,我把它扩展成了一个支持 8 路温度采集的通用模块。方法也很简单:增加一颗 ADS122U04,每颗芯片负责 4 个通道,PIC32 上用两组独立 UART 分别通信,通过 DMA 自动采集数据。上位机通过 Modbus 协议读取温度值,可以直接接入现有的 PLC 系统。

有人可能会问,为什么不用一颗多通道的 ADC 一次性搞定所有通道?我当时的考虑是故障隔离:如果一颗 ADC 坏了,只影响它负责的那几个通道,不会让整套系统瘫痪。而且每颗 ADC 可以独立配置增益和激励电流,RTD 和热电偶可以随心所欲地混接,灵活性比分立方案强很多。

整个项目开发下来,我最深的体会是:测温系统的精度不是靠某一个高端元件撑起来的,而是传感器、激励源、ADC、基准、软件算法和 PCB 布局共同作用的结果。任何一个环节做得马虎,最终都会在温度读数上体现出来。

最后分享一个小技巧:调试这类 ADC 系统,永远准备一个高精度的电压源和一个小型恒温槽。它们的作用不只是校准,更重要的是帮你分清问题出在传感器、模拟链路,还是数字处理上。我见过太多工程师在数字滤波代码里折腾了半天,最后发现问题是热电偶焊点老化导致的热阻变大——用电压源一量就知道传感器坏了。工具到位,调试效率能提高好几倍。