做工业现场和 HVAC 项目的人肯定都跟“测温度”打过不少交道。最近我把一个温度采集模块从方案设计到样机调试完整做了一遍采集端用 TI 的 ADS122U04IPWR主控用 Microchip 的 PIC24EP512GU814目标覆盖工业设备状态监测和暖通空调水系统、风管测温精度做到 ±0.2℃ 这个级别。这套组合跑起来很稳中间踩了不少坑今天把关键设计、配置代码还有调试心得一次性整理出来给正在做仪表、传感器模块或者 HVAC 控制器的朋友参考。先说结论ADS122U04 这颗 24 位 ΔΣ ADC 最适合做“多传感器、现场分布、信号弱、地线乱”的测温节点PIC24EP512GU814 则负责把多路 UART、协议解析和逻辑控制扛起来。两者配合RTD、热电偶、NTC 都能覆盖而且用 UART 走线可以很轻松地把 ADC 放到传感器近端主控放在控制柜里工业现场的长线干扰问题直接砍掉一大半。1. 选型思路为什么是 ADS122U04 PIC24EP512GU8141.1 先解决“ADC 怎么接到 MCU”的问题很多新手选 ADC 先看位数觉得 24 位就是精度其实第一件事应该先想清楚接口。传统仪表方案常用 SPI 接口的 ADC比如 ADS1220四根线连到 MCU速度快是快但放到工业现场就麻烦一是线多隔离成本高二是距离一长时钟线和数据线的时序容易出问题三是 PCB 上占用的 IO 也多。我这次选 ADS122U04最大原因就是它把 SPI 换成了 UART。UART 只有 TX、RX 两根线没有时钟同步问题直接就能接数字隔离器或者光耦也适合做一条总线挂多个从机。对 HVAC 这种“控制柜和现场传感器距离几十米”的典型场景这个优势比多几位分辨率实在得多。1.2 四个让我决定用它的事实第一模拟前端集成度高。ADS122U04 内部有 PGA增益从 1 倍到 128 倍可调还有两个匹配电流源可以用来给 RTD 和热敏电阻做激励内部基准、内部温度传感器也都有。这就意味着常见的测温传感器基本不用加外围放大电路一个芯片直接伺候。第二UART 协议是命令-响应式的调试非常直观。用 USB-TTL 板子就能在电脑上先验证芯片是否正常再写 MCU 固件前后端分离开发效率高。第三电流源匹配度好。做三线制 RTD 引线补偿时两个 IDAC 电流源的匹配是关键指标这颗芯片的匹配特性在同类产品里属于靠谱的那档。第四多地址支持。通过 ADDR 引脚和帧里的地址字节可以多个 ADS122U04 挂同一条 UART 总线这是做多路温度采集很讨巧的方案。1.3 主控选 PIC24EP512GU814 的原因PIC24EP512GU814 是 Microchip 的 16 位工业级 MCU512KB Flash串口资源充足I/O 还能兼容 5V 逻辑和 ADS122U04 的 VIO 电平对接很方便。实际项目里我用它管三件事轮询 ADC 读数据、解算温度、通过另一路 UART 或者 RS-485 和上位机交互。如果只有一路串口调试口和数据口会打架所以 MCU 串口数量不能太少。另外这颗 MCU 在 -40℃ 到 85℃ 工业温度范围内跑得很稳HVAC 机组里环境不算好芯片自身可靠性反而比性能更要紧。2. 系统框架与硬件设计要点2.1 整体信号链路整个采集模块的思路可以简化成一条链路传感器RTD / TC / NTC→ 输入滤波与激励 → ADS122U04 内部 MUX PGA ΔΣ 调制器 → UART 输出 → 隔离器 → PIC24EP512GU814ADC 放在传感器近端MCU 放在控制侧中间过隔离。这样做的好处是模拟小信号不会长途跋涉穿过整个机柜那些几十米的补偿导线只走 UART 数字信号干扰容限完全不同。2.2 RTD 接口比例测量是精度灵魂测 PT100 这类电阻型传感器我最推荐四线制比例测量。原理不复杂用一个电流源给 RTD 供电同时让同一股电流流过一颗精密参考电阻 RREFADC 参考电压取自 RREF 两端测量电压取自 RTD 两端。因为电流完全一样比例计算时电流源的大小会被消掉参考电压的绝对精度也不影响结果。四线制的接法很简单IDAC 电流从激励正端流出经过一根引线到 RTD再从另一根引线回流回流路径上串 RREF产生参考电压。RTD 两端再用两条独立的采样线接到 ADC 的差分输入端。采样线上几乎没有电流所以引线电阻不会产生压降误差。最终换算公式非常干净RRTD RREF × CODE / (Gain × 2^23)这里的 CODE 是 ADC 输出的 24 位有符号原始码2^23 对应双极性输出满量程。具体参数我建议先算再填。比如我用 1mA 激励、RREF 选 200Ω、增益设 10℃ 时 RRTD≈100ΩCODE 大约是满量程的一半100℃ 时 RRTD≈138.5Ω都还没碰到满量程线性区间很舒服。如果你想把量程拉到几百摄氏度就把 RREF 换成 430Ω 或者 500Ω或者把激励电流降到 250µA务必保证最高温度时 CODE 不会顶到满量程。三线制则是另一种常见折中两个 IDAC 设置成相等电流一个走激励线一个走远端采样线让两条引线上的压降在差分输入里互相抵消。这个方法最怕电流源失配比如 0.1% 的失配乘以 5Ω 引线电阻残余误差只有 5mΩ对 PT100 来说大约 0.013℃完全可以接受。而二线制就惨了两段引线一共 2Ω直接折算出 5.2℃ 的误差工业现场基本没法用。2.3 热电偶输入与冷端补偿设计热电偶输出的是微伏级直流电压K 型大约 40µV/℃。这种信号必须靠 PGA 放大但增益不是越大越好要先算满量程。K 型热电偶在 1000℃ 的输出约 41mV如果参考电压取内部 2.048V增益 32 对应的满量程是 64mV合适增益 64 对应 32mV到 750℃ 左右就会削顶。所以我的做法是主要测几百摄氏度的用增益 32只测 HVAC 里几百度以内的管道表面温度用增益 64 分辨率更好。冷端补偿是热电偶的常态问题。ADS122U04 内置温度传感器可以做粗略补偿标称精度够日常暖通监控用但要做到 ±0.2℃ 系统精度我建议把外部 PT100 或者 NTC 贴在端子排附近用同一个 ADC 通道轮询去测冷端温度再叠加到热电偶电压上。关键是传感器要真正贴近热电偶接入端子离远了或者被发热元件烤到补偿值就失去了意义。输入滤波这里有个容易踩的坑热电偶源阻抗高外部 RC 滤波电容不能太大。我用的是 1kΩ 电阻加几纳法电容同时把 ADC 的数据速率调到 20SPS让内部 SINC 数字滤波器承担主要的 50/60Hz 工频抑制。电容选太大采样建立时间不够反而会出现非线性误差。2.4 UART 隔离与现场接线ADC 和 MCU 之间过隔离是工业现场测温的高性价比操作。UART 两线制隔离成本很低两颗数字隔离器芯片或者一对高速光耦就能解决。我用的隔离器数据率余量留到 1Mbps 以上跑 115200 波特率非常从容。接线距离超过几米时建议把波特率降到 57600 甚至 9600并采用双绞线。不要图快测温数据的采样率本来就在 20SPS 这个量级串口波特率再高意义也不大稳才是第一位的。3. ADS122U04 的 UART 协议与寄存器配置3.1 命令帧与通信流程ADS122U04 的 UART 协议是典型的命令-响应式。MCU 发命令字节ADC 回数据或状态。常用命令如下表命令命令字节用途NOP0x00空操作可用于确认链路RESET0x06复位芯片RDATA0x12读出一次转换结果返回 3 字节RREG0x20 寄存器地址读寄存器WREG0x40 寄存器地址写寄存器随后紧跟要写入的数据上电后不能马上发命令我一般先延时 100ms让内部基准和电源稳定再发 RESET随后读一下寄存器确认链路正常。如果返回全 0xFF 或者一直没响应先查波特率、TX/RX 是否接反、VIO 电平是否匹配这三项。3.2 寄存器配置模板我把常用配置封装成两个函数一个读寄存器一个写寄存器static uint8_t ads_read_reg(uint8_t reg) { uart_write_byte(ADS_RREG | reg); return uart_read_byte(); } static void ads_write_reg(uint8_t reg, uint8_t val) { uart_write_byte(ADS_WREG | reg); uart_write_byte(val); }接下来是 RTD 场景的初始化模板。CONFIG0 的 [3:1] 位是 PGA 增益[7:4] 位是输入 MUX默认 AIN0/AIN1 正好是我要的差分输入所以增益设 1 时整个寄存器就是 0x00void ads_rtd_init(void) { uart_write_byte(ADS_RESET); delay_ms(10); // CONFIG0默认 MUXAIN0/AIN1增益1 ads_write_reg(0, 0x00); // CONFIG1默认就是连续转换模式 20SPS50/60Hz 抑制按手册位域配置 ads_write_reg(1, 0x00); // CONFIG2IDAC 激励电流设成 1mAIDAC1/IDAC2 按三线制或四线制接法路由到对应引脚 // 具体位域值直接查手册 Table不要盲抄网上代码 ads_write_reg(2, IDAC_SETTING); // CONFIG3使能内部基准温度传感器按需开启 ads_write_reg(3, REF_SETTING); }热电偶场景无非是换 CONFIG0 的增益值。增益 32 对应 CONFIG0 0x0A增益 64 对应 0x0CMUX 保持 AIN0/AIN1 就可以。3.3 连续转换和单次转换怎么选连续转换模式的好处是数据随时来随时读适合单路固定测量固件逻辑简单。但如果你在一条 UART 总线上挂多个 ADC或者一个 ADC 要轮询多个通道单次转换模式会更省心发一次启动命令等待转换完成读一次数据再切下一路。这样每读一次数据都对应一个明确的采样时刻不会出现“读出来不知道是什么时候的旧数据”这种尴尬情况。通道切换后要特别注意MUX 切过去之后内部模拟滤波器和数字滤波器都需要时间稳定我一般是丢弃切换后的前两个采样点再取有效值。4. PIC24EP512GU814 固件实现4.1 串口初始化和基础驱动PIC24EP 的串口初始化不复杂。时钟配置我在 MPLAB Code Configurator 里生成假设系统外设时钟 Fcy 40MHz。UART1 用高速模式波特率 115200寄存器计算式为UxBRG Fcy / (4 × Baud) - 1按公式算出来 86实际波特率约 114.9kbps误差 0.2%串口通信完全没问题。AD 采集本来就不是高波特率场景这点偏差无感。#define Fcy 40000000UL void uart1_init(unsigned long baud) { U1MODEbits.BRGH 1; U1BRG (unsigned int)((Fcy / (4UL * baud)) - 1UL); U1MODEbits.ON 1; U1STAbits.UTXEN 1; U1STAbits.URXEN 1; } void uart_write_byte(uint8_t b) { while (U1STAbits.UTXBF); U1TXREG b; } uint8_t uart_read_byte(void) { while (!U1STAbits.URXDA); return U1RXREG; }4.2 与 ADS122U04 交互的核心代码读取三字节转换结果并做符号扩展#define ADS_RESET 0x06 #define ADS_RREG 0x20 #define ADS_WREG 0x40 #define ADS_RDATA 0x12 int32_t ads_read_code(void) { uint8_t b[3]; int32_t raw; uart_write_byte(ADS_RDATA); b[0] uart_read_byte(); b[1] uart_read_byte(); b[2] uart_read_byte(); raw ((int32_t)b[0] 16) | ((int32_t)b[1] 8) | b[2]; if (raw 0x800000) raw | 0xFF000000; // 24 位补码扩展成 32 位 return raw; }把原始码换成电压和电阻float adc_code_to_voltage(int32_t code, float vref, float gain) { return (float)code * vref / (8388608.0f * gain); } float rtd_resistance(int32_t code, float rref, float gain) { return rref * ((float)code / (8388608.0f * gain)); }注意比例测量里如果 RREF 和 RTD 串在同一电流回路里电阻公式里应该保留 Gain 项因为 PGA 放大的是输入信号不是参考电压。这一点很多例程代码会搞错算到 100℃ 以上偏差就明显了。4.3 温度换算PT100 反算公式PT100 在 0℃ 以上用 Callendar-Van Dusen 方程足够二次方程反解温度即可R(T) R0 × (1 A×T B×T²)其中 R0100ΩA3.9083e-3B-5.775e-7。反解公式为T (-A sqrt(A² - 4×B×(1 - R/R0))) / (2×B)固件里这么写#include math.h float pt100_temp_from_resistance(float r) { const float R0 100.0f; const float A 3.9083e-3f; const float B -5.775e-7f; float disc A * A - 4.0f * B * (1.0f - r / R0); return (-A sqrtf(disc)) / (2.0f * B); }0℃ 以下要引入 C 项R R0×(1 A×T B×T² C×(T-100)×T³)C-4.183e-12。这个方程没法直接反解我习惯用牛顿迭代逼近八次左右就能收敛到 0.001℃ 以内。工程上另一种更省事的办法是直接查分度表但表格会占用不少 Flash在 PIC24EP 这种 512KB 的 MCU 上问题不大。4.4 多通道轮询与故障判断完整系统里我不可能只测一路。PIC24 的主循环按固定周期轮询各通道先把 MUX 切到目标传感器等待稳定读 CODE换算再进下一路。ADC 的原始码还能用来做传感器开路判断RTD 断线时输入会被拉向参考电压CODE 会直接冲到满量程附近热电偶断线同样是这个表现。我就在固件里设了一个阈值超过量程的 98% 就报传感器故障省掉了外部开路上拉电阻。5. 校准过程与实测结果5.1 两步校准偏移和增益任何 ADC 采集链路都躲不过校准我的流程固定分两步。第一步是零点偏移校准。把 ADC 两个输入短接读一次 CODE 存起来之后每笔数据都减掉这个偏移。RTD 场景下偏移校准用一颗精密短路插头替代传感器就行。第二步是增益校准。拿一颗 0.01% 精度的 100Ω 电阻替代 PT100给系统一个已知激励反推增益修正系数。把这个系数存到 MCU 的 EEPROM 或者 Flash 配置区出厂前每块板做一次能抹平参考电阻初始误差的大部分。参考电阻本身我也花了心思用了 0.1% 精度、温漂 10ppm/℃ 级别的金属箔电阻。虽然贵一点但测温系统误差的大头往往不在 ADC 位数而在参考电阻和高低温漂端子上。5.2 实测数据表校准完在恒温槽里做的对比以实验室标准铂电阻温度计为基准结果如下标准温度实测温度偏差波动范围0.00℃ 冰点槽0.02℃0.02℃±0.01℃25.00℃ 恒温槽24.97℃-0.03℃±0.02℃60.00℃ 恒温槽60.04℃0.04℃±0.02℃100.00℃ 沸水槽100.09℃0.09℃±0.03℃整套下来最大偏差 0.09℃重复性 ±0.03℃满足 HVAC 水系统测温通常要求的 ±0.2℃。热电偶通道因为存在冷端补偿误差全量程大约在 ±0.3℃做工业表面温度监测足够但别指望它代替 RTD 做高精度控制。5.3 影响系统精度的隐藏因素有几次精度怎么调都调不上去最后发现问题根本不在 ADC。第一次是 PCB 上 AIN 走线旁边躺着一个 DC-DC 电感纹波直接灌进了输入挪开走线噪声立刻小了一个数量级。第二次是接线端子的两种金属材质不同形成了寄生热电偶端子附近温度一变读数就跟着漂。第三次是 ADC 芯片底下有个大面积敷铜散热 pad芯片自身功耗让局部温度升温影响内部基准和温度传感器读数。这些都不在数据手册的“典型性能曲线”里只能靠现场排查。做精密测温PCB 布局和结构件设计往往比软件算法更影响最终结果。6. 常见问题与排查技巧实录6.1 一张问题速查表现象可能原因对策UART 完全无响应波特率不对、TX/RX 接反、VIO 电平不匹配用 USB-TTL 先单独验证 ADC再查 MCU 串口配置上电后第一次读数异常芯片还没完成复位和基准建立上电后延时 100ms 再发 RESET复位后再次延时读数跳变大工频干扰、隔离电源纹波、布线靠近开关器件开 50/60Hz 抑制滤波器改用双绞屏蔽线隔离电源加 LDO零点漂移越来越明显端子热电势、PCB 铜箔和焊锡热电势尽量选用同种金属端子冷端传感器贴近端子切换通道后第一笔数据不准数字滤波器还没稳定切换后丢弃前两个采样点阻值计算在高程偏差大忽略了 Gain 项或者参考电阻温漂大核对公式检查 RREF 温漂并做软件修正6.2 我印象最深的三次排障第一次是数字隔离器选型失误。一开始用了便宜的普通光耦跑到 115200 波特率低速时还凑合数据一连续传输就时不时丢字节。后来换成一款传输延时几十纳秒的数字隔离器问题彻底消失。教训是隔离器别只看能跑多少 MHz要关注单位时间内的字节连续性。第二次是冷端传感器位置。我把外部 PT100 直接贴在了 PCB 靠近 ADC 的位置结果读数比端子实际温度高了两三度因为 ADC 自身发热把 PCB 局部烤热了。后来把冷端传感器挪到接线端子根部用导热胶固定偏差才压回来。第三次是 RTD 激励电流引发的自热。用 1mA 给 PT100 测量时问题不大100Ω 上只有 0.1mW但同一套板子去测 10kΩ NTC1mA 就是 10mW在静止空气里能把自己加热出好几摄氏度。HVAC 的 NTC 通道我最后把激励电流降到了 100µA功率降到 0.1mW自热误差才可接受。6.3 常规文档不会写的避坑经验不要迷信 24 位。24 位指的是输出位数不是有效分辨率。20SPS 档位、增益 128 时有效分辨率可能只到 17、18 位但配合多次平均做 0.1℃ 分辨率的温度测量完全够用。PCB 上模拟电源和数字电源要分开走单点汇接。我第一版板子省事模拟和数字共用一条电源轨结果噪声指标差了快一倍。所有长走线都按“电流从哪里去、从哪里回”的思维梳理。RTD 的激励线和回流线要尽量靠近减少环路面积。固件里做个简单的自检机制每 N 次采样插入一次内部温度传感器读取用于长期漂移监控。这个功能平时不起眼客户现场说“仪表不准了”的时候能帮你快速定位是 ADC 漂了还是环境变了。7. 后续扩展与个人体会这套方案后续我很想再往下走一层用多个 ADS122U04 挂同一条 RS-485 总线每个 ADC 负责一个测温点PIC24EP 只做集中管理把“分布采集、集中处理”的架构做完整。UART 转 RS-485 非常自然成本也不高对 HVAC 这种几十个温度点的大型系统很合适。最后说点个人体会。做测温项目最容易犯的错就是只看 ADC 数据手册上的 ENOB 和噪声指标然后把所有希望押在位数上。实际调试下来发现最磨人的永远是参考电阻的温漂、端子上的寄生热电动势、PCB 布局里的电源耦合、以及长线带来的共模干扰。ADS122U04 和 PIC24EP512GU814 这套组合给了我很好的起点但真正的精度是一点点“抠”出来的。如果正在做类似设计的朋友遇到照着文章还调不通的情况先别怀疑芯片拿 USB-TTL 把 ADC 单独接到电脑上逐项排除 MCU 固件、硬件布线、传感器接线问题一般会浮出来。