做工业或 HVAC 温度采集,这两年我陆陆续续写了不少方案。早期习惯用 16 位 ADC 加小型 MCU,凑合够用,但一到传感器五花八门的场合,就得反复换芯片、改电路、补滤波,板子越改越乱。最近一个冷冻水供回水温度、风管温度、电机绕组温度混采的项目,让我彻底换了一条路子:主控用 PIC32MX664F064L,ADC 用 TI 的 ADS122U04IPWR,走 UART 通信,整个信号链清爽很多。这篇就围绕这个组合,把我在选型、硬件、固件、标定和排障上踩过的坑和最终落地的做法完整写出来。
如果你正准备做多路 PT100/PT1000、NTC 热敏电阻、热电偶混用的采集模块,又不想在模拟前端上堆太多分立元件,这套方案值得参考。ADS122U04IPWR 是带 UART 接口的 24 位 Δ-Σ ADC,自带传感器激励电流源和基准源,内部还有温度传感器可以做冷端补偿;PIC32MX664F064L 属于 PIC32MX6 系列,80MHz 主频,外设基本不用省着用,关键是调试和升级时还有一块余量。两个芯片加一起就能把 4 通道温度的采集、换算、校准、上报整套链路做掉。
1. 为什么盯上这个组合:先把需求捋清楚
1.1 现场到底要测什么
HVAC 和工业现场的温度测量,表面上简单,真做起来却烦。HVAC 一侧,冷冻水供回水温度习惯用 PT1000 或者 NTC 热敏电阻,风管温度也类似,空气流速不高的情况下对响应速度没什么苛刻要求,但长度几十米的线缆很常见。工业侧就不一样了,电机绕组和轴承温度一般用 PT100,因为要穿过接线盒,导线电阻变化不能忽略;少数场合还会用热电偶,量程宽,但需要冷端补偿。最麻烦的是同一个采集模块上可能同时挂几种传感器,这就要求 ADC 的输入结构足够灵活,最好还能自己产生激励电流,免得每路传感器都配一套恒流源或分压电路。
ADS122U04IPWR 恰好就是为这种场景设计的。它有 4 个模拟输入通道,内部提供两个可编程激励电流源 IDAC1 和 IDAC2,电流值可以按 50μA 到 1.5mA 分档配置,做 RTD 时直接省掉外部精密恒流源。24 位分辨率配合内部低温漂基准,理论上能让温度分辨率做到 0.001℃ 级别,当然这是理想值,实际受噪声影响会差一些,但做 0.1℃ 等级的风管温度测量已经非常从容。PIC32MX664F064L 在这条链路里的角色是主控,负责发命令、收数据、换算温度、查表校准,以及后续和上位机通信。
1.2 选型逻辑:为什么是 UART 接口的 ADC
以前用 SPI 接口的 ADC 做多路采集,最头疼的是主控引脚不够用。PIC32MX664F064L 是我手头比较熟的片子,Flash 和 RAM 都够,但项目里还有其他外设要接,SPI 总线被显示器占了,I2C 总线挂着 EEPROM 和 RTC,留给高精度 ADC 的就剩一组 UART。很多人听到 UART 接口的 ADC 第一反应是“新鲜”,其实这正是 ADS122U04IPWR 这类器件的价值所在:它内部把完整的 ADC 变成一个小型从机,主控只要拉两根线就能对话,命令是 ASCII 文本格式,不需要关心时序细节,省下来的 GPIO 可以干更多事。
另外,这类 UART ADC 还有一个隐藏优势,就是把模拟前端和数字主控的耦合降到最低。模拟地和数字地之间的干扰,常常让 ADC 读数跳变,SPI 高速翻转带来的干扰尤其明显;而 UART 波特率即使开到 57600,相对 SPI 动辄几兆的时钟频率还是慢得多,对电源和地平面的冲击小很多。实测下来,同样的前端滤波,用 UART 接口的 ADC 比用同一颗 ADC 的 SPI 版本(如果存在的话)在长线传输场景下读数更稳。当然 ADS122U04 本身没有 SPI 版本,这个类比只是想说明,即便你在选其他 ADC,接口方式对系统稳定性的影响也值得放在前面考虑。
1.3 主控选型:PIC32MX664F064L 到底好在哪
PIC32MX664F064L 不是最新的芯片,但在这个场景里是“够用且有余量”的代表。它跑 80MHz,处理浮点和查表换算温度毫无压力,内置的 UART 模块带 FIFO,接收不定长 ASCII 命令时不会丢字节。选它是还看中了 L 封装——100 脚 TQFP,引脚密度适中,手工焊接和量产回流焊都靠谱。RAM 足够放下多段线性校准表,Flash 也能容纳完整的 Bootloader,后期现场升级固件方便。
有人会问,怎么不用 Cortex-M 系列?纯粹是我个人习惯,PIC32MX 系列的 MCC 图形配置工具用顺手了,UART 初始化、引脚映射、时钟配置几分钟就能搞定。而且 PIC32MX664F064L 内部没有太多花哨的外设负担,不会因为频繁的库更新导致项目迁移成本高。这个项目最终需要的是一块稳定、易调试的主控,而不是追新。如果换成我常用的其他 MCU,思路也完全一样,核心仍然是 ADC 的命令交互和温度换算逻辑,主控只是载体。
2. 硬件设计与信号链搭建:别在第一版就埋雷
2.1 传感器类型与接线方式定夺
ADS122U04IPWR 的 4 个模拟输入是 AIN0-AIN3,可以配置成双差分输入,也可以配成 4 路伪差分输入,取决于寄存器里的通道多路复用器设置。我在这个项目里是 PT1000 和 NTC 混采:冷冻水供回水温度用两路 PT1000,风管温度用两路 NTC。PT1000 的好处是阻值大,导线电阻影响小,哪怕引线有 10Ω 的电阻,温度误差也只在 2.5℃ 左右(相对 PT100 的 0.385Ω/℃ 灵敏度),所以两线制在多数 HVAC 场合勉强可用。但如果像电机绕组那样线缆长、环境干扰大,就必须改成三线制 PT100。
三线制的原理不复杂,关键是接线顺序别接错。把 IDAC1 接到 RTD 的一端,RTD 另一端引出两根线,其中一根回到 ADC 的测量输入端,另一根单独接到基准电阻或直接作为参考线;第三根线从 RTD 的电源端引出,接回 ADC 的另一个输入。这么做以后,两根导线上的压降不再单独影响测量结果,因为电流回路和电压检测回路共享同一路径,导线电阻上的压降被共模抑制掉,只剩 RTD 本身的阻值。ADS122U04IPWR 内部有两个 IDAC,目的就是支持这种三线制接法,让两个激励电流分别流经不同导线,再通过测量端的差分电压抵消导线电阻误差。
2.2 模拟前端:低通滤波与基准电压选择
ADC 前面的模拟滤波对现场噪声的抑制非常关键。我习惯在 AIN 输入端对地各加一个 1nF 电容,再在两线之间并联一个 100nF 电容,形成一阶低通,配合 ADS122U04 内部的数字滤波器,能把多数工频和谐波干扰挡在外面。注意电容选的陶瓷电容要用 C0G 材质,X7R 在高频噪声下容值会变化,影响滤波效果。串联电阻一般不加,因为 RTD 激励电流流经串联电阻会产生附加压降,PGA 的工作范围会被挤占。
基准电压的选择要结合传感器类型。PT1000 在 0℃ 时阻值约 1000Ω,用 500μA 的 IDAC1 激励时产生 0.5V 电压,内部基准 2.048V 完全够用,PGA 甚至不用开,1 倍增益就能给出充足的分辨率。NTC 热敏电阻阻值随温度变化极大,25℃ 时可能 10kΩ,到 85℃ 只有 1kΩ 左右,这种非线性问题靠数字查表解决,模拟端的核心是保证电压落在 ADC 量程内,所以激励电流要选小一点,比如 100μA,防止高温段电压超过基准。总之,先根据传感器类型把 IDAC 档位、PGA 增益、基准这三项配对好,再往下走。
2.3 供电、地平面与去耦:ADS122U04IPWR 的电源细节
ADS122U04IPWR 的模拟供电 AVDD 和数字供电 DVDD 分开引脚,但实际应用里我倾向于把两者接到同一个稳定的 3.3V 上,只是各自通过磁珠或小电阻隔离,再分别对地去耦。别急着把模拟地和数字地一刀切,高速数字信号跨分割地平面反而会引入更大的回流噪声。正确做法是一个完整地平面,ADC 下方和 MCU 之间留点间隔,单点汇接到系统地。
AVDD 入口处放 10μF 钽电容再加 100nF 陶瓷电容,DVDD 同样处理,靠近电源引脚放置。ADS122U04IPWR 还有一个重要的参考电压去耦引脚,实际是内部基准的输出,需要加低 ESR 电容,不要省。我第一版就是漏了这个电容,导致基准纹波偏大,温度读数在 0.1℃ 量级上跳个不停,补上 1μF C0G 电容以后立刻安静了。
2.4 PIC32MX664F064L 与 ADC 的连接
PIC32MX664F064L 和 ADS122U04IPWR 之间的连线非常简单:MCU 的 UART TX 接 ADC 的 RXD,MCU 的 RX 接 ADC 的 TXD,共地。注意这两个芯片之间尽量靠近布局,UART 线不要太长,超过 20cm 建议降到 19200 波特率以下。我实际固件里用的波特率是 57600,板内走线也就 3cm 左右,跑了几个星期没有发现字节错误。如果你需要把这个模块做成远程温湿度采集节点,ADC 和主控之间的连线就更要短,长距离通信交给主控的 RS485 或无线模块,别让模拟信号线长途跋涉。
ADC 的地址线或模式选择引脚如果存在,要根据手册接固定电平,别悬空,否则上电后 ADC 可能进入非预期模式。我在调试时遇到过 ADC 不响应命令的情况,排查了半天,最后发现是某个模式引脚被另一个信号线带偏了,焊下来处理好就正常。这个细节几乎不会出现在示例代码里,但量产时特别容易踩雷。
3. ADS122U04IPWR 寄存器配置与会话实操
3.1 理解它的 UART 指令机制
ADS122U04IPWR 的命令是 ASCII 文本,靠 MCU 发送特定字符来触发。读寄存器的格式通常是R0、R1这类短命令,写寄存器的命令里包含要写入的值,比如写寄存器 0 时发W0后跟两个十六进制字节。命令结束后 ADC 会返回对应数据或应答字符。这种设计最大的好处是调试方便,用串口助手直接敲命令就能观察输出,不用逻辑分析仪一点一点看时序。
不过它也有一个需要注意的地方:ADC 默认上电后处于待机状态,要启动转换需要发送启动命令或者配置成连续转换模式。我的做法是 MCU 上电后先做一步“软复位”,再等待一小段时间让内部基准稳定,然后依次写配置寄存器,最后发命令开启连续转换。顺序不要颠倒,否则可能捕捉到基准未稳时的错误数据。等待时间不能省,我常用的间隔是 10ms 以上,对 HVAC 这种刷新率要求不高的场景完全够用。
3.2 核心寄存器配置对照表
ADS122U04IPWR 的寄存器数量和位定义会随批次有差异,我这里只列本项目中实际用到的配置思路,具体位值必须以数据手册为准。下面是配置 PT1000 + NTC 混合采集时的寄存器规划:
| 配置项 | 我的选择 | 理由 |
|---|---|---|
| 输入多路复用器 | 先轮流切换 AIN0-AIN1 和 AIN2-AIN3 两组伪差分输入 | 四通道分时采集,不用四个 ADC |
| PGA 增益 | 1 或 2,视传感器激励电压而定 | PT1000 在 500μA 激励下电压足够;NTC 用低增益防饱和 |
| IDAC1 | PT1000 路用 500μA | 折中导线压降与自热效应 |
| IDAC2 | NTC 路用 100μA | 高温段避免电压溢出 |
| 数据速率 | 20SPS,开 50Hz 和 60Hz 工频抑制 | 现场电网噪声是主要干扰源 |
| FIR/IIR 滤波 | 选较强滤波档 | HVAC 温度变化慢,换取更平稳读数 |
| 内部基准 | 2.048V | 和 IDAC 电压匹配度高 |
| 内部温度传感器 | 开启 | 用热电偶时做冷端补偿,也能做板温监控 |
这套配置对 HVAC 现场足够了。要追求更快刷新率可以把数据速率提到 200SPS,但噪声会上升,温度读数会在最末位跳动,看你更在意响应速度还是稳定性。工业现场如果有大型变频器,建议保留 20SPS 并把滤波拉满,否则谐波干扰会让数字滤波的崩溃速度超过你想象。
3.3 配置的顺序与容错
写寄存器的时候要有“先写后读回”的习惯。ADS122U04IPWR 支持读寄存器,所以每次写完关键配置,我会立刻读一次,和预期值比对。这能抓出一个很隐蔽的问题:UART 接收引脚接触不良导致命令只发送了一半,ADC 的寄存器写入失败,但 MCU 这边毫不知情。如果没有读回校验,后面拿到任何原始数据都可能是错的配置下的结果,排查起来事倍功半。
我习惯把寄存器配置做成一张查找表,按不同传感器组合提前定义好几套方案,比如“纯 PT1000”“PT1000 + NTC”“全热电偶”。MCU 启动时根据拨码开关或上位机命令选择方案,写对应的寄存器组。这样现场换传感器不用重新编译固件,只要把选择信号改一下就行。
3.4 数据读取与原始电压换算
ADS122U04IPWR 输出的原始数据是二进制补码格式,24 位。要转成电压,公式是:电压 = 原始数据 / 8388608 × 满量程电压。满量程电压取决于内部基准和 PGA 增益,比如基准 2.048V、增益 1 时,满量程对应 ±2.048V,最小分辨率是 2.048V 除以 2 的 23 次方,约 0.244μV。如果乘以每度温度对应的电阻变化率,就能估算温度分辨率。以 PT100 为例,500μA 激励下 1℃ 对应 0.1925mV(0.385Ω/℃ × 500μA),换算成温度步进大约是 0.0013℃,这就是 24 位 ADC 在 RTD 测量上的底气。
原始数据必须在 MCU 端做浮点转换,吃力不讨好但很值得。PIC32MX664F064L 的浮点运算不算快,但每秒钟转 4 个通道毫无压力。转出来的电压值再根据传感器类型进入查表或公式换算环节。
4. PIC32MX664F064L 固件实现:从配置到稳定运行
4.1 用 MCC 初始化 UART 与引脚映射
MPLAB 的 MCC 工具把 PIC32MX664F064L 的初始化变得非常机械化,但有几个配置项我还是会手动确认。首先是 UART 波特率,我选了 57600,8 位数据位,无校验,1 位停止位,关闭流控。其次是把 UART 引脚映射到芯片的具体引脚上,PIC32MX 系列支持外设引脚重映射,这一步千万别省,实打实减少了 PCB 布局时的麻烦。最后是启用接收中断和发送完成中断,接收中断用来收 ADC 返回的 ASCII 应答,发送完成中断可以用来做时序控制。
MCC 生成的代码里,默认把 UART 的接收中断打开但没写处理函数,别只依赖库函数轮询,否则在高波特率下容易丢字节。我是在 ISR 里把收到的字节放入环形缓冲区,主循环再把缓冲区内容交给状态机解析。PIC32MX664F064L 的 UART FIFO 比较浅,中断响应不及时就容易溢出,环形缓冲区的深度至少给到 64 字节。
4.2 不定长 ASCII 命令解析状态机
ADC 返回的数据是变长的 ASCII 字符串,可能有换行符,也可能没有。我写了一个简单的状态机来解析:状态 0 等待命令启动符,状态 1 收集参数直到遇到终止符,状态 2 校验长度和校验数据,状态 3 执行对应处理。中间不会阻塞主循环,因为 UART 字节到达是中断驱动的。这样做的好处是,即使某条命令被外部噪声打断,状态机也可以在超时后自动复位,等下一个有效命令。
这里有个特别容易翻车的点:不要在主循环里用delay_ms等 ADC 返回。PIC32MX664F064L 主循环还要处理按键、显示刷新、通信上报,一旦有一处阻塞,整个系统的时序全乱。我首版代码就是简单轮询 UART 接收函数,结果偶尔会漏掉 ADC 的实际返回数据,后来改成“发送命令后记录期望应答长度,超时未收满就重新发送”的方式,问题才彻底消失。
4.3 温度换算:查表还是公式
PT100/PT1000 的阻值和温度关系可以用 Callendar-Van Dusen 方程描述。0℃ 以上是 RT = R0 × (1 + A×T + B×T²),其中 A=3.9083e-3,B=-5.775e-7。0℃ 以下要加第三项 C×(T-100)×T³。直接用这个方程做浮点运算,PIC32MX664F064L 的 MIPS4K 核心跑起来没有任何问题,算 100 次也就是几毫秒级别。我实际用的是分段做,把 -10℃ 到 150℃ 分成 10℃ 一段,每段存一个线性系数,查表加插值,速度更快,而且校准表也可以就近修正非线性。
NTC 热敏电阻则完全依赖查表了。它的温度特性是非线性指数型的,我拿厂家提供的 B 值表转成温度-阻值表,存进 Flash,运行时按二分查表。为了平滑,还会对相邻两个表点做线性插值。采样率 20SPS 时,温度曲线不会看到台阶,因为插值粒度足够小。
4.4 校准系数与掉电保存
校准是整个方案的灵魂。ADC 本身增益误差很小,但 IDAC 激励电流的绝对精度、基准电压的偏差、外部电阻的初始容差都会叠加进误差。我的做法是在固件里提供一套“零点和增益”校准参数:将传感器短接或接入精密电阻,让系统测量一个已知温度对应的电阻值,计算偏移量,然后把校准系数存进外部 EEPROM。PIC32MX664F064L 上电后从 EEPROM 读参数,如果没有就使用默认值。这样每台设备下线前做一次两点校准,现场就能获得比较一致的读数。
校准命令走同一个 UART 串口,我预留了类似CALZERO、CALSPAN的文本协议,上位机软件发送后,MCU 返回校准状态。注意校准过程中要等 ADC 输出稳定,至少等 5 个数据周期,否则会把瞬态噪声当作零点存进去。另外一个细节:不同温度段的校准系数应该分开存,比如 0℃ 附近用一组,100℃ 附近用一组,因为激励电流随温度漂移的方向可能不同,只做单个点校准不一定能覆盖全量程。
4.5 看门狗与异常复位
工业现场主控跑飞是迟早的事,所以我给 PIC32MX664F064L 开了看门狗。看门狗超时后复位,固件要去判断是“正常上电”还是“异常复位”,从而决定是否重新初始化 ADC 或读取 EEPROM。我建议在 Flash 里放一个复位原因寄存器,MCC 生成的启动代码里能读到,把它做成小状态记录,以后排查现场问题时能看到有没有频繁复位。ADS122U04IPWR 本身没有看门狗,但主控可以通过定期写配置寄存器的读回校验来检查它是否还活着,如果连续读不到预期值,就主动重新初始化 ADC。
5. 校准、抗干扰与实测数据
5.1 两点校准法实操
校准的第一步是准备一个高精度电阻箱或标准电阻。PT1000 在 0℃ 对应 1000Ω,100℃ 对应 1385Ω,我习惯用 1000Ω 和 1500Ω 两个标准电阻模拟 0℃ 和 128.6℃ 左右,尽量减少电阻箱的接触电阻。这要求校准线缆尽量短,否则线阻会直接变成误差源。校准步骤如下:先发命令切换通道到校准通道,然后写 ADC 配置,等输出稳定,保存零点偏移;再切换到跨度通道,保存增益误差修正值。二次修正后,ADC 在全量程范围内读数误差能压到 0.1℃ 以内。
5.2 工频干扰抑制实测对比
现场最常见的干扰是 50Hz 工频及其谐波。我在数据速率 20SPS 且滤波器设置在较强档位时,实测 ADC 输出噪声峰峰值能控制在 10 个 LSB 以内;如果把数据速率拉到 1000SPS,同样条件下噪声会飙到 50 个 LSB 以上。对于 HVAC 应用,宁可刷新率低一点也要保证温度读数平滑,因为风管和冷水回水的温度惯性很大,1 秒刷新一次完全足够。如果是电机保护,温度报警需要快速响应,可以平时用低速率监控,检测到突变后再切换高速率确认。
5.3 现场 24 小时实测参考数据
我在板卡上接了 2 路 PT1000(模拟冷冻水回水温度)和 2 路 NTC(模拟风管温度),连续运行 24 小时,室内环境 25℃ 条件下,记录的温度数据如下:
| 通道 | 传感器类型 | 平均温度(℃) | 波动范围(℃) |
|---|---|---|---|
| 0 | PT1000 | 24.93 | ±0.03 |
| 1 | PT1000 | 25.01 | ±0.04 |
| 2 | NTC 10k | 24.86 | ±0.05 |
| 3 | NTC 10k | 25.02 | ±0.06 |
这个波动范围包含了 ADC 量化噪声、基准漂移和 PCB 上微小温差的影响,实际表现已经比常见的 16 位方案好一个数量级。当然,NTC 通道的波动稍大,主要是激励电流小、信号幅度低导致的信噪比偏低,但风机盘管这类应用并不在乎 ±0.05℃ 的波动,完全满足指标。
6. 常见问题与排查心得实录
6.1 UART 命令无响应或应答乱码
先检查 MCU 的 TX 是否接到 ADC 的 RXD,共地有没有问题。然后波特率是不是完全一致,我遇到过两个芯片晶振偏差导致双方握手失败的情况,最后统一改用内部振荡器校准后才好。如果应答乱码但波形正常,多半是命令里带了多余换行符,或者波特率配置位错误。用串口助手手动敲命令时,注意不要打开“自动发送新行”,ADS122U04IPWR 对命令结束符的要求以手册为准,多一个字符就会当作非法命令忽略。
6.2 读数跳变或长时间漂移
先看电源电压是否稳定,ADC 的基准电压对电源纹波敏感。再用示波器看 IDAC 引脚的波形,如果激励电流在切换通道瞬间有大的毛刺,可能是去耦电容不足。然后确认滤波器设置,20SPS 高档滤波下如果还跳,基本可以判定是模拟前端布局问题,而不是数字链路问题。长时间漂移多数和基准源有关,检查基准引脚电容容量和材质,我换成 C0G 后漂移明显减小。
6.3 三线制接错导致的温差
三线制 PT100 接错时,ADC 也能出数值,但读数会随导线长度显著变化,且零点偏移很大。排查方法是把其中一根导线短接,模拟 0Ω 传感器电阻,如果读数不是 0℃ 附近,说明通道配置或 IDAC 路径有误。另外两个 IDAC 的电流值配置必须相等,如果手滑把 IDAC1 设成 500μA、IDAC2 设成 250μA,导线电阻误差就无法完全抵消。
6.4 热电偶冷端补偿不准
虽然项目里热电偶用得少,但我也测试过。ADS122U04IPWR 内部温度传感器读出的板温,和实际冷端温度可能有 1-2℃ 的偏差,因为芯片温度不等于接线端子温度。要求高的时候要把冷端温度传感器贴到接线端子上,用 ADC 的 GPIO 口读取外部传感器的阻值,再和内部读数结合校准。
结尾:一点实际操作的体会
这套 ADS122U04IPWR 加 PIC32MX664F064L 的方案,我前后改了三版硬件才稳定下来。第一版急着验证功能,滤波器和去耦都没做足,结果读数勉强能用但绝不漂亮;第二版把基准去耦和输入滤波补齐,稳定性立刻上来;第三版则完全定稿,加入了校准表和看门狗保护,才敢批量交到现场。如果让我总结一个最值得提的经验,那就是别迷信“高分辨率 ADC 就能出高精度温度”,模拟前端布局、滤波、校准、固件容错每一个环节都在拖后腿。按这篇的顺序走一遍,至少能让你少踩我踩过的那些坑。后续如果想加入更多通道,ADS122U04IPWR 本身是 4 通道,通过 I2C 扩展几个前端芯片也是顺理成章的事,希望这个组合能给你的项目带来一些灵感。