ADS122U04IPWR与PIC18F85J50:UART接口24位ADC的HVAC温度采集方案

发布时间:2026/11/5 5:04:46
ADS122U04IPWR与PIC18F85J50:UART接口24位ADC的HVAC温度采集方案

做 HVAC 温度采集这一行时间久了,你会发现大部分控制板的温漂问题根本不是算法问题,而是信号链选型没到位置上。前阵子在一个风柜控制项目里,我用 TI 的 ADS122U04IPWR 搭配 Microchip 的 PIC18F85J50,做了一块四路温度采集模块,精度做到了接近 0.1°C 级别,而通信接线比以往 SPI 方案简单得多。这个组合让我想认真写一篇工程笔记:ADS122U04IPWR 本质上是一颗四通道 24 位 ADC,但对外接口是通用 UART,特别适合 PIC18F85J50 这类 8 位主控在工业和 HVAC 场景下做多点温度采样。如果你正在纠结“MCU 自带 ADC 够不够用”“SPI 温度芯片怎么总是受干扰”这类问题,这篇文章会把方案论证、硬件连法、软件实现、误差校准和现场排查一次性讲透。

1. 方案拆解:为什么是 ADS122U04IPWR 与 PIC18F85J50

1.1 温度测量链路的核心矛盾

温度传感器输出的信号天然很小。K 型热电偶在室温附近的灵敏度大约 41µV/°C,哪怕温度变了 1°C,电压变化也只有几十微伏。NTC 热敏电阻和 PT100 铂电阻虽然信号稍大,但要把 0.1°C 的温差分辨出来,需要的信号检测能力同样在微伏级别。如果你直接用单片机的 10 位或 12 位 ADC,输入范围又是 0 到 3.3V,那么一个 LSB 对应的电压可能是毫伏甚至是十几毫伏,根本无办法稳定测出 0.1°C 的变化。所以工业测温和 HVAC 高精度控制场景里,前端必须有一颗高分辨率、低噪声的 ADC。

ADS122U04IPWR 这颗芯片的核心优势就在这里。它是 24 位分辨率,内部还集成了可编程增益放大器,用 PGA 把微弱信号放大之后再做量化,这样小信号也能在 ADC 的满量程范围里充分展开。配合内部的低漂移基准源,整个模拟前端不再依赖外部精密电阻或独立基准芯片,这对 PCB 面积和 BOM 成本都很友好。再说直接一点:它不是“一颗 ADC”,而是把仪表放大器、基准、温度传感器和四路输入选择器打包在一起的前端方案。

1.2 为什么 ADS122U04IPWR 能省掉一半麻烦

我最初想用 SPI 接口的 ADS1220 或类似芯片,但项目里主控是 PIC18F85J50,本身带 SPI 外设,接线也不复杂。真正的问题出在 HVAC 控制柜的复杂环境里。柜子里有继电器、接触器、变频器,SPI 的 SCK 和 MOSI 长距离连线容易耦合噪声,时序稍微被干扰就会出现“数据移位、读回全 0、写寄存器失败”这种玄学问题。把时序调稳定要花不少时间,而且每个板子布线不一样,现象还不一样。

ADS122U04IPWR 改成 UART 接口后,通信只有 TXD 和 RXD 两根线,协议又是异步字符帧,对时序裕量要求低得多。尤其放在 2 米到 5 米的传感器线缆场景里,UART 只要波特率正确,基本不用担心时钟边沿被干扰。它的内部设计其实也保留了 24 位 ADC 和 PGA 的全部能力,四路模拟输入可以做差分或伪差分,配合内部集成的传感器温度检测功能,还可以顺便做热电偶的冷端补偿,省掉一个贴在端子排上的 NTC。这些特性组合起来,让“一颗芯片管四路温度”成为现实。

1.3 PIC18F85J50 在这个项目里能干什么

PIC18F85J50 是一颗 8 位 MCU,但它有多个 UART 模块、足够的内存和工业级温度范围。最初有人质疑 8 位机做高精度测量会不会算不过来,实际真正需要主控参与运算的只有查表、线性化和数字滤波。比如 NTC 的 Beta 公式计算,用 32 位浮点也就是几十条指令的事,PIC18F 完全跑得动。更重要的是 J50 系列的工作电压范围宽,IO 电平也能和 3.3V 传感器系统兼容,不用额外做复杂电平转换。

