2026/11/5 7:36:40

ADS122U04+PIC32MZ:HVAC高精度温度采集系统设计与实现

ADS122U04+PIC32MZ:HVAC高精度温度采集系统设计与实现 聊到温度测量尤其是 HVAC 和工业现场这种环境很多人第一反应就是随便找个 NTC、接个单片机、读个 ADC 不就行了。真做起来就会发现事情远没那么简单传感器长线压降、自热效应、工频干扰、整机温漂每一个都能让温度值在屏幕上蹦迪。我最近做的这个项目核心就是两颗芯片的搭配——TI 的 ADS122U04IPWR 24 位 ADC和 Microchip 的 PIC32MZ1024EFK144 单片机用来采集 HVAC 系统里风管温度、冷冻水供回水温度和室内环境温度。整套方案从选型到落地实测精度和稳定性都达到了预期这篇文章就把完整过程记录下来给准备做类似温度采集项目的朋友一个参考。1. 方案拆解这套双芯片组合到底强在哪1.1 为什么偏偏选 ADS122U04IPWR 这颗 ADC先聊 ADC。工业温度测量的核心矛盾是信号变化极其缓慢但极其微弱。以最常见的 Pt100 为例温度每变化 1°C电阻只变化大约 0.385Ω如果用 1mA 激励电流换算成电压只有 0.385mV。要让 0.1°C 的分辨率有意义系统必须分辨出 0.04mV 级别的电压变化这对 ADC 的要求一下子就上去了。ADS122U04IPWR 是一颗 24 位 Δ-Σ 型 ADC4 通道差分输入带可编程增益放大器PGA增益范围 1 到 128 倍。它最吸引我的地方是集成了UART 接口——你不需要去折腾 SPI 时序、片选信号或者 GPIO 模拟时序直接把它当一颗串口从机来用发送命令读数据就行。这在工业现场是一个巨大的优势。为什么这么说因为温度传感器往往装在风管里、水管上离主控板有几米甚至十几米远。SPI 在这种距离下非常脆弱时钟抖动、线间串扰都会导致通信错误。而 UART 是异步串行通信抗干扰能力强得多用双绞线或者屏蔽线跑到十米级别完全没有压力。工业现场最常见的 RS-485 本质上也还是串口协议UART 接口让后续扩展和长线传输都从容得多。另外这颗 ADC 内置了两路可编程激励电流源这是为 RTD 测量量身定做的。激励电流源给传感器供电同时参与比例测量可以抵消参考电压的漂移。它还内置了温度传感器可以做冷端补偿配合热电偶使用也可以用来自校准。这些功能单独拿出来都不稀奇但集成到一颗芯片里外围电路可以省掉一大片。1.2 PIC32MZ1024EFK144主控选它不只是因为性能PIC32MZ1024EFK144 是 Microchip 的 MIPS M 级内核单片机主频 200MHz带 FPU1MB FlashSRAM 也有几百 KB。说实话拿来做温度采集这个体量的活儿性能是严重溢出的。但我选它并不是为了跑分而是看中了几个对工业场景真正重要的点。第一是这个系列对工业环境的适应能力。工作温度范围宽引脚定义和外围模块的设计都考虑了抗干扰和长寿命需求这在 HVAC 控制柜、机房、锅炉房这种场合很重要。第二是外设丰富且独立UART、SPI、I2C、CAN、DMA、外部中断一应俱全意味着你不必为了一个功能去省着用引脚layout 的时候自由度很高。第三这颗芯片有硬件加密引擎虽然温度采集本身用不上但如果你做的是带联网功能的楼宇控制器、需要固件防抄、通信加密这个能力后面会用得上。还有一个很实际的原因PIC32MZ 系列的调试工具链成熟MPLAB X XC32 编译器配套的 ICD 调试器和 PICkit 都很好用。做工业项目的朋友都懂调试体验就是开发效率遇到问题能快速定位比什么都重要。1.3 这套组合适合什么场景不适合什么场景任何方案都有边界这套组合的甜点区是HVAC 系统的多点温度采集风管送风/回风温度、冷冻水供水/回水温度、冷凝水温度、室内温度工业过程温度监测反应釜、热交换器、锅炉进出口、环境温度记录需要中等以上精度、多通道、传感器类型不固定的场合但它不适合的场景也很明显如果只是做单通道、精度要求不高的消费级产品比如一个室内温湿度计用 12 位 MCU 内置 ADC 加一颗 NTC 就搞定了成本低一个数量级没必要上这套方案。如果要做几百上千通道的大型采集系统又需要高速采样24 位 Δ-Σ ADC 串口通信的方式也不太合适应该考虑专用采集卡。2. 硬件细节从传感器到 ADC 再到 MCU 的信号链设计2.1 传感器接法RTD、热电偶、NTC 三种典型接法这套系统里我同时用了三种类型的温度传感器正好覆盖了工业 HVAC 最常见的三种情况。RTDPt100/Pt1000用于风管温度和冷冻水温度。RTD 精度高、稳定性好但有一个头疼的问题导线电阻会引入误差。Pt100 在 0°C 时只有 100Ω如果导线电阻有 1Ω那就是 2.6°C 的误差完全不可接受。解决方法是三线制或四线制接法。ADS122U04 的两路激励电流源在这里派上了大用场——三线制接法下一路电流源驱动传感器另一路驱动导线做补偿配合 ADC 内部的测量切换可以自动消除导线电阻的影响。我实际做的时候用三线制接法线长五米误差控制在 0.1°C 以内。热电偶K 型或 T 型用于一些高温场合。热电偶输出的是微伏级别的热电动势K 型热电偶典型灵敏度大约 40µV/°C比 RTD 的信号还微弱所以 PGA 增益必须拉高我通常设到 64 倍或 128 倍。热电偶测量必须做冷端补偿——热电动势是测量端和冷端的温差产生的冷端温度用 ADS122U04 内部温度传感器来测然后在固件里做补偿计算。这里有一个细节冷端补偿的精度直接影响整体精度所以内部温度传感器的校准很重要我实测下来在 20~30°C 范围内补偿效果很好。NTC 热敏电阻用于室内环境温度。NTC 的好处是便宜、响应快、灵敏度极高但一致性差、线性度差。我只在非关键场合用它而且必须做查表线性化和个体标定。NTC 的接法最简单激励电流源 分压电阻就行但要从软件上把非线性掰回来。2.2 PCB 布局和模拟前端24 位 ADC 对噪声是零容忍24 位 ADC 听起来很美好但如果布局布线不当实际有效位数可能只有 16 位甚至更低。噪声是 24 位 ADC 的天敌这句话一点不夸张。我在这块板子上做的第一件事是把模拟部分和数字部分彻底分开。ADS122U04 以及它的传感器接口、激励电流源、参考电压去耦电容都放在 PCB 的一个独立区域PIC32MZ、UART 收发器、电源转换电路放在另一个区域。两个区域之间用星形接地或单点接地连接模拟地AGND和数字地DGND在 PCB 的电源输入端汇合绝不允许数字信号回流穿过模拟区域。电源是另一个关键。ADS122U04 的模拟电源 AVDD 和数字电源 DVDD 我都用了独立的 LDO 供电并且在靠近芯片引脚处放置了 0.1µF 10µF 的去耦电容组合。我还踩过一个坑一开始为了省事直接用 DC-DC 模块的 3.3V 给 ADC 供电结果转换结果的跳动幅度惊人。后来换成低噪声 LDO 单独供电噪声立刻降了一个数量级。DC-DC 的纹波对于逻辑电路可能无所谓但对 24 位 ADC 来说就是灾难。信号线的走线也很有讲究。RTD 的激励电流源和测量输入走线必须分开避免激励电流的磁场感应到测量回路里。所有传感器信号线我都做了包地处理就是信号线两侧加地线形成一个简单的屏蔽结构。如果空间允许可以在 ADC 输入引脚前加一个 RC 低通滤波器截止频率设在几百赫兹能有效滤除带外高频噪声。滤波器电阻不宜太大否则会和传感器阻抗分压造成增益误差我用的是 1kΩ 0.1µF。2.3 UART 链路和电源设计工业现场要考虑的生存问题ADC 和 MCU 之间的 UART 链路在板内很短的情况下可以直接连接但考虑到工业现场可能有长线需求我加了 ESD 保护和电平缓冲。ADS122U04 的 UART 引脚是 3.3V 电平PIC32MZ 也是 3.3V 电平两者直连没问题但为了保险起见我在 UART 线上串接了 100Ω 电阻并且在 ADC 端的 RX 引脚上加了 TVS 管防止静电和浪涌。电源方案上整个系统用 24V 工业电源供电板上先经过一个隔离 DC-DC 降到 5V再用两个 LDO 分别转出 3.3V 模拟电源和 3.3V 数字电源。模拟地、数字地、机壳地在电源入口处做单点连接。这套电源架构的代价是多花了一点成本和板面积但换来的稳定性和抗干扰能力在工业现场绝对值回票价。3. 固件落地ADC 驱动、滤波和温度换算的完整实现3.1 寄存器配置与 UART 命令交互的核心流程ADS122U04 的寄存器配置方式跟 SPI 版本的 ADS1220 类似只是传输通道换成了 UART。固件侧的基本流程是初始化 UART - 复位 ADC - 写配置寄存器 - 发启动命令 - 等待 DRDY - 读数据。先看 UART 初始化。我用的是 PIC32MZ 的 UART2 模块波特率 1152008 位数据无校验1 位停止位。计算波特率分频器的公式是// FPB 40MHz外设时钟 // 目标波特率 115200 // 分频系数 FPB / (16 * 波特率) - 1 20.7取 21 U2BRG 21; U2MODE 0; U2MODEbits.BRGH 0; U2STA 0; U2STAbits.UTXEN 1; // 使能发送 U2STAbits.URXEN 1; // 使能接收注意一个细节如果后面要支持更长的通信距离或更差的信道环境可以把波特率降到 9600 或 19200。波特率越低每个 bit 的时间窗口越大抗干扰能力越强。但代价是数据吞吐量下降。对于温度采集这种低速率应用9600 波特率完全够用我用的是 38400平衡了速度和可靠性。复位 ADC 和配置寄存器的代码如下void ads122u04_reset(void) { uint8_t cmd 0x06; // RESET 命令 uart_write(cmd, 1); delay_ms(2); // 等待复位完成 } void ads122u04_write_reg(uint8_t addr, uint8_t value) { uint8_t cmd[3]; cmd[0] 0x40 | (addr 1); // WREG 命令addr 范围 0~3 cmd[1] 0x00; // 写 1 个寄存器 cmd[2] value; uart_write(cmd, 3); delay_us(100); }ADC 内部有四个配置寄存器分别控制输入多路复用器MUX、PGA 增益、数据速率和转换模式、以及激励电流源。我的配置思路是这样的寄存器 0MUX四通道分别配置为 AIN0-AIN1、AIN2-AIN3、AIN0-AIN3、AIN1-AIN2 等差分对寄存器 1增益RTD 通道设 PGA 8热电偶通道设 PGA 64NTC 通道设 PGA 4寄存器 2数据速率20 SPS正常模式。这个速率下 ADC 的噪声最低有效分辨率最高寄存器 3电流源两路激励电流源设为 500µA用于 RTD 三线制测量数据速率的取舍要重点说。ADS122U04 支持从 20 SPS 到 1000 SPS 的采样率但分辨率是跟着采样率走的——采样率越高等效噪声带宽越宽有效位数越低。温度信号的特点是变化极慢20 SPS 完全满足需求所以我直接选了最低速换取最高的分辨率。实测下来 20 SPS 时 ADC 输出码值的跳动非常小等效分辨率大概能到 20 位以上对应温度分辨率远优于 0.01°C。3.2 数据读取、滤波和温度线性化换算配置完成后发 START 命令让 ADC 开始连续转换然后通过 DRDY 信号或者轮询判断数据是否就绪。void ads122u04_start(void) { uint8_t cmd 0x08; // START 命令 uart_write(cmd, 1); } int32_t ads122u04_read_data(void) { uint8_t cmd 0x12; // RDATA 命令 uint8_t buf[4]; uart_write(cmd, 1); uart_read(buf, 4); // 4 字节24 位数据 状态字节 int32_t raw ((uint32_t)buf[0] 16) | ((uint32_t)buf[1] 8) | buf[2]; // 24 位有符号数扩展为 32 位 if (raw 0x800000) raw | 0xFF000000; return raw; }拿到原始码值之后换算分两步先把码值换算成电阻值再把电阻值换算成温度。RTD 的电阻换算用比例法。假设参考电阻 R_ref 1kΩ精度 0.01%ADC 满量程码值为 2^23 8388608那么R_rtd (raw_code / 8388608) * R_ref这个公式成立的前提是采用了比例测量架构即 ADC 的参考电压恰好来自激励电流源流过参考电阻产生的电压。好处很明显激励电流源的绝对值漂移不会影响测量结果因为电流同时流过参考电阻和传感器比例抵消了。然后是电阻到温度的换算。Pt100 的阻温特性在 0°C 到 100°C 范围内近似线性T (R / 100 - 1) / 0.00385比如测得 R 119.4Ω则 T (119.4/100 - 1) / 0.00385 ≈ 50.4°C。这个线性近似在窄温度范围内误差很小约 ±0.1°C如果要求更高精度用查表法或 Callendar-Van Dusen 方程做多项式拟合。我做了一个 0~200°C 的 Pt100 分度表每 1°C 一条数据固件里查表加线性插值精度能做到 0.05°C 以内。原始码值直接换算出来的温度通常带有一定噪声即使 20 SPS 下也有轻微的码值跳动。我在固件里加了一个简单的一阶低通滤波float filtered_temp 0; // 每次取到新测量值后更新 filtered_temp (new_temp - filtered_temp) * 0.1f;系数 0.1 表示滤波时间常数温度响应速度会变慢但 HVAC 场景本来就不需要快速响应稳定是最优先的。如果想要响应快一点可以把系数调大到 0.2 到 0.3。这个平滑系数本质上是低通滤波器的截止频率选值的准则是滤除高频噪声但不能让真实温度变化被钝化太多。热电偶的换算更复杂一些。先查热电偶分度表得到热电动势对应温度的初值再用 ADS122U04 内部温度传感器测到的冷端温度换算成冷端电动势加到测量值上最后再查一次表得到真实温度。冷端补偿的精度取决于内部温度传感器的标定我建议在固件里做一点偏移校准——把已知温度的参考源测量一遍算出冷端偏移量存到 Flash 里。3.3 单次转换和连续转换的选择与切换ADS122U04 支持单次转换和连续转换两种模式。我最终采用的是连续转换模式但这里有一个很多人容易忽略的功耗问题——如果系统对功耗敏感比如电池供电的现场仪表连续转换模式下 ADC 和 UART 都处于持续工作状态功耗可能不是最优的。这时候可以切换为单次转换模式发 START 命令等待转换完成读数据然后进入休眠状态按需唤醒。HVAC 控制器通常不愁供电所以我用连续转换 周期读取的方式。具体做法是MCU 每 2 秒读一次四路数据做滤波、换算、打包通过 Modbus 协议上报给上位控制器。2 秒的刷新周期对 HVAC 控制来说完全足够温度变化本身就要几十秒甚至几分钟才会稳定。系统在硬件上还留了 DRDY 中断引脚如果以后想改成事件驱动模式直接把 MCU 的外部中断接到 DRDY 上用中断触发读取会更省 CPU。4. 现场调试我在这个项目里踩过的坑4.1 症状一UART 通信完全不通发送命令没响应第一次上电调试发送复位命令后石沉大海用示波器量 ADC 的 UART 引脚发现 TX 引脚完全没有波形。排查了一圈最后找到了原因ADS122U04 复位后默认的工作模式可能不是我预期的 UART 模式有些引脚需要通过外部电阻拉到特定电平来配置上电默认状态。我花了不少时间读数据手册才发现这个芯片的 UART 使能和工作模式配置除了寄存器之外还和某个引脚的上电状态相关。解决办法也很简单在复位引脚上加一个 RC 延时电路确保上电时电源稳定后再释放复位同时在固件里加大复位后的延时。把复位后的等待时间从 2ms 加到 10ms问题就消失了。这种上电时序问题在工业现场很常见ADC 需要的时间比 MCU 更长一定要给足。4.2 症状二温度读数跳变严重滤波也压不住第二个问题是 RTD 通道的数据跳动很大明显超出正常范围。我用示波器看 ADC 输入引脚发现上面叠加了一个幅度不小的高频噪声。排查下来有两个元凶。第一个是开关电源的纹波耦合到了模拟电源上。当时为了测试方便我用的是一个 24V 适配器供电适配器的开关噪声通过 LDO 耦合到了 3.3V 模拟电源上。虽然 LDO 有一定的纹波抑制能力但对于频段很高的开关噪声抑制效果有限。解决方法是把 LDO 换成更高 PSRR 的型号并在 LDO 前后都加了 π 型滤波器电感 电容。第二个元凶更有意思RTD 的激励电流源线路和测量输入线路在 PCB 上靠得太近激励电流的跳变通过寄生电容耦合到了测量输入端。这个在原理图上是看不出来的只有布局布线才会触发。我把激励走线单独走一层中间用地层隔离测量输入从另一侧进入问题就消失了。所以做 24 位 ADC 的 PCB布局的敬畏心一定要有该分的层要分该隔离的走线要隔离不能凭感觉。4.3 常见问题速查表症状可能原因排查思路与解决办法数据全部是 0x7FFFFF 或 0xFFFFFF输入超出量程、MUX 配置错误、传感器断路检查寄存器配置用固定电压源比如 1.5V 电池直接输入验证 ADC 是否正常读数漂移严重激励电流源不稳定、参考电阻温漂大换 0.01% 精度低温漂参考电阻检查电流源配置寄存器热电偶读数误差大冷端补偿不准确用已知温度源校准内部温度传感器偏移量UART 偶尔丢字节波特率偏差、地线环路用示波器测波特率实际值检查通信地是否与功率地形成环路上电瞬时读数异常复位时序不满足加 RC 延时拉长复位后的等待时间长线传输时有偶发错误线缆未屏蔽、未加终端匹配改用双绞屏蔽线屏蔽层单端接地还有一个很实用的调试技巧我会在固件里留一个测试模式把四个通道的原始码值直接以十六进制格式通过串口打印出来。调试阶段先不看温度值只看码值的变化规律。码值稳定、单调、符合预期再开始做换算和标定。这样可以把问题定位在硬件还是软件省掉大量孤立故障的时间。4.4 几个让系统更稳的小技巧现场跑了一段时间后我总结了几个提升系统稳定性的小技巧不一定写在任何文档里但很管用。第一给每路传感器做合理性检查。比如冷冻水温度如果在冬天报出 60°C那就是异常数据。我在固件里对每个通道设置了上下限和变化速率上限超了就报故障而不是把错误数据发出去。HVAC 系统最怕的就是传感器失灵导致控制器做出错误动作数据合理性检查是第一道防线。第二CRC 校验一定要开。ADS122U04 支持 CRC 校验虽然在短距离板内通信中 CRC 出错的概率很低但一旦线缆老化或者环境干扰严重CRC 能让你识别坏帧而不是把错误数据当正确数据使用。我在 UART 通信协议里也加了简单的校验字段双重保险。第三参考电阻选型不能省。比例测量架构下参考电阻的温度稳定性直接影响测量精度。我用了 1kΩ、0.01% 精度、10ppm/°C 温漂的精密电阻价格不高但效果立竿见影。如果参考电阻温漂大数据手册写得再好的 ADC 也白搭因为参考是可以浮动的。5. 写在最后的几点体会这套方案做完之后我最大的体会是温度测量这种看起来很简单的项目真正决定成败的往往是那些不起眼的细节——布局布线、上电时序、参考电阻选型、滤波策略。ADS122U04 本身是一颗很优秀的 ADCPIC32MZ1024EFK144 也有充足的余量但把它们用好靠的还是对信号链的完整理解。我实测下来的整体性能是RTD 通道全量程误差在 ±0.15°C 以内热电偶通道在冷端补偿后误差 ±0.5°C 以内NTC 通道经过标定后也能做到 ±0.3°C 左右。对于 HVAC 控制这个领域这个精度已经相当充裕。如果你也在做类似的系统我的建议是先把信号链算清楚再动手画板拿到板子先写测试模式别急着写业务逻辑出了问题先怀疑硬件和布局最后才怀疑代码。这套方法论帮我少走了很多弯路希望也能帮到你。