搞工业现场的温度采集尤其是 HVAC 冷站和暖通空调设备里的多点测控我以前也是习惯用运放搭信号调理电路再进单片机自带的 ADC。直到前阵子做冷站控制项目改造传感器有几十路 PT1000还有一部分 K 型热电偶控制器用的是 Microchip 的 PIC18F86K22模拟采集方案最终换成了 TI 的 ADS122U04IPWR。这个组合看起来跨度挺大24 位 Δ-Σ ADC 加一颗 80 引脚的 8 位单片机很多同行第一反应是“8 位机是不是太老了”。我的回答一直是在工业和 HVAC 现场能用最简单可靠的方式把温度和通信做稳就是好方案。ADS122U04IPWR 这颗料本身就是冲着温度测量去的内部集成了可编程增益放大器、两个可编程激励电流源、2.048V 低漂移基准甚至还有一个芯片结温传感器用来做热电偶冷端补偿。和它配对之后PIC18F86K22 不需要再承担任何模拟信号调理的脏活只管通过 UART 接口配置 ADC、读结果然后把所有精力放到线性化、PID 控制、Modbus 通信这些东西上。这篇文章就当一次项目复盘从选型、硬件、固件到现场踩坑把这套方案从头到尾拆开讲清楚。1. 选型逻辑温度 ADC 搭配高端 8 位单片机的价值所在1.1 温度信号有多难采先看微伏级的物理事实很多人不理解为什么普通单片机的 ADC 测温度不够用问题不是位数而是信号幅度。以 PT100 为例0℃ 时电阻约 100Ω温度每升高 1℃电阻增加约 0.385Ω。如果用 1mA 激励电流对应的电压变化只有 0.385mV/℃。如果想让系统分辨出 0.01℃前端就需要能稳定分辨 3.85μV。再看热电偶更夸张K 型热电偶灵敏度大约 40μV/℃J 型大约 52μV/℃如果现场环境不好几十微伏的噪声就能吃掉一大截精度。常规单片机的 12 位 ADC参考电压按 3.3V 算一个 LSB 是 0.8mV对温度信号来说这个分辨率完全不够看。即便把前端运放增益拉高运放自身的失调电压温漂、零点漂移又成了新问题。ADS122U04IPWR 这类温度专用 ADC 解决的就是这个矛盾。24 位分辨率配合 PGA以增益 32 为例等效满量程只有 ±64mV理论 LSB 大约是 7.6nV完全覆盖温度传感器的信号基。当然实际有效位数受噪声限制不可能真的到纳伏级但做到 0.01℃ 级别的重复性和稳定性比用“运放普通 ADC”的离散方案靠谱得多。1.2 ADS122U04IPWR 自带哪些“温度测量外挂”这颗 ADC 最值得圈出来的几个资源我列成了表格做方案选型时可以直接对照内部资源功能对温度测量的意义4 通道模拟输入支持差分或单端输入可接多路 PT100/PT1000、热电偶可编程增益 PGA增益 1 到 128热电偶这类微伏信号也能有效放大两个 IDAC 电流源0.25mA 到 1.5mA 可编程给 RTD 提供激励省掉外部恒流源内部电压基准2.048V低漂移结合比例测量消除基准温漂内部温度传感器测量芯片结温配合热电偶做冷端补偿省一个外部温度芯片传感器断路检测Burn-out 电流源现场排查断线非常有用UART 串行接口命令/响应帧结构比 SPI 少了时序约束长线传输更稳其中 UART 接口是选择 ADS122U04IPWR 而不是 ADS1220 或者 ADS122C04 的主要原因。SPI 接口在板内短距离没问题但如果 ADC 板和控制器板是分开放置中间隔着几十厘米甚至更长的排线SPI 时钟线容易因为反射造成通信异常。UART 接口天生就是为跨板通信准备的两根线就能解决问题而且 PIC18 系列本身把 EUSART 外设做得很成熟115200 波特率下几乎不用调时序。1.3 PIC18F86K22 在这个系统里到底扮演什么角色一颗 80 引脚的 8 位单片机在今天看来好像有点“复古”实际上 PIC18F86K22 的外设资源非常充裕五个 EUSART、两个 SPI、两个 I2C、多个 16 位定时器、还有足够的 I/O 去控制继电器和读取面板按键。对于空调机组、冷冻站这类设备控制逻辑并不需要跑到 GHz 级更需要的是外设稳定、抗干扰强、工具链成熟。ADS122U04IPWR 负责把物理温度变成数字量PIC18F86K22 负责其余的批量工作通过 UART 与 ADS 通信管理配置寄存器和转换结果对原始码做比例换算、查表、多项式拟合得到工程单位温度值执行 PID 或者开关量控制逻辑通过另一个 UART 挂载 RS-485 收发器对外走 Modbus 协议驱动显示面板、蜂鸣器、故障指示灯处理看门狗和上电自检。如果把温度采集也塞给单片机裸跑模拟部分会占用大量开发时间而且环境一变精度就崩。芯片 ADS 把模拟难题封装好MCU 只做自己擅长的数字控制这是成熟工业产品的典型分层思路。2. 硬件搭建从前端传感器到 PCB 布局的完整思路2.1 ADS122U04IPWR 与 PIC18F86K22 的引脚级连接先画接口连接思路。ADS122U04IPWR 的串行接口是 UART 电平TXD、RXD 直接和 PIC18F86K22 的 EUSART1 对应交叉连接。数据就绪引脚 DRDY 这种信号不一定每个项目都接但我强烈建议接上否则就要靠轮询或者固定延时去读数据既浪费 CPU 又容易读到不完整的转换结果。ADS122U04IPWR 引脚方向PIC18F86K22 接线说明UART_TX输出接 EUSART1 的 RXADC 回传数据和寄存器内容UART_RX输入接 EUSART1 的 TXMCU 发送命令DRDY输出接 RB0 或任意外部中断引脚下降沿表示新转换数据就绪RESET输入接普通 I/O上电复位或软件复位AVDD/DVDD电源统一 3.3V模拟/数字电源分开走线再汇合AVSS/DGND地单点连接避免数字电流污染模拟地接 DRDY 的设计有一个实际好处PIC18F86K22 的外部中断可以在数据准备好时立刻读取不用去猜 ADC 到底转完没有。调试阶段如果你把 DRDY 悬空后续几乎一定会碰到“偶发读到一个中间值”的灵异问题。2.2 RTD 的比例测量接法RTD 温度测量我优先推荐比例法。原理不复杂让同一个 IDAC 电流同时流过待测 RTD 和一个高精度参考电阻RTD 上的电压送到 ADC 的模拟输入参考电阻上的电压作为 ADC 的基准输入。这样做的好处是IDAC 电流的温漂、电源电压的波动都会同时对 RTD 电压和参考电压产生影响而 ADC 测量的是两者的比值误差被天然抵消掉。这正是 ADS122U04IPWR 内部两个 IDAC 存在的意义。强烈建议参考电阻选温漂系数低的金属箔电阻或精密薄膜电阻阻值选 3.9kΩ 或者 4.02kΩ精度 0.1% 起步温漂 5ppm/℃ 以下。这个电阻的稳定性直接决定整个温度链路的最终精度不能随便在普通电阻箱里抓一个。四线制接线如图所示IDAC1 电流从 RTD 的一端流入从另一端流出回到 AVSS测量线直接并接在 RTD 两端采样回路没有电流流过所以导线电阻不影响测量结果。如果是两线制导线电阻会直接加进 RTD 阻值长距离布线时误差会很可观HVAC 现场能上四线就上四线。2.3 热电偶输入的微伏级信号保护热电偶输出的是微伏级直流信号最怕的是外界干扰串入。工程上我习惯在 ADC 输入引脚和热电偶端子之间加两级处理第一级是串联电阻限流每根线上串 10Ω 到 100Ω防止意外高压冲击烧毁芯片第二级是滤波电容差分位置放一个 100nF 的 C0G 电容每根线与 AGND 之间再放一个 1nF 到 10nF 的电容构成低通滤波器。这里有一个容易忽略的点热电偶是浮地信号探头外壳有时会碰到金属管道可能引入共模电压。如果现场接地系统比较复杂最好在 ADC 输入前加 TVS 管把共模电压钳位在安全范围内。我实测过一台变频器旁边的冷水机组不加保护时热电阻读数能上下跳 0.3℃加了差分电容和共模电容之后波动基本回到了 ADC 本身的噪声底附近。2.4 PCB 布局里的数字地和模拟地处理ADS122U04IPWR 这种混合信号芯片布局的核心思想是“不要把数字信号的回流电流赶到模拟回路里”。我的做法是把板子分成明显的模拟区和数字区。ADS 芯片和它周围的去耦电容、参考电阻、传感器端子全部放在模拟区PIC18F86K22、RS-485 收发器、电源模块放在数字区。两层板时模拟地铺一个完整区域数字地铺另一个区域最后在电源输入端的公共点位置做单点连接。别学那些把地平面整体一片铺完的做法看起来漂亮但是 PIC18F86K22 在大电流翻转 I/O 时产生的数字噪声会通过地平面直接灌进模拟区域ADC 的有效分辨率立刻打折扣。另外连接 ADS 模拟输入的前端走线尽量短而粗传感器线不要和 220V 强电线路走同一个线槽这在 HVAC 设备里尤其重要因为现场线束往往非常密。3. PIC18F86K22 侧固件初始化、寄存器配置与数据解析3.1 初始化 UART 与数字引脚先说 PIC18F86K22 这一侧的初始化。我的项目里 EUSART1 用于和 ADS 通信波特率选 1152008 数据位、无校验、1 停止位。代码示意如下void uart1_init_115200(void) { TRISC6 0; // TX1 输出 TRISC7 1; // RX1 输入 BAUDCON1 0x08; // BRG16 使能 SPBRGH1 0; SPBRG1 34; // 64MHz 系统时钟下 115200 对应的 SPBRG 值 TXSTA1 0x24; // 使能发送8 位数据 RCSTA1 0x90; // 使能接收8 位数据 }GPIO 方面DRDY 引脚配置为输入并打开内部上拉用外部中断或者轮询都可以。我的建议是用事件驱动数据就绪产生下降沿在中断里置一个标志位主循环看到标志再发起读取。这样不会因为 ADC 转换时间不定而阻塞主循环。3.2 ADS122U04IPWR 寄存器配置思路ADS122U04IPWR 与主机的交互是基于命令帧的配置寄存器和读取数据都通过 UART 完成。寄存器组分成 REG0 到 REG3 四个主要配置字节分别负责输入多路复用和增益、转换模式和数据速率、IDAC 与基准、以及传感器检测等选项。我给出一个典型的 PT1000 场景配置流程void ads_rtd_init(void) { ads_write_reg(ADS_REG0, 0x16); // AIN0/AIN1 差分输入PGA32 ads_write_reg(ADS_REG1, 0x24); // 连续转换模式数据速率 20SPS ads_write_reg(ADS_REG2, 0x10); // IDAC11mA电流从 AIN0 输出 ads_write_reg(ADS_REG3, 0x50); // 使用内部基准开启内部温度传感器 }其中的寄存器值具体配置需要按产品数据手册中寄存器位定义的顺序进行编排不同版本或不同测量模式会有变化。重点是思路先把输入通路选好再定增益接着确定电流源大小和流向最后选择基准源。顺序错了经常会出现“ADC 读数乱跳”或者“转换结果满量程”的假故障。如果是热电偶应用PGA 一般选 64 或者 128数据速率可以适当提高。冷端补偿方案是把 ADS 芯片自身的结温传感器读出来因为 ADS122U04IPWR 的芯片温度就是热电偶冷端温度只要有精度要求这个内部传感器能省掉一块外部 NTC 和对应标定。3.3 读取转换结果并换算成温度值转换后的数据是 24 位有符号整型读取时按命令帧把四个字节收齐再拼装成 int32_t。示意代码如下int32_t ads_read_conversion(void) { uint8_t buf[4]; int32_t raw; ads_send_command(ADS_CMD_READ_DATA); // 发起读数命令 uart_receive_bytes(buf, 4); // 接收 4 字节结果 raw ((int32_t)buf[0] 16) | ((int32_t)buf[1] 8) | buf[2]; // 24 位有符号数扩展 if (raw 0x800000) raw | 0xFF000000; return raw; }得到原始码之后最重要的换算公式来了。因为我使用比例测量RTD 电阻不是靠电压绝对值算的而是靠 ADC 码值和参考电阻的比值算R_rtd (raw / 0x7FFFFF) × R_ref其中 0x7FFFFF 对应满量程编码R_ref 就是那颗 3.9kΩ 精密电阻。算出电阻之后再根据 PT1000 或者 PT100 的 ITS-90 标准表进行线性化查表或者用 Callendar-Van Dusen 方程做多项式拟合牛顿迭代几轮就能得到温度值误差小于 0.01℃ 量级完全够用。3.4 与主控制逻辑融合拿到温度值之后剩下的活就交给 PIC18F86K22 的控制程序了。我的做法是温度采集模块独立成一个文件向上提供 get_temperature_channel(ch) 接口向下只依赖 UART 接收状态。这样写 PID 控制逻辑时不需要关心 ADC 内部状态调试时也能单独打印通道数据。为了增强现场稳定性I/O 处理里必须加看门狗。如果 ADS 长时间没有响应或者 DRDY 中断长时间不触发就让 MCU 重启并重新初始化 ADC。这类设备装到机房、屋顶、地下室之后往往几个月都没人去碰自动恢复能力比调试时的优雅更重要。4. 校准与精度提升把 24 位分辨率变成真精度4.1 实验室标定的基本套路ADS122U04IPWR 能做到很高的理论分辨率但“分辨率”和“精度”是两回事。现场装机之前我会在实验室里做一次完整的静态标定标准设备用恒温油槽或者干体炉配上级别足够的铂电阻温度计来读取真实温度。标定流程不复杂把待测通道接到标准铂电阻上传感器放进恒温槽从 -20℃ 到 120℃ 每隔 10℃ 取一个点每个点稳定 10 分钟以上记录 ADC 解算温度和标准铂电阻温度。最后做线性拟合并补偿偏移T_corrected a × T_raw ba 和 b 通过最小二乘法算出。这个偏移主要来自参考电阻精度和传感器个体差异不校正的话哪怕 ADC 线性度再好整体绝对误差也可能到 0.5℃ 以上。对 HVAC 控制来说0.5℃ 可能勉强能接受但如果是冷冻水出水和回水温差控制0.5℃ 的误差会直接让机组能效计算失真。4.2 热电偶冷端补偿的特殊处理K 型热电偶测量的是热端和冷端的温度差要把热端真实温度算出来必须先知道冷端温度。ADS122U04IPWR 自带内部温度传感器刚好可以让冷端补偿做在一块芯片内。实际工程里有个细节内部温度传感器测到的芯片结温不一定等于热电偶接线端子的真实温度因为芯片自身会发热PCB 周围也有器件散热。如果对补偿精度有高要求我建议把电路板上的热电偶端子靠近 ADS 芯片并且让 MCU 周边电路尽量远离热电偶端子减小热源干扰。同时可以单独在接线端子旁边贴一颗高精度 NTC 做冷端温度参考用两路温度取平均来减少热梯度误差。HVAC 现场还有个常见问题室外机组冬天可能夜间降到 -20℃控制柜内如果没有加热器PCB 温度会跟着骤降。ADS 芯片内部温度传感器虽然有标定但快速温度变化时热电偶端子和芯片之间可能出现动态温差导致开机电热偶读数异常。这种场景下建议在上电后等待几分钟等板内温度稳定后再启用热电偶补偿。4.3 数字滤波与统计处理即使模拟端做得再好工业现场也不可能是无噪声环境。我常用的滤波策略是“中值滤波 一阶低通”两级搭配中值滤波连续采集 5 个数据排序后取中间值物理含义是丢掉那些突然的尖峰毛刺一阶低通中值输出再过一个 IIR 滤波器加权系数根据响应速度需求来定比如 y 0.7 × y_prev 0.3 × x。这样处理后温度显示值的跳动量会明显收敛。代价是响应速度变慢所以像回水温度这种需要快速报警的场景我会把低通系数调大一些而像水箱温度这种大惯性对象则可以把系数调小一些滤得更深。有一点要提醒滤波是放在 ADC 原始码之后、PID 控制器之前做的不要只滤最终显示值。因为 PID 控制器内部用的温度如果带太多毛刺积分项会被反复冲刷导致阀门或压缩机的执行机构频繁动作。5. 现场踩坑复盘工业/HVAC 场景下必须注意的细节5.1 激励电流过大引起的 RTD 自热第一次硬件调试我图省事把 IDAC 设成了 1.5mA因为觉得电流越大信号越强、抗干扰越好。结果实测下来PT1000 在 25℃ 水浴里读数会持续缓慢上升等几分钟后稳定下来比真实温度高 0.2℃ 左右。原因很简单电流流过 RTD 会产生 I²R 热功率把传感器自身烧热了。PT1000 在 1.5mA 下的自热功率大约 2.25mW裸装热阻比较大的传感器足以造成明显温升。后来把激励电流降到 0.5mA读数和标准温度计的偏差明显缩小但同时噪声略有增加解决方案是适当增加 PGA 和滤波深度。所以 RTD 激励电流需要谨慎平衡电流太小信噪比不足电流太大自热严重。我的推荐起点是 PT100 用 1mAPT1000 用 0.5mA遇到封装比较大的传感器再往下调。5.2 共模干扰让有效位掉了不少项目第二阶段把样板装进冷站控制柜做测试。柜里同时有变频器、接触器、电磁阀一动作温度读数就周期性跳动。最初以为是电源不稳后来用示波器看 ADS 输入引脚波形发现是几十伏的共模尖峰从传感器长线耦合进来。排查思路做了三件事确认传感器屏蔽层单端接地不能两端接地形成环路在 ADC 输入和传感器端子之间增加共模短截滤波电容把 PCB 的模拟地和现场线槽的接地参考点理清避免地电位差直接加在传感器回路上。处理后同样工况下再测温度跳动从 0.3℃ 降到 0.02℃ 以内。这类问题在实验室很难复现只有设备真正靠近动力线时才会暴露所以设计前期就应该预留好滤波电容位置和屏蔽层接地柱。5.3 UART 通信“偶发乱码”的真相第三个坑出在通信链路。系统长时间跑下来偶尔会出现某个通道温度突然跳到几百度然后下一次转换又恢复正常。查了很久才发现问题不在 ADS 硬件而在命令帧处理UART 通信偶尔会有字节丢失或者错位如果固件没有做帧同步判断就会把残留的旧数据当成新数据组装。解决方法是完善帧协议和超时处理每个命令帧增加固定帧头和 CRC 校验接收数据时先找字节边界当接收长度和校验值不一致时丢弃整个帧并要求重发用定时器做超时判断DRDY 标志置位后超过 10ms 还没有收到完整数据就主动复位 UART 并重新初始化 ADS。这个改动看起来小但对长期运行稳定性影响巨大。 HVAC 设备往往要求全年无休地运行任何偶发性毛刺只要没有自动恢复机制最终都会变成凌晨三点被电话叫醒的售后事故。5.4 关于系统上电顺序和掉电保护最后补一个容易被忽视的上电顺序问题。ADS122U04IPWR 和 PIC18F86K22 共用 3.3V 电源如果系统断电瞬间 MCU 闪存还在写参数而 ADC 已经掉电复位之后配置寄存器可能处于不可预知的状态。我后来在固件里加了一个标志量每次上电都强制重新配置 ADS不做“沿用上次配置”的假设。另外如果要支持热插拔传感器建议开启烧毁电流检测或者定期检查通道是否断线现场维护人员经常拔错线一次误接可能把模拟输入口打坏。加一级 TVS 保护、加一个自恢复保险丝成本很低但能省掉大量返修成本。这套方案跑到现在机组冷热水温控制精度稳定在 ±0.1℃ 以内几十个通道的长期漂移也在可控范围。如果在项目里遇到类似需求不妨也试着把 ADS122U04IPWR 和 PIC18F86K22 组合起来先把模拟前端的问题交给专用芯片再让单片机专注做它擅长的控制逻辑。最后想提醒的是数据手册上的寄存器位定义一定要对着具体型号的最新版本反复核对哪怕只漏掉一个 IDAC 路由配置位现场调试也可能花掉你足足一下午。