选择它还有一个很现实的原因:很多 HVAC 控制器项目对成本敏感,8 位 MCU 在供应链上更成熟,开发资料也齐全。你不需要为了一路温度测量去上一颗 Cortex-M4F,把资源和成本浪费在 CPU 性能上。主控真正要做的就是初始化 UART、解析 ADS122U04IPWR 返回的数据帧、把原始码值换算成工程温度值,然后通过 Modbus 或者 CAN 送出去。这种分工很符合工业控制里“模拟前端负责测量、主控负责通信和控制”的经典架构。

1.4 为什么不直接用 MCU 内置 ADC

我见过不少工程师直接拿 MCU 内置 ADC 做 NTC 温度采集,配合 10kΩ 上拉电阻到电源,精度做到 1°C 到 2°C 也不是不行。但 HVAC 系统里温度控制经常涉及 PID 调节,如果温度波动在 ±0.5°C 以内,很多设备是不动作的;可内置 ADC 的非线性、参考电压漂移和电源噪声叠加起来,可能在满量程范围内造成几十个 LSB 的误差,反映到控制上就是压缩机频繁起停、房间温度震荡。另一个问题是 MCU 内置 ADC 的采样保持电路切换时间不够灵活,多路复用时通道间串扰也会影响精度。

独立 ADC 芯片的优势在于模拟部分可以做得更干净。ADS122U04IPWR 的 PGA 输入端有完善的 EMI 滤波能力,数据输出采用数字通信方式传输,模拟地到数字地之间的相互干扰更容易隔离。这也是我坚持用外部 24 位 ADC 的原因:把敏感模拟测量和嘈杂数字控制彻底分开,系统设计思路清晰,后续维护也好定位问题。

2. 硬件连接与电路设计要点

2.1 不同温度探头的接入方式

ADS122U04IPWR 虽然是四通道输入,但具体怎么接传感器要看实际测温类型。如果接的是热电偶,直接把热电偶的正负极接 AINx 和 AINx+1,利用 PGA 的高增益模式放大微伏级信号。热电偶信号本身是直流的,但现场会叠加工频干扰和射频噪声,所以输入端最好串联一个几百欧姆的电阻,再接一个 100nF 到 1µF 的电容到地,构成低通滤波,避免高频噪声在 PGA 之前就饱和。

如果接 PT100 或 PT1000,情况要复杂一点。它们本质上是电阻传感器,必须先有一个激励电流流过电阻,再把电阻两端电压送到 ADC。ADS122U04IPWR 不像上一代 RTD 专用芯片那样自带恒流源,所以需要外接精密电流源,或者用简单的桥式电路。我自己常用 1mA 恒流源激励 PT100,0°C 时电阻 100Ω,两端电压 100mV,300°C 时电阻约 215Ω,两端电压 215mV。PGA 增益设成 8 或者 16,这个范围的信号就能被放大到接近满量程。

如果只是测 HVAC 的风管温度,NTC 热敏电阻反而是最简单的方案。NTC 和精密电阻组成分压电路,把分压点接到 ADC 输入,通过查表或者 Beta 公式换算温度。不过 NTC 的非线性很大,低温段和高温段的分辨率完全不一样,建议尽量选择阻值变化平缓的型号,并把分压电阻的温漂控制在 25ppm/°C 以内,不然 ADC 再准也会被分压电阻拖累。

2.2 UART 通信与电平匹配细节

ADS122U04IPWR 的工作电压一般是 2.3V 到 5.5V,PIC18F85J50 可以选择 3.3V 供电。最稳妥的做法是把两颗芯片都用 3.3V 供电,IO 电平直接兼容,TXD 和 RXD 交叉相连就行。这里必须注意一个问题:UART 的 TXD 在空闲时是高电平,如果 MCU 和 ADC 的电源上电时序不一致,MCU 的 IO 可能会被 ADC 拉到一个不确定状态。所以我在实际电路里会在 TXD 和 RXD 上各加一个 10kΩ 上拉电阻接到 3.3V,同时在 MCU 侧把相关引脚配置成数字输入或开漏输出,避免上电瞬间出现总线冲突。

