
做 HVAC 控制柜的朋友应该都有过这种经历风道里的 PT100 信号想送进控制器距离稍微一长模拟线缆就开始给你颜色看。我之前一套方案用的是 SPI 接口的高精度 ADC传感器板和主控板分开板间靠 5V 供电加时钟线连接结果上电一次掉线一次干扰进来之后数据直接起飞。后来换成 TI 的 ADS122U04IPWR一颗 24 位 Δ-Σ ADC直接用 UART 口和单片机说话再配上手上的 STM32F732IE整套温度测量链路才算真正稳下来。这篇文章就是把我在工业与 HVAC 温度测量项目里用这两个芯片的过程拆开写一写。适合正在做温度采集、传感器变送器、控制器模拟量输入通道的嵌入式工程师尤其是被长线干扰和接地问题折磨过的人。文章不打算复述数据手册只讲实际选型时怎么想、硬件怎么接、固件怎么写、误差怎么控最后把调试现场踩过的坑也一并列出来。1. 从现场倒推选型为什么温度采集链路偏偏要这样搭1.1 工业与 HVAC 的温度精度预算先说一个容易被忽略的事实HVAC 和工业过程控制对温度测量的要求完全不一样。HVAC 里风道温度、回水温度通常做到 ±0.5°C 就能交差重点看长期稳定性和成本。工业过程控制就不一样了很多场合要做到 ±0.1°C 的重复性甚至要求分辨率能分辨 0.01°C 的变化。这个差距直接决定了 ADC 位数和传感器类型的选择。以 PT100 为例0°C 时电阻 100Ω100°C 时电阻 138.5Ω灵敏度大约 0.385Ω/°C。如果用 1mA 恒流源激励温度每变化 1°C传感器两端电压只变化 385µV。想分辨 0.01°C等效电压分辨率就要到 3.85µV。16 位 ADC 在 2.048V 基准、8 倍增益下一个 LSB 大约 3.9µV理论上刚刚够但实际噪声一大就基本看不出来。换成 24 位 ADC满量程对应的 LSB 电压小了几个数量级虽然受噪声限制达不到理想分辨率但至少在量化级别上不会拖后腿。工业现场还有 50Hz 工频干扰、变频器谐波、大电流电缆耦合这些问题所以 ADC 的差分输入、PGA 增益和内置数字滤波器比单纯“位数高”更关键。这也是我最后选 ADS122U04IPWR 而不是随便一颗高精度运放加 MCU 内置 ADC 的原因集成度高前端调理电路省了一大半。1.2 ADS122U04IPWR 的看家本领以及“UART 接口”意味着什么ADS122U04IPWR 这颗芯片从型号上就能看出它的定位ADS1220 的 UART 版本。内核还是 24 位 Δ-Σ 调制器带 PGA、内部基准、两个可编程激励电流源 IDAC还有一路内部温度传感器工作温度范围覆盖 -40°C 到 125°CTSSOP-16 封装工业环境完全够用。它和常见的 ADS1220 最大区别就是把 SPI 口换成了 UART 口。别小看这个接口变化现场用起来差别非常大。SPI 需要 CLK、MOSI、MISO、CS 至少四根线时钟频率高、沿沿锋利稍微拉长一点距离就变成一根天线。UART 只需要 TX、RX 两根线异步协议不需要时钟同步电平速度可以压得很低配合数字隔离器、光耦甚至 RS-485 收发器都非常自然。对比项SPI 版 ADCUART 版 ADS122U04信号线至少 4 根2 根板间距离短距离为主适合分离式安装隔离方案隔离 SPI 麻烦光耦/数字隔离器顺手抗共模干扰依赖时钟质量异步帧更抗振铃另外一个实际收益是代码逻辑简单。SPI 时序要盯着 CS 和时钟沿而 UART 只要波特率对齐、按手册发命令字节剩下的交给串口中断和 DMA。对工程师来说少一块调试时间就是实打实的成本。1.3 STM32F732IE 在链路里承担什么活STM32F732IE 在我这套系统里不是单纯“读 ADC”的工具它要做的事情包括驱动两路 ADS122U04 轮询采集、做 PT100 线性化、热电偶冷端补偿、数字滤波以及把最终温度值通过 MODBUS 或一路 DAC 送到上层控制器。这些运算在一个 Cortex-M7 内核、主频 216MHz 的芯片上根本不费力FPU 处理浮点线性化公式非常快。选型时我更看重两点。第一STM32F732 的 USART 外设带分数波特率发生器115200 这种常用波特率可以做到几乎没有误差和 ADS122U04 对接时不容易出现帧错误。第二它有足够多的 UART 通道每个 ADS122U04 独占一路串口非常合适避免多片设备在一条总线上排队。工业级温度范围也让整个控制板不用为“商用级芯片在夏天机柜里死机”这种事操心。2. 传感器侧的真实接法RTD 激励、热电偶冷端与参考电阻2.1 四线制/三线制 RTD电流激励怎么抵消导线电阻RTD 本身是无源电阻元件必须有电流流过才能产生测量电压。ADS122U04 内置两个 IDAC 恒流源可以配置成 0.25mA 到 3mA这就是给 RTD 供电用的。激励电流越大信号电压越强但自热效应也越明显。PT100 在 1mA 激励下 100°C 时功耗只有 0.14mW自热影响基本可以忽略所以我通常优先用 1mA。接线方式直接影响测量精度。两线制最省线但导线电阻会直接叠加到 RTD 电阻里50 米线用 0.5mm² 铜线单趟电阻可能有 2Ω误差折算成温度超过 5°C完全不能接受。四线制最准两根线给 RTD 送电流另外两根线专门做电压检测电压检测线上几乎不流过电流导线压降进不了测量回路。问题是四线制探头成本高、现场接线容易错。三线制是工业和 HVAC 最常见的折中方案。它的思路是让两条电流线的压降尽可能出现在共模位置差分输入把它们消掉。实际接法我建议直接参考 TI 关于 RTD 测量的应用笔记里面有 IDAC1、IDAC2 和参考电阻的完整拓扑。我这里只强调设计目标任何接法只要让检测回路不承载激励电流或者让线阻压降以共模形式出现就是对的。2.2 比例式测量为什么我用外部参考电阻而不是内部 2.048VADS122U04 内部有 2.048V 基准电压很多朋友上来就把它用作 ADC 参考接线也简单。但这里藏着一个误差源激励电流源 IDAC 是有温漂和初始误差的如果激励电流变了RTD 上的电压就变了而 ADC 参考电压还是那个稳如泰山的 2.048V最终读数自然跟着电流一起漂。比例式测量可以把这个误差干掉。做法是在外部放一颗精密参考电阻 RREF让 ADC 的基准电压直接取自 RREF 上的压降VREF I × RREF。RTD 电压 VIN I × RRTD两个电压都受到同一个电流 I 的影响相除之后电流项抵消。理想情况下即使 IDAC 电流随温度变化了ADC 输出码也基本不变因为分子分母是同步缩放。比例式测量下的换算公式非常干净R_RTD CODE × RREF / (2^23 × G)其中 CODE 是 24 位有符号转换码G 是 PGA 增益。RREF 的选取原则是让激励电流和传感器量程匹配同时参考电压不能超过器件允许范围。比如 PT100 测 0~150°CRREF 取 1.8kΩ1mA 电流下 VREF 1.8V离满量程还有余量比较稳妥。2.3 热电偶冷端补偿与内部温度传感器的配合如果用热电偶事情会稍微绕一点。热电偶输出的是热端和冷端的温差电动势冷端温度必须补偿回来否则读数直接偏几度。ADS122U04 内部集成了一个温度传感器可以作为冷端温度的来源省去外接热敏电阻的通道。但要注意一点内部温度传感器测的是芯片封装内部温度只有当热电偶接线端子、等温块和芯片距离很近、热平衡做得足够好时这个读数才能代表真实冷端温度。冷端补偿公式如下T_hot T_cold V_tc / S_tcV_tc 是热电偶的输出电压S_tc 是该温度点的塞贝克系数K 型热电偶大约 41µV/°C。ADC 侧要用高增益去放大小信号比如 PGA 设成 32 或 64。冷端温度本身建议在固件里再做一次平滑滤波因为芯片温度会受到自身功耗和周围发热元件影响直接拿去补偿热电偶会让输出跟着抖动。工业过程控制里如果要求冷端补偿精度更高我建议在等温区加一颗外置精密 NTC 或数字温度传感器而不是依赖芯片内部温度传感器。HVAC 这种精度要求低的场合用内部温度传感器就够。2.4 输入端的 RC 滤波和 ESD 保护传感器探头挂在设备外面线缆长、干扰大、还可能被师傅拿螺丝刀碰一下。ADS122U04 的输入引脚不能裸奔。我每一路差分输入都加了串联电阻和差分电容电阻取 1kΩ电容取 100pF 到 1nF既能抑制射频干扰又能和 ADC 内部的采样结构一起构成抗混叠滤波。ESD 保护也不能省。工业线缆很容易感应静电TVS 二极管选结电容小的型号并联在差分输入和地之间。要注意 RC 滤波器的截止频率不能太低否则传感器信号建立时间会变长。配置完 PGA 之后最好等一下 RC 充放电至少留出几十毫秒再启动转换。3. 固件接入的第一步读懂 ADS122U04 的 UART 协议与配置流程3.1 上电后的三次握手波特率对齐、复位等待、DRDY 确认ADS122U04 的 UART 接口乍一看和普通串口外设没区别但直接上电就发命令往往会失败。原因有两个第一ADC 上电复位需要时间MCU 如果在上电瞬间就发命令ADC 根本没准备好第二ADS122U04 的波特率来自内部配置寄存器上电默认值和你在固件里想用的值不一定一致。我在这套系统里的做法是给 ADS 上电后先等待 10ms让它完成内部上电复位然后连续发送三次复位命令把芯片拉到确定的初始状态接着等待 DRDY 引脚产生有效信号确认 ADC 已经进入可接收命令的状态。只有完成这一步后面写配置寄存器才有意义。这里要特别提醒DRDY 引脚是 ADC 的“心跳”它在转换完成时产生下降沿或脉冲。如果不确认 DRDY 就直接发读数据命令轻则读到上一次的旧数据重则把数据流和命令流混在一起整个解析都乱掉。我建议无论用不用中断DRDY 都必须接一个空闲 GPIO 或 EXTI。3.2 CONFIG0 到 CONFIG3 的配置决策表ADS122U04 有四个主要配置寄存器我用一张表总结一下每个寄存器控制什么以及我在实际项目里是怎么填的。具体的位域编码请以数据手册和官方配置工具为准这里只讲功能决策。寄存器我要设置的内容决策依据REG0AIN0/AIN1 差分输入差分模式抗共模干扰比单端稳妥REG1PGA 增益、转换模式、数据速率RTD 信号约 0.1~0.5VPGA 8 倍增益合适REG2外部参考、IDAC 路由、低侧开关用 RREF 做比例测量IDAC1 接 RTD 高端REG3IDAC 电流大小、内部温度传感器电流取 1mA自热和信号幅度平衡传感器不同这套配置也要跟着改。测热电偶时 REG1 的 PGA 要调到 32 或 64REG3 里 IDAC 电流可以关掉因为热电偶不需要激励内部温度传感器要打开因为冷端补偿要用。测热敏电阻时激励电流可以降到 0.25mA 或 0.5mA以免大电流让 NTC 自身发热改变阻值。3.3 单次转换与连续转换的选择逻辑ADS122U04 支持单次转换和连续转换。单次转换模式下主机发一个 START 命令ADC 做一次转换完成后 DRDY 拉低主机读走数值ADC 回到等待状态。连续转换模式下ADC 按设置的数据速率反复转换DRDY 周期性出现主机需要持续读走结果。我的 HVAC 项目使用的是单次转换模式原因是系统里有两片 ADS122U04 和多路温度通道单次转换便于分时轮询。每次启动一个通道等 DRDY读数据换下一个通道时序都是确定的不会出现连续模式下“上一次还没读走下一次转换已经结束”的粘包问题。连续模式适合只测一个点、要非常平滑且不想频繁和芯片握手的场合。但连续模式有个隐藏问题如果主机被中断任务拖住长时间没读数据ADC 内部数据寄存器会不断更新你最终拿到的是“最近一次”转换结果而不是某一时刻的采样值。做实时控制时要小心。3.4 一段贴近实际的初始化代码结构驱动代码的细节每家主控不一样但流程是一致的。我习惯写一个小的配置封装功能逻辑如下static void adc122u04_write_reg(uint8_t reg_addr, uint8_t value) { /* WREG 命令先发命令字节再发寄存器地址然后发数据字节 */ uart_send_byte(WREG_CMD); uart_send_byte(reg_addr); uart_send_byte(value); } static void adc122u04_init(adc_cfg_t *cfg) { adc122u04_reset(); delay_ms(10); /* 配置寄存器语义位级编码见芯片手册 WREG 命令表 */ adc122u04_write_reg(REG_CONFIG0, cfg-mux); adc122u04_write_reg(REG_CONFIG1, cfg-pga | cfg-conv_mode | cfg-data_rate); adc122u04_write_reg(REG_CONFIG2, cfg-vref | cfg-idac_routing); adc122u04_write_reg(REG_CONFIG3, cfg-idac_current | cfg-int_temp_sensor); adc122u04_start(); while (!adc122u04_drdy_ready()); }看到这里可能有朋友觉得奇怪为什么代码里没有具体的寄存器数值因为 UART 版和 SPI 版在命令编码上有区别位数、命令字节格式都不同我不想在文章里写错。实际项目里我会打开 TI 官方数据手册的 WREG 部分把每个寄存器的位域定义做成宏再用宏拼出上面的 cfg 字段。前面那个 cfg 配置结构体虽然看起来像固件 API但真正目的是把配置流程讲清楚。4. STM32F732 侧的采集节奏与温度换算从 ADC 原始码到摄氏度4.1 UART DMA EXTI 的低延迟采集状态机主控这边我采用 UART 空闲接收加 DMA 的方式。ADS122U04 每次转换完成会产生一个 DRDY 下降沿用来触发 STM32F732 的外部中断。在中断里启动一次 DMA 接收把数据帧搬进内存然后立刻回主循环做解析和换算。这样做的好处是CPU 不用忙等串口逐字节接收也不容易在串口中断里被高优先级任务打断导致丢数据。采集状态机大概长这样空闲状态发 START 命令等 DRDYDRDY 到达后启动 DMA 接收DMA 完成后挂起一个标志主循环在时间片里处理数据。每片 ADS122U04 的 DRDY 都用单独的 EXTI 线互不相扰。如果 ADC 返回纯 24 位数据DMA 接收长度设为 3 字节如果开了状态字节就按 4 字节接收。这个要和自己配置的寄存器一致。4.2 原始码到电阻值的完整公式推导ADS122U04 的转换码是 24 位有符号数差分输入在正满量程时对应约 2^23 - 1负满量程对应约 -2^23。拿到 raw 之后先转成有符号 int32再代入公式。比例式测量的最终公式是R_RTD (CODE / 2^23) × (RREF / G)CODE 是有符号码G 是 PGA 增益。这个公式比“电压法”省一步因为参考电压和激励电流的原始值都被约掉了。举个例子G 8RREF 1.8kΩPT100 在 0°C 时 RRTD 100Ω那么 CODE RRTD × 2^23 × G / RREF 100 × 8388608 × 8 / 1800 ≈ 3728269。也就是大约 3.7M 码。同条件下每 0.01°C 对应的电阻变化约 0.00385Ω换算成码值变化大约 140 码。所以 24 位的量化空间绝对够真正的瓶颈在噪声。4.3 PT100 的 Callendar–Van Dusen 反解得到 RRTD 之后下一步是把电阻换成温度。PT100 在 0~100°C 范围内可以简化用二次方程描述R R0 × (1 A×T B×T²)其中 R0 100ΩA 3.9083e-3B -5.775e-7。反解这个二次方程取正根static double pt100_resistance_to_temp(double r) { const double R0 100.0; const double A 3.9083e-3; const double B -5.775e-7; double a R0 * B; double b R0 * A; double c R0 - r; double disc b * b - 4.0 * a * c; if (disc 0.0) { return -999.0; } return (-b sqrt(disc)) / (2.0 * a); }这个函数在 0~100°C 区间内和 IEC 60751 精度基本吻合。如果测温范围扩展到 -200°C就要用带 C×(T-100)×T³ 的完整分段公式建议直接查表插值避免浮点二次方程在低温段失真。4.4 软件滤波策略既要平滑又不能拖慢回路ADC 虽然标了 24 位但实际有效分辨率受噪声限制。我在 330SPS 数据速率下实测G8 时原始码跳动有十几个 LSB直接拿去给 PID 用会抖到没法看。常见的补救办法是软件滤波。我用的是“五点滑动平均 一阶低通”组合。滑动平均把高频毛刺压掉一阶低通把剩余噪声再削一层。一阶低通系数 alpha 取 0.1 到 0.3 之间alpha 越小越平稳但响应越慢。HVAC 风道温度变化本身不快alpha 取 0.2 效果不错如果是工业过程快速升温alpha 可以调到 0.5避免滤波成“慢半拍”。提示滤波不是越多越好。PID 回路里额外叠加纯滞后和低通滤波会降低相位裕度搞不好会自激振荡。滤波参数要和温度变化速率匹配。5. 不准的话先别怪 ADC把误差源一项项拆出来5.1 ADC 自身的噪声、失调与增益误差很多人拿到 ADS122U04 之后先测一个理想电压发现码值不是完全稳定的就开始怀疑芯片坏了。其实 Δ-Σ ADC 的“24 位”指的是量化位数不是有效分辨率。在 G8、330SPS 下折合到输入端的噪声通常有几百纳伏到几微伏表现在 PT100 上就是零点零几摄氏度到零点一摄氏度的跳动。这很正常。失调误差会让零点偏移增益误差会让斜率变化。ADS 系列一般支持内部失调校准或者我们直接在软件里减一个“零点值”。最简单的方法把差分输入端短接采一组码当 offset之后每次读数减掉它。增益误差则可以通过两点校准修正具体见 5.3。5.2 激励电流和参考电阻的温漂才是隐形杀手比例式测量抵消了 IDAC 的温漂但外部参考电阻 RREF 的温漂不会被抵消。如果你随手抓一颗普通贴片电阻当 RREF标称 25ppm/°C环境温度变化 30°C 就会带来 0.075% 的误差折合到 100°C 的 PT100大约 0.19°C。如果在机柜里温度升了 60°C误差接近 0.4°C这在水流量计的温差测量里可能直接导致热量计量不准。所以 RREF 必须选低温度系数的精密电阻至少 10ppm/°C扣预算就上 5ppm/°C 的金属箔电阻。初始精度 0.1% 的偏差可以通过校准消掉温漂偏差则要用温度寿命来保证这一点不能省。5.3 零点校准与两点校准量产可用的标定流程我没有把校准想得太复杂。量产时给每个通道做两个点的线性修正R_corrected a × R_raw b第一个点是零点通常把 RTD 探头放进冰水混合物或者直接用精密电阻箱设定 100Ω第二个点可以设在 138.5Ω对应 100°C。用精密电阻箱比恒温槽方便得多因为不用考虑水温不均和热传导延时。校正后固件只存两个浮点或定标参数。没有电阻箱的话可以在电路板上留下校准模式关机状态下换上一个精度 0.05% 的固定电阻通过串口命令采集码值并保存零点。这个方法我很常用尤其是现场传感器被密封在风道里、无法拆卸时比拆探头靠谱得多。5.4 我们实测的一组数据与偏差复盘下面是我在实验室用一台高精度温度校验仪做的一组数据传感器是 A 级 PT100ADC 配置为 G8、RREF1.8kΩ、330SPS 加数字滤波标准温度系统读数误差0.0°C0.04°C0.04°C20.0°C20.09°C0.09°C50.0°C49.96°C-0.04°C80.0°C80.12°C0.12°C100.0°C99.91°C-0.09°C最大偏差大约 0.12°C主要来源是 RREF 的初始偏差和 PT100 自身在 A 级允差内的偏离。这个结果对 HVAC 来说绰绰有余对要求 ±0.1°C 的工业场合则需要再做一次两点校准把系统偏差收进 ±0.05°C 以内。6. 调试现场常见的坑从收不到数据到读数悄悄漂移6.1 上电首包失败与波特率跳变第一个坑几乎人人都会踩固件写好一上电第一条命令发出去之后ADC 没有任何反应读回来的全是 0xFF 或 0x00。最后发现是主机上电时序太快ADC 还在复位中或者 ADC 的默认波特率和主机当前波特率不一致首帧直接错位。我的解决方案很笨但有效主控上电后先延时至少 10ms连续发三次复位命令再等待 20ms。期间用一个标志位把后续采集流程锁住直到第一次 DRDY 有效才解锁。有些项目还会在配置完波特率寄存器后主动重启一次通信确保两边波特率对齐。这个延时虽然简单但省了我很多调试时间。6.2 DRDY 丢边沿导致的粘包与丢帧第二个坑是粘包。我在连续转换模式下遇到过一种情况DMA 接收的数据流比预期多了一个字节后面整个解析全部错位。原因是 DRDY 下降沿来了但主控正在处理更高优先级的中断启动 DMA 的动作被延迟ADC 已经把新数据覆盖到同一个寄存器里或者数据寄存器被读走之后又进入下一帧。解决办法是改用单次转换模式并把 DRDY 边沿捕获作为采集状态的切换条件。每次只启动一个完整“START - DRDY - DMA 接收”周期如果 DMA 超时未完成就清空缓冲区回到 IDLE。超时定时器是个好东西主循环里放一个 20ms 看门狗式检查一旦卡死就重新初始化该通道避免整个系统挂掉。6.3 长线 UART 的波形整形与隔离建议分离式安装时UART 线长几米并不罕见。在 115200 波特率下线缆电感和分布电容会让波形出现明显振铃边缘反弹会导致 MCU 接收到错误的起始位。我实测过 5 米普通杜邦线高电平上沿像弹簧一样抖偶尔就丢帧。处理方式有三个把波特率降到 19200用屏蔽双绞线传输在接收端加一个简单的 100Ω 串阻和上拉/下拉整形。如果还要做电气隔离推荐用数字隔离器代替光耦速率和一致性都好很多。隔离之后地环路彻底断开现场传感器和主控之间的共模电压差不会再打进 ADC。6.4 自热效应和环境温度变化引起的“假漂移”有段时间我发现读数会在开机后慢慢往上飘半小时后才稳定。排查了很久最后确认不是 ADC 的问题而是 PCB 上 ADS122U04 离一颗降压电感太近电感发热把芯片周围空气烤热了。内部温度传感器和 PGA 的温度特性都会受到影响读数自然跟着飘。处理办法是物理上把 ADC 挪远一点同时在传感器端增加通风和散热路径。HVAC 风道里如果风速时有时无传感器自热也会导致小范围漂移这时把激励电流从 1mA 降到 0.5mA 能明显缓解。记住一个原则测温系统最怕的是“局部温度准整体温度偏”等温区要尽量小热源要尽量远。6.5 最后留一个自检通道有一件小事让我在量产返修率上省了不少钱每块板子上我都会留一个空闲通道焊接一颗经过筛选的精密电阻比如 138.5Ω对应 100°C 的 PT100用同样的配置跑一遍 ADC固件里做个“回读校验”。如果这个通道测出来的值偏离设定值太多说明 ADC、参考电阻或基准链路出了问题而不是探头问题。这个自检通道的价值在于故障隔离。现场报修说“温度不对”客服只要发一条命令让设备自检就能分辨是传感器探头坏了还是主板采集链路坏了省掉了大量现场排查时间。可以说这套方案真正稳定下来一半靠 ADS122U04 和 STM32F732IE 本身另一半靠的是给系统留了一条确认“自己没坏”的后路。