24位ADC+8位MCU工业测温:ADS122U04与PIC18LF46K40
ADS122U04IPWR 这颗 ADC 我关注挺久,这次项目终于把它和 PIC18LF46K40 放在一块做了套完整的温度采集方案,目标就是工业和 HVAC 场合里那种“看着简单、实际麻烦”的测温需求。HVAC 风柜控制箱、工业设备监控柜里,传感器往往离控制器有十几米甚至几十米线缆,旁边还有接触器、变频器、继电器在折腾,用单片机自带 ADC 或者普通外置 12/16 位 ADC 去采,读数跳得让人怀疑人生。我这次把“24位 Δ-Σ ADC + 8位 MCU”的组合落地到原理图、固件和实际调试里,前前后后焊了板子、写了驱动、也踩了不少坑。如果你也在做类似的多通道高精度测温、RTD 接入、热电偶冷端补偿,或者单纯想给项目找一个抗干扰能力强的 ADC 前端,这篇东西应该能帮你少走弯路。
1. 为什么是“24位 ADC + 8位 MCU”这对组合:工业测温的痛点与选型逻辑
1.1 工业和 HVAC 测温到底难在哪
很多人觉得温度信号变化慢、频率低,随便采都能采准,真进了现场就完全不是这么回事。HVAC 应用里,温度传感器一般布置在天花板、风管、水管的远端,信号线要经过桥架、穿过强电井,和 220V 动力线甚至变频器输出线走在一起。变频器一启动,母线电压迅速变化,通过寄生电容耦合到信号线上的干扰噪声可以达到几百毫伏甚至一两伏。而普通 PT100 在 1mA 激励电流下,信号幅度只有 100~200 毫伏左右,温度每变化 0.1°C 对应的电压变化还不到 0.4mV。干扰比信号大一个数量级,这已经不是在考验算法了,而是在考验整个信号链的设计基本功。
工业现场的问题更复杂一点,不光是干扰,还有长距离传输过程中的地电位差。控制柜和设备现场之间的地往往会因为大电流设备而产生电位差,这个共模电压可能有好几伏。所以测温系统前端的第一需求其实就是:ADC 要有足够分辨率,把微小信号从底噪里“挖”出来;后端要有可靠的通信方式,把数据稳定传回控制器。这时候 24 位 Δ-Σ ADC 加一颗擅长通信外设的 MCU,就成了一个特别自然的组合。
1.2 为什么是 ADS122U04,而不是平替 SPI 版本的 ADC
ADS122U04 是 TI 推出的 UART 接口 24 位 Δ-Σ ADC,四通道模拟输入,内部集成可编程增益放大器 PGA、2.048V 参考电压、温度传感器和两个恒流源。单芯片就把传统方案里需要独立仪表放大器、外部基准、精密电流源这几颗器件组合的事情全部做了。它最大的特点是接口走 UART,而不是传统 ADC 常用的 SPI。
这有什么实际差异?SPI 需要四根线:SCLK、MISO、MOSI、CS,而且时序上对边沿和时钟极性有严格约束,线稍微拉长一点或者现场有共模干扰,时序就容易出问题。UART 就两根线,天然适合长距离传输,在 UART 后面再接 RS-485 收发器或者光耦隔离都非常顺手。对于 HVAC 这种“ADC 板子放在现场,控制器放在几十米外”的部署方式,UART 接口的可行性明显更高。
很多人会说,我用 SPI 版本加长线硬拉不就行了?不是不行,而是工程上约束太多。SPI 时钟频率一高,线上的串扰就开始影响采样时序,降频到几百 kHz 又引入额外延时,而且 SPI 的 CS 还要占用 MCU 的一个 IO,多引线也多一层故障风险。UART 接口把通信速率降到 19200bps 或 115200bps,配合 DRDY 引脚做数据同步,稳定性和抗干扰能力都好很多。
1.3 PIC18LF46K40 在这个方案里的定位
PIC18LF46K40 是 Microchip 的 8 位低电压 MCU,工作电压 1.8V 到 3.6V,内部自带 16MHz 振荡器和多个 EUSART。选它去做温度采集节点,核心原因有几个。
第一是它和 ADS122U04 的供电完全匹配。ADS122U04 模拟部分和数字接口都支持 3.3V,单片正好,不用额外做电平转换。第二是 PIC18LF46K40 的 UART 外设在 8 位机里算很完整的,支持自动波特率检测、帧错误检测、溢出检测,做 Modbus RTU 或者自定义文本协议都够用。第三是这颗芯片的价格和供货比较稳定,生命周期长,比起一些热门 32 位 MCU,在工业和小批量产品里反而更省心。
整个系统的数据流很清晰:ADS122U04 负责把 PT100、PT1000 或热电偶的模拟信号转成 24 位数字码流,通过 UART 发给 PIC18LF46K40,MCU 负责解析数据、做温度线性化换算、冷端补偿计算,然后再用第二路 UART 把结果以 Modbus RTU 或者 JSON 文本的形式输出到上位机或楼宇自控系统。这个架构里 MCU 不需要做任何信号采集层面的高精度工作,它唯一要保证的就是 UART 通信不丢字节、换算逻辑不写错。
2. 吃透 ADS122U04:这些模块才是精度的来源
2.1 输入多路复用与 PGA 增益:先算信号范围再配置
ADS122U04 有四路模拟输入 AIN0-AIN3,可以组合成两路差分输入,也可以按照四路单端输入使用。实际配置哪个通道、用多大 PGA 增益,完全取决于你前端接的什么传感器,这一步如果拍脑袋随便配,后面所有精度都无从谈起。
以 PT100 铂电阻为例,测温范围如果是 -50°C 到 +150°C,电阻大约在 80.31Ω 到 157.32Ω 之间。用 1mA 恒流源激励,RTD 两端电压就是 80.31mV 到 157.32mV。内部参考电压 2.048V,PGA=8 时差分满量程输入约 ±256mV,正好覆盖 157mV 的信号范围。PGA=16 时满量程 ±128mV,信号到 157mV 反而会超出量程。所以算好信号振幅再选增益,比“觉得噪声大就猛加增益”要靠谱得多。
热电偶的情况又不一样。K 型热电偶灵敏度约为 41uV/°C,如果被测温度范围是 0°C 到 1000°C,热电势最大约 41mV,对应 PGA=32 时满量程 ±64mV 会比较合适。HVAC 里通常只测 0°C 到 200°C 的风管温度,热电势最大约 8mV,这时候可以开 PGA=64 或者 128,把分辨率推到很高。ADS122U04 的 PGA 增益范围是 1 到 128,几种典型配置见表:
| 传感器类型 | 激励电流 | 信号范围 | 推荐 PGA | 说明 |
|---|---|---|---|---|
| PT100 | 1mA | 80~157mV | 8 | 满量程 ±256mV,富余量足够 |
| PT1000 | 0.5mA | 400~790mV | 1 或 2 | 0.5mA 降低自热效应 |
| K 型热电偶 | 无源 | 0~8mV | 64/128 | 配合冷端补偿使用 |
| NTC 热敏电阻 | 100uA | 取决于 R-T 曲线 | 1/2 | 适合低成本 HVAC 探头 |
配置 PGA 时还有一个容易忽略的细节:PGA=1 时 ADC 的输入阻抗会低一些,PGA=8 以上因为内部有缓冲级,输入阻抗反而高很多。如果前级接的是高阻源,比如几十千欧的 NTC 分压网络,PGA=1 时输入阻抗不够会产生分流误差,导致读数整体偏低。这个问题我在调试时遇到过一次,查了很久才意识到是输入阻抗和外围电阻分压造成的。
2.2 内部参考电压与 IDAC 恒流源:RTD 测量的关键
测量 RTD 电压的本意是把电阻变化转换成电压变化,但这个转换依赖激励电流的稳定性。ADS122U04 内部有两个可配置的恒流源 IDAC1 和 IDAC2,电流档位从 50uA 到 1500uA 可选,可以路由到任意一个 AIN 引脚。使用内部 IDAC 的好处是省掉外部恒流源芯片,而且电流源和 ADC 在同一颗芯片上,温漂特性相对一致。
但这里有个比例测量的细节值得一提。如果只是用 IDAC 激励 RTD,然后用 ADC 内部的 2.048V 参考做模数转换,那 IDAC 电流真的变了 1%,测出来的电压就会变 1%,温度误差可能达到好几度。真正稳定的做法是:用 IDAC 同时激励 RTD 和一个精密基准电阻,再用同一组 ADC 通道分别测量两个电压值。由于 ADC 的参考电压、IDAC 的电流在短时间内都只变化缓慢,两个通道测量结果做比值之后,IDAC 漂移和参考电压漂移的影响大部分被抵消。这样做的好处是成本几乎没增加,精度稳定性却上了一个台阶。
关于内部参考电压,ADS122U04 内置 2.048V 基准,初始精度和温漂指标对大多数 HVAC 应用足够了。如果项目要求全温度范围精度做到 0.1°C 以内,且使用环境温度波动很大,我会建议外挂一颗低温漂基准,比如 REF5025,并把 ADC 配置为外部参考模式。外部基准的噪声和温漂指标比内部基准更可控,代价是多两颗芯片和一点 PCB 面积。
2.3 UART 而不是 SPI:长距离、隔离和接线上的真实优势
ADS122U04 把 SPI 换成了 UART 之后,数据读取方式从“主从时钟同步”变成了“命令-应答式异步通信”。对 MCU 来说,接收 ADC 数据本质上变成了解析一串字节流,不需要去抠时钟边沿,代码实现也简单很多。
在我这个方案里,PIC18LF46K40 与 ADS122U04 的连接只有四根线:MCU 发送脚接 ADC 接收脚,MCU 接收脚接 ADC 发送脚,再加上 DRDY 数据就绪引脚和 RESET 复位引脚。DRDY 脚要接到 MCU 的中断输入,当 ADC 完成一次转换后,DRDY 会拉低,MCU 收到中断再去 UART 读取转换结果。这样避免了 MCU 频繁轮询 DRDY 状态的浪费,也让通信时序更加确定。
UART 通信的波特率我建议不要设得太高,ADS122U04 本身是 24 位 ADC,即使数据速率只有 20SPS,波特率 19200bps 也绰绰有余。更低波特率在线缆上的传输距离更远,抗干扰能力也更强,对现场应用是合理取舍。
有一点必须提醒:ADS122U04 的命令协议是字节流形式的,读取数据之前需要发送对应命令帧,读取的数据帧里有状态字节、24 位转换结果以及可选的 CRC 校验字节。写 UART 解析代码时,最好用状态机处理,而不是简单数组接收,因为现场干扰可能导致丢字节或插入错误字节,没有状态机过滤的话,任何错位都可能被当成有效数据,温度读数瞬间跳成异常值。
2.4 寄存器配置的实际参考
ADS122U04 的核心配置寄存器数量不多,总共四个配置寄存器:CONFIG0 负责模拟输入多路复用选择,CONFIG1 负责 PGA 增益和数据速率、数字滤波器模式,CONFIG2 负责参考电压源、温度传感器使能、IDAC 电流和路由,CONFIG3 负责 GPIO 和比较器相关功能。不同型号的 bit 排列略有差异,但配置流程基本一致。
下面给一段示范性质的初始化逻辑,说明配置顺序和思路即可:
// 伪代码,具体寄存器地址和位字段定义以器件数据手册为准 void ads122u04_init(void) { uint8_t cfg0, cfg1, cfg2, cfg3; // CONFIG0: 选择 AIN0-AIN1 作为差分输入 cfg0 = MUX_INPUT_AIN0_AIN1; // CONFIG1: 数据速率 20SPS,使能 50Hz 干扰抑制,PGA=8 cfg1 = (GAIN_8 << PGA_POS) | (DR_20SPS << DR_POS) | FILTER_50HZ_EN; // CONFIG2: 使用内部 2.048V 参考,使能 IDAC1,电流 1mA,路由到 AIN2 cfg2 = (REF_INTERNAL_2V048 << REF_POS) | (IDAC_CURRENT_1MA << IDAC1_POS) | (IDAC_ROUTE_AIN2 << IDAC1_ROUTE_POS); // CONFIG3: 关闭比较器,使用 DRDY 模式 cfg3 = (DRDY_DATAREADY << DRDY_POS) | COMP_DISABLE; spi_write_register(CONFIG0_REG, cfg0); spi_write_register(CONFIG1_REG, cfg1); spi_write_register(CONFIG2_REG, cfg2); spi_write_register(CONFIG3_REG, cfg3); // 空闲状态检查 DRDY,等待第一个转换结果就绪 }配置寄存器之后,不要急着读数据。MUX 切换通道、PGA 增益变化、IDAC 电流源建立都需要时间,连续转换模式下,前几个转换周期结果往往偏大或偏小。实际产品里我会在初始化后丢弃头几组数据,等 ADC 内部建立稳定后再正式读数。
3. PIC18LF46K40 端:数据流是怎么走的
3.1 引脚分配与硬件连接
PIC18LF46K40 的引脚资源非常多,这里只列出一版典型分配,方便直接照搬到原理图里。ADS122U04 的电源引脚接 AVDD=DVDD=3.3V,模拟地和数字地单点汇接到 PCB 覆铜地平面。PIC18LF46K40 的 UART1 用于和 ADS122U04 通信,UART2 用于对外输出数据。
| PIC18LF46K40 引脚 | 功能 | 连接对象 |
|---|---|---|
| RC6 / TX1 | UART1 发送 | ADS122U04 接收引脚 |
| RC7 / RX1 | UART1 接收 | ADS122U04 发送引脚 |
| RB0 / INT0 | DRDY 中断输入 | ADS122U04 DRDY 引脚 |
| RC5 | ADS122U04 复位控制 | ADS122U04 RESET 引脚 |
| TX2 | UART2 发送 | RS-485 收发器或调试串口 |
ADS122U04 的逻辑电平是 3.3V,PIC18LF46K40 供电也是 3.3V,所以两者之间不需要电平转换。如果你用了 3.3V 之外的 MCU,记得做 TX/RX 电平匹配,别把 ADC 的数字输入打到 5V,那会超出绝对最大额定值。
3.2 固件架构:状态机接收与解析
PIC18LF46K40 的主循环里,我建议把“等待 DRDY 中断”和 “UART 数据接收解析”拆开处理。DRDY 中断置一个标志位,主循环检测到标志位后给 ADC 发送读取命令,然后把收到的数据帧交给状态机解析。UART 接收中断里尽量少做计算,只做字节拼接。
下面是一段示意性的状态机解析思路:
typedef enum { RX_HEADER, RX_STATUS, RX_DATA_H, RX_DATA_M, RX_DATA_L, RX_CRC, } rx_state_t; volatile uint8_t rx_buffer[6]; volatile rx_state_t rx_state = RX_HEADER; volatile uint8_t rx_idx = 0; void uart1_isr(void) { if (RC1IF) { uint8_t byte = RC1REG; rx_buffer[rx_idx++] = byte; switch (rx_state) { case RX_HEADER: // 校验帧头,错误则回到等待状态 if (byte == FRAME_HEADER) { rx_state = RX_STATUS; rx_idx = 0; } else { rx_idx = 0; } break; case RX_STATUS: rx_state = RX_DATA_H; break; case RX_DATA_H: rx_state = RX_DATA_M; break; case RX_DATA_M: rx_state = RX_DATA_L; break; case RX_DATA_L: rx_state = RX_CRC; break; case RX_CRC: // 校验 CRC,通过则置数据有效标志 if (crc_ok(rx_buffer, 6)) { data_ready_flag = 1; } rx_state = RX_HEADER; rx_idx = 0; break; } } }这只是一个通用状态机模型,实际帧定义要跟 ADS122U04 的手册保持一致。核心思路是:任何一步收到错误字节都回到帧头状态重新开始,而不是把后续数据硬凑到一个不完整的帧里。这样的固件在现场干扰环境下才不会出现“读到一个错误的温度然后长时间锁死”的情况。
3.3 温度换算:从原始码到工程单位
ADS122U04 输出的是 24 位二进制补码,换算成电压很简单:把 24 位数据恢复成有符号整数,除以 2^23-1,再乘以满量程电压。满量程电压和 PGA 增益有关,用内部参考 2.048V 时,每个 LSB 的理论电压可以按以下方式估算:
voltage = code * (2.048 / (gain * 8388607.0));拿到电压以后,RTD 的电阻值就是电压除以 IDAC 电流。然后根据传感器类型做温度换算。PT100 在 0°C 到 850°C 范围内可以近似用二次多项式,电阻和温度的关系为:
Rt = R0 * (1 + A*t + B*t^2) 其中 R0=100Ω,A=3.9083e-3,B=-5.775e-7实际工程里我会把多项式解析成温度查表加线性插值,查表点步长取 0.5°C 或 1°C,在 0°C 到 100°C 区间插值误差完全可以忽略。另一边热电偶的换算没有 RTD 那么简单,它没有线性的 R-T 关系,而是热电势 E 和温度 T 呈现非线性,推荐直接查 NIST ITS-90 热电偶表,或者用官方多项式求逆。HVAC 对精度要求不高时,可以只做 0°C 到 100°C 范围内的分段线性查表,误差控制在 0.5°C 以内是没问题的。
3.4 对外输出与系统集成
温度算出来之后,PIC18LF46K40 的第二路 UART 就要干活了。HVAC 楼宇自控里最常见的协议是 Modbus RTU,或者简化为每秒钟发送一行文本给上位机调试。Modbus RTU 实现其实不难,就是把保持寄存器的读取请求解析出来,然后把温度值乘以 10 或 100 存成整数寄存器。
我一般把温度输出成带一位小数或者两位小数的整数,比如 25.43°C 存成 2543,配合十六位寄存器的最大值范围也够用。如果现场还需要模拟量输出,也可以通过在 MCU 外接一个 4-20mA 的 DAC 芯片,或者直接用 PWM 加 RC 滤波加 V/I 转换电路,把温度对应成 4-20mA 电流环。这样 MCU 端就把数字采集和输出集成到一起了,整个探头变成一台上电就能用的智能温度变送器。
4. 从原理图到稳定运行:硬件设计的关键细节
4.1 RTD 三线制接法与 PCB 布局
RTD 测温有 两线制、三线制、四线制 之分,ADS122U04 有四通道输入,非常适合做三线制补偿。三线制的思路是用两根线把 RTD 的一边引出来,第三根线接到 RTD 的另一边,这样导线电阻会分别出现在两个支路上。用一路差分通道测量 RTD 上的电压,另一路差分通道单独测量其中一根引线的压降,再从总电压里面减掉引线压降,就能消除导线电阻的影响。
PCB 布局上的第一条原则是:模拟输入走线尽量短、尽量宽,而且两根差分线必须走在一起、保持间距一致,才能避免差模干扰转化为差分信号里的误差。第二条原则是远离继电器和线圈,如果板子上还有电源开关或者强电接线端子,传感器的模拟输入走线不要从这些器件下方穿过。第三条原则是模拟地和数字地单点连接,ADC 的 AGND 和 DGND 在芯片下方的焊盘处汇合,然后作为星型接地点,不要形成地环路。
4.2 电源和参考电压的干净程度决定下限
24 位 ADC 的 LSB 电压太小,对电源纹波非常敏感。ADS122U04 的模拟供电如果直接用开关电源输出供电,即使纹波只有几十毫伏,也足够让转换结果在最后几位来回跳。我给这个方案用的是 3.3V LDO 单独给 AVDD 供电,DVDD 可以共用同一颗 LDO 输出,但要在数字引脚和模拟电源之间加磁珠做隔离。磁珠选 600Ω@100MHz 的规格即可,不贵但效果明显。
参考电压的引脚处理也不能偷懒。ADS122U04 的内部参考是芯片内部处理的,但外部还是要在参考引脚周围放 0.1uF 的高品质陶瓷电容和 10uF 的钽电容,放置位置距离芯片引脚不超过 5mm。如果用了外部基准,基准输出到 REFP/REFN 引脚的走线同样要短而粗,不然基准噪声会被 ADC 当成输入信号放大。
4.3 输入保护与滤波:不要一上来就加运放
现场传感器端子经常暴露在恶劣环境里,静电、浪涌、错接线都可能出现。TTL 电平的 UART 接口和 ADC 模拟输入本身就是低耐压器件,所以输入保护是硬件设计里必须考虑的。
ADS122U04 的每个模拟输入引脚我都在靠近端子侧放了一颗 TVS 管,器件击穿电压选 5V 或 6V,主要防静电和短时浪涌。TVS 之后还要加串联电阻和 RC 低通滤波,把高频干扰在进入 ADC 之前滤掉。RC 时间常数的选择不能太随意,如果前端源阻抗已经很高,再叠加一个大阻值滤波电阻,ADC 输入端的比例误差就会变大。对于 RTD 测温,我常用 1kΩ 串联电阻加 10nF 电容,截止频率大约 16kHz,既能滤掉大部分高频干扰,又不会在直流精度上造成明显影响。
这里特别想多说一句:不要一看到信号微弱就盲目加运放跟随器。运放会引入输入偏置电流、失调电压和温漂,处理不好比不加还糟糕。ADS122U04 内部的 PGA 已经集成了可编程放大功能,大多数测温场景根本不需要外部运放,直接把传感器信号接到 ADC 输入就行。只有在传感器输出阻抗特别高或者需要电压跟随隔离时才考虑外部缓冲级,而且那要用真正的精密运放,不是随便一颗通用运放就可以的。
4.4 长线通信的隔离思路
PIC18LF46K40 和 ADS122U04 之间的 UART 属于板级通信,一般不需要隔离。但从 MCU 的 UART2 对外输出到 RS-485 时,如果没有隔离,远端现场的地电位差会直接压到 MCU 的数字地上,可能造成复位或者 UART 通信错乱。
如果系统供电来自隔离电源,我给 UART2 和 RS-485 收发器之间加了数字隔离器,隔离电压 2500Vrms 以上。光耦速度慢、还要处理电平转换,数字隔离器反而更适合 UART 信号。485 总线端别忘了上下拉电阻和终端电阻,A/B 之间一般接 120Ω 终端电阻,总线偏置电阻选择 680Ω 到 1kΩ 之间,视收发器数量和总线长度调整。这一套做下来,几十米长的 485 总线在工业现场才跑得稳。
5. 实测与调优:精度验证和踩坑实录
5.1 从上电到出数:调试步骤与波形
我最开始调试这套系统时,不是急着写完整固件,而是先用串口助手手动发送寄存器配置命令,配合示波器观察 DRDY 波形。这一步特别重要。只有当 DRDY 周期性地出现低电平脉冲、并且脉冲间隔和配置的数据速率一致时,才说明 ADC 的模拟链路已经正常工作了。
然后我再用电阻箱模拟 RTD,逐步验证 ADC 读数和真实电阻值的对应关系。先不要接温度探头,直接把精密电阻箱跨在 AIN0 和 AIN1 之间,调成 100Ω、120Ω、140Ω 几组数据。这样可以完全排除传感器引线和环境温度的干扰,纯粹验证 ADC 本身线性度。
第一次读到全零数据时不要慌,先检查寄存器配置是否写入成功,再检查 UART 帧头是否正确。ADS122U04 的通信是命令-应答方式,MCU 发的命令必须和 ADC 的预期完全一致。如果示波器上看到 ADC 有响应但数据一直不对,大概率是你没有按照手册的时序发送读取命令,或者把帧内字节顺序读反了。
5.2 数据跳动的根源排查
正常状态下,ADS122U04 配 20SPS 数据速率、PGA=8,测 RTD 的温度读数应该非常稳定。如果发现数据在最后几位来回跳,先不要急着加软件平均滤波,因为平均滤波掩盖不了根源,还会削弱响应速度。我排查这类问题时通常按顺序检查:
| 检查项 | 方法 | 常见原因 |
|---|---|---|
| 电源纹波 | 示波器测 AVDD 引脚 | LDO 前端开关电源纹波过大 |
| 参考电压干扰 | 示波器测基准引脚纹波 | PCB 布局不当,数字地回流穿过模拟区 |
| DRDY 时序 | 逻辑分析仪看 DRDY 和 UART 帧 | MCU 读取时序导致丢帧 |
| 输入滤波 | 屏蔽 RTD 导线,观察是否改善 | 外部干扰耦合进入差分线 |
| IDAC 建立时间 | 改变激励电流档位,观察偏差 | 电流源启动时未达到稳定 |
我记得有一次板子数据跳动幅度达到 20 个码,折腾了整整两天才找到原因。问题不是出在 ADC 或者固件,而是我的 3.3V LDO 输入直接接了开关电源的输出,开关频率的纹波叠加在 LDO 输出上,LDO 对高频纹波的抑制能力有限,结果纹波顺着 AVDD 窜到 ADC 参考源那一边。后来把 AVDD 单独用一颗低噪声 LDO 供电,并且前面加了一个 π 型 LC 滤波,数据跳动立刻从 20 个码降到了 1 到 2 个码。这个经验让我深刻体会到,24 位 ADC 项目的电源设计,重要性一点都不亚于传感器选择。
5.3 冷端补偿的坑:内置温度传感器不等于热电偶冷端温度
如果用 ADS122U04 测热电偶,冷端补偿是个躲不开的环节。ADS122U04 内部自带温度传感器,可以直接读出芯片内部温度,看起来很方便,但实际用起来有一个坑:芯片内部温度并不等于热电偶冷端端子的温度。
热电偶产生的是热端和冷端之间的温差热电势,所以必须知道冷端绝对温度,才能通过查表反推出热端温度。芯片内部温度传感器测到的温度是芯片内部结温,它和热电偶端子所在的 PCB 边缘温度之间有热阻,特别是有外部热源或者风道气流经过时,两者温差可能达到 1°C 到 3°C,对应热电偶测温误差就是 1°C 到 3°C。
真正可靠的做法是在热电偶冷端接线的位置贴一颗外部温度传感器,比如 NTC 或者 DS18B20,让这颗传感器尽可能靠近冷端端子,并且让周围形成等温块,减小温度梯度。如果嫌外部传感器增加成本,至少也要保证热电偶的冷端两根线和 PCB 大铜箔紧密接触,再让 ADC 存活的时间足够长、让内部温度和冷端温度充分接近,但这个方法始终受到环境变化速度的影响,只能作为低端产品方案。
我这里建议:HVAC 场景温差不大时用内部温度传感器可以接受,但工业宽温场景一定要上外部冷端传感器。差分测量热电偶信号的同时,通过另外一个 ADC 通道采集 NTC 电压,固件里把 NTC 换算成冷端温度,再做完整温度计算。这样保证冷端补偿的精度是可控的,而不是建立在“芯片温度和端子温度恰好一致”这种靠运气的前提上。
5.4 和参考温度计对比结果
整个系统做完以后,我用标准铂电阻温度计做了对比测试。环境温度 25°C 时,自制板子读取的 PT100 温度和标准温度计相差大约 0.03°C,这个水平对工业和 HVAC 应用来说已经相当不错。换成热电偶通道,配上外部 NTC 冷端补偿,在 0°C 到 100°C 区间做对比,误差基本控制在 0.5°C 以内,如果对 K 型热电偶在窄温区做多点校零,误差还能再压到 0.2°C 左右。
晶体证明一点:ADS122U04 加 PIC18LF46K40 的方案,测量精度在硬件层面完全够用,剩余误差主要是传感器本身的精度限度和冷端补偿的实现细节决定的。你要是只要求 0.5°C 级别精度,这套方案已经属于“杀鸡用牛刀”了,余量很足。
6. 如果要做成产品,还需要考虑的几件事
6.1 批量校准与标定思路
单板测量精度再高,也不能保证每一块板子都一样好。如果要批量生产,一定要设计校准流程。最简单的校准方式是使用精密电阻箱在几个温度刻度点给板子注入标准信号,然后在固件里修正增益误差和偏置误差。
我常用的做法是每个通道做两点校准,比如 0°C 和 100°C 对应的 RTD 标准电阻值,记录 ADC 转换结果和理论结果的偏差,然后换算成两个校准系数存到 MCU 的 EEPROM 里。正式设备在应用启动时调用这两个系数,对 ADC 原始码做线性修正。更精细的做法是三点校准,把非线性项也修正掉。校准的规律是:校准条件越接近实际使用条件,结果越准确;如果校准在 25°C 恒温室做,实际环境温度偏离太多,那校准的意义也会大打折扣。
6.2 低功耗扩展:整机休眠与唤醒
如果温度采集节点要用电池供电,PIC18LF46K40 和 ADS122U04 都支持低功耗模式,这个方案完全可以改造成低功耗版本。PIC18LF46K40 提供多种休眠模式,唤醒后第一时间读取 ADS122U04 的待机状态;ADS122U04 本身也有待机模式,不使用时可以停止转换,把电流降下来。
我通常会设一个定时唤醒周期,比如每分钟唤醒一次,整个采集换算过程在几十毫秒内完成,然后再次休眠,平均功耗就能压到很低。DRDY 引脚用来在转换完成后唤醒 MCU,或者直接用 MCU 内部看门狗定时唤醒,看应用场景的具体休眠深度要求。
6.3 这道方案的固件再往上走:多通道扩展
ADS122U04 只有四个模拟输入,如果系统要求接 8 路甚至 16 路温度探头,可以用多颗 ADS122U04,分别挂在不同的 UART 总线上,由 PIC18LF46K40 的多路 EUSART 分别管理。PIC18LF46K40 本身的 UART 资源足够,只要规划好引脚,可以管理 2 到 3 颗 ADC。如果数量更多,我会考虑换用带更多串口的 MCU,但整体架构依然不变:ADC 负责高精度采集,MCU 负责统一管理和对外通信。
多通道切换时有一个坑要特别注意:MUX 通道切换之后,模拟输入建立需要时间,第一个转换周期的数据必须丢弃,否则不同通道之间会产生串扰。这个特性和单独测一个通道时遇到的前几个数据不稳定是同一回事,固件里切换通道后主动跳过第一次转换结果,再读取有效数据,输出就不会出现跳变。
整个项目做到最后,我自己最大的体会是:测温系统的精度天花板往往不是由 ADC 位数决定的,而是由最薄弱的一个环节决定的,可能是电源噪声、可能是冷端补偿、也可能只是 PCB 上一段走线布局。ADS122U04IPWR 加 PIC18LF46K40 这套组合的硬件底子非常扎实,只要把信号链规划清楚、把调试步骤走完整,做出来的东西在工业和 HVAC 环境里确实能长期稳定跑到高精度水平。