ADS122U04IPWR 的 UART 通信是带地址和校验的。它支持同时挂多颗芯片在同一条总线上,通过地址字节区分具体设备。这个特性对多路温度采集很有用,比如四个模块挂在一条 UART 总线上,只要每个模块用拨码开关设置不同地址,主控就能顺序访问。接线距离长了以后,建议把波特率降到 9600 或 19200,信号完整性会好很多。9600 波特率下,一帧温度数据大约耗时 3ms 到 5ms,四路轮询下来完全够用。

2.3 电源、PCB 布局与 HVAC 机箱的抗干扰

整个测温模块最忌讳的是电源不干净。HVAC 柜子里有 220V 交流电,继电器闭合瞬间会产生很大的电流跳变,地线也会跟着抖。我给 ADS122U04IPWR 供电用的是单独的 LDO,输入来自 24V 电源模块,LDO 输出端并一个 10µF 陶瓷电容和一个 0.1µF 高频小电容,做到宽带去耦。模拟电源和数字电源如果允许,尽量用磁珠隔开,至少要让 ADS122U04IPWR 的 AVDD 和 DVDD 引脚都有独立的去耦电容。

PCB 布局上,我习惯把模拟输入放在板子边缘,传感器线缆通过端子排接入,从端子到 ADC 的走线尽量短。模拟地和数字地在 ADC 芯片下方单点连接,避免数字信号回流穿过模拟区域。如果板子上还有继电器驱动电路,一定要把继电器线圈的驱动地单独走一路,不要和传感器模拟地混在一起。再一个容易踩的坑是传感器线缆屏蔽层接地:屏蔽层最好在控制柜侧单端接地,不要在传感器侧也接地,否则会形成地环路,低频干扰反而更严重。

3. 软件层面:从 UART 初始化为一次完整的温度读取

3.1 初始化序列与寄存器配置

软件的第一步是初始化 PIC18F85J50 的 UART。波特率 9600,8 位数据,无校验位,1 位停止位。ADS122U04IPWR 的 UART 协议是帧格式,包含设备地址、命令、数据和校验段。我不会在这里逐字节抄手册,因为不同版本芯片的帧定义会略有差异,但驱动骨架是一样的:发送读寄存器命令、等待响应、解析状态字节、根据状态判断转换是否完成。

我习惯先做一次上电复位,然后读回 ADC 的默认寄存器值,确认通信链路能正常工作。再写配置寄存器,把输入多路选择器设置为任意通道组合,PGA 增益按传感器类型设定,基准选择为内部基准,转换模式设为单次转换。对于 HVAC 现场,我一般不上连续转换,因为温度变化本身很慢,单次转换可以做到“随时唤醒、测完就睡”,对整机功耗和电磁干扰都有好处。

下面这段代码是按“可读性优先”写的驱动骨架,具体命令帧请对照你手头数据手册的时序图做二次封装。

uint8_t uart_send_byte(uint8_t dat) { while (!TXSTAbits.TRMT) {}; // 等待发送寄存器空 TXREG = dat; return 0; } uint8_t uart_recv_byte(uint8_t *dat) { while (!RCSTAbits.FERR) {}; // 等待接收完成 *dat = RCREG; return 0; } void adc_reset(void) { uart_send_byte(DEV_ADDR); uart_send_byte(CMD_RESET); // CMD_RESET 以手册为准 __delay_ms(10); } void adc_write_config(uint8_t addr, uint8_t value) { uart_send_byte(DEV_ADDR); uart_send_byte(CMD_WRITE_REG); // 写寄存器命令 uart_send_byte(addr); uart_send_byte(value); uart_send_byte(calc_crc(value)); // 简单校验 }

配置完成后,我会再读一遍所有寄存器,确认写入值和实际值一致。这一步能解决现场非常多的“通信时好时坏”问题。如果写入失败,多半是接线松动或者地址配置错误,提前发现总比在测量阶段抓瞎强。

3.2 发起转换并读取测量结果

单次转换模式下,初始化后 ADC 不会自己开始采样。你要发送启动转换命令,然后等待转换完成标志。有的芯片有 DRDY 引脚,有的芯片需要在状态字节里查询标志位,具体以数据手册为准。我在代码里采用轮询方式:每 20ms 发一次状态查询,发现转换完成后再读取转换结果。这样做的好处是主控可以插空处理其他任务,不会被 ADC 阻塞。

读出来的结果一般是 24 位二进制补码,高字节在前。手动合并三个字节时注意符号位扩展。如果芯片输出的是 24 位无符号码,用 32 位整数接收,然后判断最高位是否为 1,如果是 1 就需要转成负数。转换完成之后,最好检查状态字节里的错误标志,比如输入超量程、PGA 饱和或者基准电压异常。这些错误标志在工业现场太重要了,不用白不用。

3.3 原始码值换算成电压和温度

得到原始 ADC 码后,先换算成输入电压。24 位 ADC 的 LSB 大小取决于 PGA 增益和基准电压。以内部基准 2.048V、PGA 增益 8 为例,输入满量程相当于 ±2.048V / 8 = ±0.256V。也就是说,ADC 码值变化 2^24 次,对应电压变化 0.512V,那么每个 LSB 对应的电压约为 0.512V / 16777216 ≈ 30.5nV。这个分辨率拿来测热电偶绰绰有余。

int32_t raw_code = merge_3_bytes(data_buf); float voltage_v = raw_code * (2.0 * 2.048 / 8.0 / 16777216.0); float voltage_mv = voltage_v * 1000.0;

电压变成温度,就要看传感器类型了。PT100 的阻值随温度近似线性变化,0°C 时 100Ω,100°C 时 138.5Ω,斜率约 0.385Ω/°C。先用电压和激励电流算出电阻,再用线性公式或查表得到温度。NTC 热敏电阻则用 Beta 公式:T = 1 / (1/T0 + ln(R/R0)/B) - 273.15,其中 T0 是 25°C 对应的开尔文温度,R0 是 25°C 时的标称阻值。热电偶稍微麻烦,需要先由电压查对应分度表得到仪表温度,再减去冷端温度补偿。

3.4 数字滤波与数据稳定性

24 位 ADC 本身分辨率很高,但也意味着它会把微伏级的噪声全部量化出来。HVAC 现场的温度信号变化很慢,我通常会做两级滤波:先做中值滤波,取连续 5 次采样去掉最大最小值再求平均值,把脉冲干扰滤掉;再做一阶低通,让控制环路看到的温度曲线平滑变化。一阶低通的系数可以设成每次更新 20% 新值,这样时间常数大约几十毫秒到几百毫秒,既不迟钝也不毛躁。

需要特别提醒的是,滤波不能放在校准之前。所有滤波算法都必须针对被测温度本身,而不是针对原始 ADC 码。否则零点漂移和增益误差也会被平均进去,让系统看起来稳定但实际不准。我见过很多现场工程师把原始码值做平均,后来校准时才发现平均出来的结果跟真实温度差了一大截,就是这个原因。

4. 误差分析与校准策略

4.1 误差来源不要只看 ADC

很多人在评估系统精度时只盯着 ADC 的位数,这是个大误区。24 位 ADC 的量化噪声非常小,但整个测量链路的误差往往来自传感器、基准电压、激励电流和连接器接触电阻。下面我列了一张实际评估时常用的误差来源表,供大家在方案阶段估算用。

误差来源典型影响应对方式
传感器自身精度PT100 可达 ±0.1°C 到 ±0.3°C选用更高等级传感器或做两点校准
内部基准温漂影响增益精度,造成约 ±0.05%FS使用低漂移参考模式并做软件校准
激励电流温漂RTD 测温中每 10ppm/°C 至少引入 0.02°C选用精密恒流源或定期校准电流
PGA 零点漂移输入短接时仍有几十到几百 nV 偏差初始化后做硬件自校准或软件减偏移
冷端温度不准热电偶测量直接引入等值误差利用片上温度二极管并做平移校准
端子接触热电势可能达到 1°C 级别使用同种金属端子并保持温度一致

这张表说明,ADC 只是提供了一个高分辨率的测量平台,真正的系统精度要靠外围和校准拼出来。HVAC 应用如果只追求 0.5°C 精度,放宽校准要求问题不大;但如果是工艺冷却水或者恒温恒湿箱这类要求 0.1°C 的场景,就得认真做校准流程。

4.2 零点校准和增益校准怎么做

零点校准最简单:把 ADC 输入通道短接,并在固件里记录当时的测量值作为偏移量。每次换算温度前先减去这个偏移量。注意短接时要使用与传感器相同的切换方式,不能直接把 AINx 和 AINx+1 长时间缩在一起,最好用一个继电器或者杜邦线临时连接,记录完偏移量再恢复。否则你校准的是一个“短路状态”,而不是“传感器接入状态”,仍然会有残余误差。

增益校准就需要更精确的手段。如果你有高精度电压源,可以给输入通道加一个已知电压,比如 100mV 或者 200mV,然后根据 ADC 读数计算实际增益和理想增益的比例系数。这个比例系数会存储在 EEPROM 里,每次上电加载到固件中。没有高精度电压源时,可以用电阻箱模拟 RTD 的已知阻值,配合 1mA 恒流源产生已知电压,效果等同。校准最好是两点同时做,低点取零点附近,高点取测量范围的上限,两点之间做线性插值。

4.3 热电偶冷端补偿的工程处理

热电偶本身是差分测量器件,它测的是热端和冷端之间的温差,冷端参考点接在 ADC 输入端子的位置。如果冷端温度就是板上温度,我们可以直接用 ADS122U04IPWR 内部温度传感器的读数做冷端补偿。但内部温度传感器测的是芯片内部温度,和端子温度之间可能有一个固定差值,这个差值会随气流或柜内温度变化。所以更稳妥的做法是在端子排附近再放一个高精度 NTC,标定出它和热电偶冷端之间的差值。

现场实测时,我用电烙铁加热一个金属块,对比热电偶读数、NTC 读数和参考温度计读数,得到冷端补偿修正量。修正量可以是常数,也可以做成分段表。因为 HVAC 控制柜内温度一年四季变化很大,只做固定平移可能夏天准、冬天偏,分段表更可靠。记住冷端补偿的误差是 1 比 1 加到最终温度上的,热电偶测量想做到整体 0.5°C,冷端补偿必须控制在 ±0.2°C 以内。

4.4 自热效应和长期漂移

任何激励电流流过传感器都会产生热量,温度传感器本身被自己热到,测量值就会偏高。PT100 在 1mA 电流下自热一般小于 0.1°C,但如果传感器封装很小且风管里风速很低,热量散不出去,自热会更大。解决方法是降低激励电流,比如 PT100 用 0.5mA,PT1000 用 0.1mA;前提还是 ADC 的 PGA 增益要调到足够高,小信号也能分辨。NTC 更敏感,建议激励电流不超过 0.2mA。

长期漂移方面,PCB 上任何焊点、连接器和端子都存在缓慢氧化的过程,几年后接触电阻可能变大。我在产品里做了一项“定期自检”:每个月把内部校准电阻切换到输入端,记录 ADC 读数变化,如果和出厂值的偏差超过阈值就通过 Modbus 上报“传感器需要维护”。这套逻辑平时不引人注意,但真正发生老化问题时能省去大量现场排查时间。

5. HVAC 现场调试的常见坑与排查实录

5.1 UART 通信不稳定,时序好像没问题但线路偶发异常

这个问题在 HVAC 柜子里太常见了。故障现象是上电后能通信一阵子,但压缩机或继电器一动作,通信就丢帧。排查第一步看供电:继电器线圈断电瞬间会产生反电动势,把 24V 电源拉出毛刺,如果 LDO 压差又不够,就会直接干扰 ADC 电源。解决方法是给继电器线圈并联续流二极管,并把 LDO 的输入输出电容加大。第二步看线缆:UART 的 TXD 和 RXD 如果和继电器驱动线并行走线,干扰会直接感应进来,改走不同层或加屏蔽就能解决。

如果你用的是 9600 波特率,还出现少量丢帧,多半是总线上拉电阻太大或者分布电容太大导致波形边沿变缓。把上拉电阻从 10kΩ 改到 4.7kΩ,或者降低波特率到 4800,往往就好了。最后再查一下地址配置,多颗 ADC 挂在同一总线上时,如果有两个模块地址撞了,会出现偶尔读到 0xFF 或错误帧的情况。

5.2 温度读数像“心电图”一样抖动

读出来的温度短时间内在 ±0.5°C 之间来回跳,说明噪声没有被充分压制。先不要怀疑 ADC 芯片,拿出示波器看 AIN 引脚的波形。如果是 50Hz 工频干扰,在输入端并联 1µF 电容能把干扰压到可接受范围。如果是高频毛刺,输入端串联几欧姆到几百欧姆的电阻做 RC 滤波,时间常数设置不要超过软件采样周期的五分之一,免得信号被滤平。

另一个常见原因是在测量过程中还开着继电器扫描或者数码管动态刷新。这些数字电路的瞬态电流会在电源地上反弹,而 ADC 的模拟输入又跟它共用参考地,读数自然不稳定。我的做法是让温度采样发生在“安静窗口期”,比如数码管刷新的间隙,或者继电器切换完 20ms 之后再进行转换。这样软硬件都不需要大动,稳定性却能明显提升。

5.3 校准之后过几天又偏移了

如果你做了零点校准和增益校准,但过几天精度又漂了,大概率是校准系数被写进了 RAM,掉电就丢,或者校准时用了不稳定的参考源。校准系数一定要存进 EEPROM 或者 Flash 模拟 EEPROM 区域,并加上校验字。如果参考源本身随温度变化,比如用普通稳压管搭的基准,校准效果当然只能维持几天。把参考基准源换成内部基准,或者选用低温漂的参考芯片,重复性会好很多。

还有一个小坑是校准时的读数次数太少。单次读数偏差可能达到几个 LSB,直接写进校准系数就会引入新的误差。比较稳妥的做法是每次校准时连续读 100 次再取平均,平均值作为校准基准。我甚至在校准程序里加入了统计方差判断:如果 100 次读数的方差超过阈值,就提示“校准环境噪声过大,请降低干扰后重试”,这样保证了校准动作可信。

5.4 温度范围显示得对,但控制就是慢半拍

系统显示的温度在理想范围,可 PID 控制响应还是有滞后,这种情况要检查采样周期和滤波时间常数。HVAC 温度变化本来就是分钟级的,但如果在算法里叠加了 500ms 甚至 1s 的软件低通滤波,传感器又包在厚金属套管里,整个控制环的惯性会大得离谱。解决方案是滤波时间常数和传感器热时间常数分开考虑:如果传感器热时间常数是 10 秒,软件滤波就不要超过 2 秒,否则你会觉得“显示很稳,但控制永远跟不上”。

在工程现场,我一般把原始采样周期设为 200ms 一次,中值滤波窗口取 5 个点,滑动平均再取 4 次。这样整体数据延迟大约在 1 秒左右,对 HVAC 的控制完全够用。如果未来要做变风量快速调节,可以再缩短采样周期,但一定要保证电源安静、端子可靠,不然快采样只会快吃到噪声。

5.5 最后分享一个“土办法”:用温度梯度代替绝对值

在很多 HVAC 项目里,大家真正关心的不是绝对温度是多少,而是温度变化趋势和差值。这时我更倾向于先测四路温度的梯度,也就是通道间的相对值,再调控制逻辑。因为相对值测量可以把 ADC 的共模误差、参考电压误差都抵消掉,精度反而比绝对值有意义。比如你要判断风管前后温差是否达到 2°C,只需要保证两路通道用相同增益、相同滤波参数,差值测量往往能做到 0.05°C 的稳定度。

这种思路的工程价值在于它不需要高精度基准源,甚至不需要做繁琐的增益校准,只需要保证系统的重复性。先把“相对温度准确”做到极致,再通过一次简单的偏移校准把绝对值拉回来,会比一开始就死磕绝对精度省力很多。我在这个项目里的实际体会是,ADS122U04IPWR 与 PIC18F85J50 的搭配恰好适合这种“先保证低噪声、再追求高精度”的开发路径。如果你也正在做类似的工业或 HVAC 温度测量,不妨先把这条路走通,再回头优化成本。