ADS122U04+STM32F072:HVAC精密温度采集方案设计实战 在几次 HVAC 控制器项目里我逐渐把温度采集链路固定成了同一种组合ADS122U04IPWR 和 STM32F072RB。ADS122U04IPWR 是一颗带 UART 接口的 24 位精密 ADCSTM32F072RB 是意法半导体的入门级 Cortex-M0 芯片两者配合用来测工业空调、冷水机组里的 PT100 和热电偶温度。这套方案解决的最大问题是怎么用中低成本的器件在工业现场长期稳定地测到 ±0.2°C 级别的温度值。它适合正在选型变送器、楼宇自控、HVAC 控制器的人参考也适合刚接触精密测温的新手快速上手。对于做嵌入式测温的工程师来说选型阶段最烦的不是传感器本身而是信号链路的整体设计传感器输出的信号那么小噪声来源又那么多ADC 怎么选、参考电压怎么弄、激励电流谁提供、软件如何把原始码变成人看的温度每一步都决定最终精度。我在这一篇里把这套方案的完整设计思路、电路接法、软件框架和调试坑全部摊开来讲希望能帮你少走弯路。1. 方案选型为什么偏偏是这两颗芯片1.1 从信号链路看测温方案的刚需温度传感器输出的信号大致分两类。RTDPT100、PT1000输出电阻需要恒流激励变成电压热电偶输出热电势量级只有几十微伏每摄氏度。两者都不是 MCU 内置 ADC 能直接消化的信号。MCU 的 12 位 ADC 一般参考电压 3.3VLSB 大约 0.8mV拿来测 PT100 在 1mA 激励下的 100mV 信号还行但要做到 0.1°C 分辨率就不现实了。至于热电偶那微伏级信号内置 ADC 根本没法看。所以想要高精度测温外部精密 ADC 是刚需。ADS122U04 这种 24 位 Δ-Σ ADC 解决的正是“小信号数字化”这件事。Δ-Σ 架构通过过采样和噪声整形把量化噪声推到高频段再用数字滤波器滤掉换取的是 20 位级别的有效分辨率。对温度这种以秒计的慢变量数据率用 20SPS 就足够得到的有效位数反而最漂亮。这是选型时容易被忽略的一点ADC 不是越快越好数据率越低数字滤波器越深噪声越低测温精度越高。温度信号变化像乌龟爬ADC 根本不需要跟兔子比速度。HVAC 场景对温度测量的需求也很有意思。楼宇自控和工业空调箱的控温精度通常在 ±0.2°C 到 ±1°C通道数从几路到十几路不等现场环境往往有变频器、电机、开关电源这些强干扰源。这种“精度要求不算极致但环境很脏”的应用恰好是 ADS122U04 这类器件最擅长应对的高有效位数给足了设计余量数字滤波能压掉不少现场干扰UART 接口又比 SPI 更好处理长距离和隔离。1.2 ADS122U04 的核心资源与 UART 接口优势ADS122U04 的硬件资源对温度采集简直是量身定做的。多路复用器可以选择 4 路差分或 8 路单端输入我做过两套设计都是四路 PT100 扫两路热电偶一个 ADC 全部搞定。内部 PGA 从 1 倍到 128 倍可编程能把毫伏级信号抬到接近参考电压的水平。两组 IDAC 电流源可以直接激励 RTD省掉一颗外置恒流源芯片。内部温度传感器用于热电偶冷端补偿不用再外挂数字温度芯片。还有高精度内部参考源虽然在比例测量里我主推外部参考电阻但这个内部参考作为备选和自检手段还是很香的。更关键的是接口。ADS122U04 的 UART 接口在日常调试中比 SPI 好用太多。SPI 有片选、时钟、主出从入、主入从出四根线时钟沿稍微有点抖动就容易被采错软件里还得小心 GPIO 的片选时序和速率匹配。UART 天生两根线协议本身就是字节流MCU 里现成的 USART 外设拿过来就能用而且可以很方便地经过 RS485 或者 RS422 拉到几十米外的传感器终端。HVAC 现场经常是设备分散、走线长设备间还用 Modbus 总线在跑UART 接口跟这套体系天然匹配。这个优势比理论参数更实在。我见过不少工程师执着于 SPI 接口的 ADS1220理由是 SPI 速率高。但温度系统瓶颈从来不在通信速率而在模拟信号质量。ADS122U04 用 UART 传输同样的命令和寄存器配置2kSPS 的最高数据率对测温绰绰有余通信线还少了两根PCB 面积和故障点都少。选型时不要被接口速率带偏关键路径是模拟前端而不是数字接口。1.3 STM32F072RB 在这套方案里承担什么角色STM32F072RB 是 ST 的 Cortex-M0 内核芯片主频 48MHz128KB Flash 和 16KB RAM。对一路到八路的温度采集、温度换算和 PID 控制逻辑来说这个资源是充足的价格也平民。选它还有个实际原因它有多个 USART其中一个给 ADS122U04另一个留作 Modbus RTU 通信如果还要接人机界面第三个 USART 也能顶上不会出现外设打架的情况。我见过不少项目为了处理能力硬选 F103其实 F072 这种轻量方案更适合 HVAC 控制场景。温度采集的任务本质是“周期性读取 浮点运算 定时控制”M0 内核跑起来很轻松。F072 的功耗也更低在需要 24V 供电的现场控制器里节省的每一毫安都对整机功耗预算有意义。除此之外F072 集成的 12 位 DAC 和模拟比较器在某些控制器里还能兼任输出 0-10V 控制信号或做报警阈值比较一颗芯片的模拟资源利用率可以拉满。对于只做温度采集的板子它的低功耗模式在休眠状态下表现也不错这是 M3/M4 平台不一定比得上的地方。要说为什么选“RB”后缀而不是更小的 F071C8主要还是容量余量。温度换算的查表、分度表数组、通信协议缓冲这些加起来32KB 的 Flash 会很紧张128KB 版本可以随意放代码而不用天天优化空间。RAM 16KB 也足够支撑浮点运算和环形缓冲。工程上留冗余比省成本更重要这是我在几个量产项目上总结出来的经验。2. 硬件电路连接关系比代码更决定精度2.1 RTD 接入比例测量与四线/三线制接法测温电路的第一个选择是激励电流的大小。PT100 在 0°C 时是 100Ω典型温度系数约 0.385Ω/°C。如果激励电流取 1mA0°C 时信号电压是 100mV100°C 时约 138.5mV信号量级不大不小PGA 增益放到 8 到 16 倍就可以把信号抬到接近参考电压的水平让 ADC 满量程利用率比较高。PT1000 的阻值大0°C 时 1kΩ激励电流建议降到 0.25~0.5mA否则自热效应会让传感器自身发热实测读数会偏高。这里提一句我调过的教训激励电流不是越大越好自热误差在大体积管道上可以忽略但风管里那根细传感器就要小心0.5mA 和 1mA 在静止空气中能差出 0.1°C 以上。比例测量的接法是这套方案里最值得直接抄的部分。把同一个 IDAC 电流同时流过参考电阻和 RTDIDAC 电流的绝对精度会在最终电阻比中消掉。只要参考电阻的温漂足够小整个链路的误差就基本集中在这个电阻上。选型上我建议用 0.1% 甚至 0.05% 精度、温漂 5ppm 以内的金属薄膜电阻。算一笔账25ppm/°C 的普通电阻在 50°C 温升下会产生 1250ppm 的漂移换算到 PT100 温度大约是 0.32°C这个量级对恒温控制已经需要警惕了换成 5ppm 的电阻同样的温升只有 0.06°C完全可控。四线制和三线制的本质都是把“电流回路”和“电压采样回路”分开。四线制最干净两根线走激励电流两根线只采电压采样线没有电流流过线阻不影响测量。三线制省掉一根线适合已经布好的现场电缆。接法上要让激励电流路径和差分采样路径尽量只在 RTD 本体附近交汇这样线阻引起的压降不会进入差分输入。工业现场如果线缆长度超过十米建议直接上四线制省下来的调试时间远比省一根线值钱。具体到我常用的接法IDAC 输出接 RTD 高端RTD 低端回流到模拟地参考电阻接在 REFP/REFN 之间由同源 IDAC 激励。ADC 数字输出直接等于 RTD 阻值与参考电阻的比值乘上满量程系数和 PGA 增益的倒数就得到实际阻值。这里有一个关键点参考电阻必须和 RTD 用同一个 IDAC 激励否则电流源的微小波动会破坏比例关系。我见过有人为了省事给参考电阻单独供电结果温度一变两个电流源之间的比例漂移直接反映到读数上看起来就像传感器坏了。2.2 热电偶接入与冷端补偿热电偶的接入要注意两点一是信号电平极小K 型热电偶大约 41µV/°CPGA 增益要放到 64 或 128二是必须做冷端补偿。热电偶输出电势反映的是热端与冷端的温差不是绝对温度。冷端在哪里就在热电偶引线连接到 PCB 接线端子的那个位置。要补偿冷端温度ADS122U04 内部温度传感器就能干这件事把它当作一路输入读一次得到冷端温度再配合查表法把热电偶电势换算成冷端到热端的温差两者相加就是真实温度。这里有个容易忽略的细节冷端温度传感器读到的必须是热电偶引线与 PCB 端子相交处的温度。PCB 上如果有功率器件或者变压器会把板温加热导致冷端温度不均匀这时内部温度传感器和实际冷端温度之间的偏差可能到好几度。解决办法是把 ADC 芯片和接线端子靠得近一点避开发热源最好有铺铜均温。我在一块板上把 ADC 放在了板子的角落结果那个区域正好靠近一个 24V 转 5V 的 DC-DC冷端补偿温度比实际高了 2°C导致热电偶读数整体偏大后来换到板中央才解决。热电偶引线还容易引入共模噪声。两个输入引脚到地之间建议各加一个 100nF 左右的滤波电容并在输入引脚之间并联一个较小的电容构成一阶低通。这个电容值别取太大会影响建立时间我一般取 1nF 到 10nF 之间和数据率匹配。如果现场有变频器走线又长还可以在靠近传感器端加共模电感但多数 HVAC 场景下前级的简单滤波已经够用。2.3 电源、去耦与 PCB 布局的工程细节电源是另一个决定性因素。ADS122U04 的数字电源和模拟电源建议分开走线各自去耦。我习惯在 AVDD 引脚放一个 10µF 钽电容加一个 0.1µF 陶瓷电容DVDD 单独一个 0.1µF两个电源之间如果只有板内噪声串一个磁珠或者小阻值电阻就足够。REF 引脚的去耦同样要讲究参考电压稳定直接决定转换结果稳定我在 REFP/REFN 之间会再并一个 100nF然后靠近引脚摆。模拟地和数字地最终单点连接。很多工程师画板时把 AGND 和 DGND 铺成一大片然后在 MCU 和 ADC 之间乱串其实没必要。ADC 这类器件内部已经把模拟和数字分开了外部只要保证回流路径不交叉铺地不会带来大问题。我实际踩过的一个坑是不要在 ADC 的模拟输入走线下面走数字信号线尤其不能走 USART_TX 这种翻转电平的线串扰会让 ADC 输出出现周期性的跳变后级滤波都压不掉。PCB 上还有一个细节ADC 与 STM32 之间的 UART 走线电平翻转比较快如果距离长可以串 100Ω 到 1kΩ 的小电阻波形边缘不要求漂亮稳定最重要。这又呼应了 UART 接口的选择这种抗干扰处理比 SPI 的时钟完整性要求容易得多。整板布局我的建议顺序是传感器接线端子 → ADS122U04 → 参考电阻 → MCU尽量让模拟信号路径短而粗数字通信路径只要不干扰模拟区就行。3. 软件实现从 UART 命令到温度数值3.1 驱动层UART 配置与命令时序ADS122U04 的软件驱动本质上是把 SPI 风格的操作字节通过 UART 字节流发出去。MCU 侧只要把 USART 配置成 8 数据位、无校验、1 停止位波特率固定在一个双方都确认的值就能正常工作。我实测下来 9600 和 115200 都稳定没有出现字节错位。只有一次在 115200 下用劣质 USB 转串口工具调试时见过丢字节所以调试期我习惯用 9600产品里上位机要求速率时再调高。初始化步骤大概是复位 ADC等待内部上电完成依次写配置寄存器然后发 START 命令启动连续转换。数据准备好后 DRDY 引脚拉低MCU 可以用外部中断感知也可以直接发 RDATA 命令读数据。我更建议用 DRDY 引脚触发读取省 CPU 时间也能避免在数据正在更新时读到一半的中间值。驱动层的重点是要学会读寄存器回读确认写完配置寄存器后用 RREG 把刚才的值读回来和写入值比对一遍能立刻暴露 UART 通信的字节错位、位宽不一致等问题。驱动代码的框架不复杂STM32F072RB 的 USART1 配置大概是这样的// USART1 初始化 9600 8N1PA9TXPA10RX void ads122u04_uart_init(void) { // 使能 GPIOA 和 USART1 时钟 RCC-IOPENR | RCC_IOPENR_GPIOAEN; RCC-APB2ENR | RCC_APB2ENR_USART1EN; // PA9、PA10 复用为 AF1 GPIOA-MODER ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10); GPIOA-MODER | (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1); GPIOA-AFR[1] | ((1 4) | (1 5)); // 48MHz 时钟下9600 波特率对应 BRR5000 USART1-BRR 48000000 / 9600; USART1-CR1 USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; } // 单字节收发封装相当于 SPI 的 transfer uint8_t ads122u04_transfer(uint8_t byte) { while (!(USART1-ISR USART_ISR_TXE)); USART1-TDR byte; while (!(USART1-ISR USART_ISR_RXNE)); return USART1-RDR; }写寄存器时序是发 WREG 指令、寄存器地址、参数一次多寄存器写就是一串连续的字节。这里有个容易踩的坑ADS122U04 的 UART 帧对字节间隔有要求如果 MCU 在两个字节之间去处理中断拉长了间隔芯片可能把后续字节当成新命令的首字节导致寄存器写错位。解决办法是把一次 WREG 操作的几个字节放在一个临界区内连续发完或者直接关中断发送。我在最初版驱动里吃过这个亏现象是寄存器乱套回读值和预设值完全对不上看波形又看不出问题后来查手册里对帧间隔的说明才定位到。命令编码我是直接参考 TI 手册里的 SPI 命令帧通过 UART 原样传输读寄存器 RREG、写寄存器 WREG、启动转换 START、停止 STOP、读数据 RDATA。具体命令字节和寄存器位域定义请以最新版手册为准不同批次文档细节有修订但命令帧格式基本稳定我用的是和 ADS1220 同源的命令集。3.2 寄存器配置思路与数据读取流程寄存器配置按功能分三块。第一块是输入多路复用器选择当前通道接哪一对引脚第二块是 PGA 增益、参考源、转换模式第三块是数据率、滤波器类型和 IDAC 电流大小。以 PT100 为例我会把 PGA 设为 8 倍参考源用外部 REFP/REFN数据率 20SPSIDAC 打开 0.5mA 或 1mA 激励。热电偶场景则把增益放到 64 或 128启用内部温度传感器通道外部参考和内部参考都行但做冷端补偿时我会额外读一次内部温度通道。多通道扫描在 HVAC 设备里很常见比如四路 PT1000 测进风、回风、供水、回水温度。逻辑上就是循环切换输入多路复用器每次切换通道后丢弃前几次转换结果等数字滤波器稳定后再读取。这个“建立时间”参数在数据手册里有详细表格和增益、滤波器配置都有关系。工程上我通常做法是切换后丢两次结果再读第三、第四次取平均这样既简单又稳。我不太推荐在连续转换模式下频繁切换通道因为滤波器的群延迟会叠加最终读数会包含上一个通道的残留看起来就像是通道之间串扰。读取流程上单次转换模式比连续模式更适合多通道扫描。START 命令启动一次转换读取结果后自动进入低功耗省电且通道切换逻辑非常清晰。连续模式更适合单通道长期监测但数据准备好后要及时读取否则 DRDY 超时后会覆盖数据程序里要处理这个状态。我自己的项目里四路 PT100 用单次模式轮流测一路热电偶单独用连续模式两者配合没有冲突。配置代码里我会写一个通道结构体把增益、输入选择、IDAC 大小都绑在一起这样扫描函数只需要遍历结构体数组就能完成。3.3 温度换算、非线性修正与实用公式拿到了 ADC 原始码温度换算分两步第一步把码值换算成电阻值第二步把电阻值换算成温度。第一步的比例关系和参考电阻、PGA 增益有关公式是R_rtd (ADC_Code / 8388607.0) * R_ref / gain这里 8388607 对应 24 位二进制补码的满量程前提是比例测量参考电压由同一电流源在参考电阻上产生。如果参考电压用的是内部固定基准公式就不是这个简单的线性关系了要加上参考电压绝对值参与计算精度也会受内部基准温漂影响。这就是我前面反复强调外部参考电阻做比例测量的原因省掉一个误差来源公式也干净。举一个实际计算的例子假设 R_ref1500Ωgain8ADC 原始码读出 447392。代入公式R_rtd 447392 / 8388607 * 1500 / 8算出来约 100.1Ω。这个电阻值放在 PT100 的 0 到 100°C 区间里对应温度大约 0.25°C。整个过程用一句代码就能写完但前提是 float 精度要够用STM32F072 的 FPU 是软浮点跑这个计算没有问题就是在高数据率下注意循环时间。电阻到温度的换算最准确的是用 Callendar-Van DusenCVD方程。0°C 以上区域R_t R_0 * (1 At Bt^2)其中 A3.9083e-3、B-5.775e-7。反解 t 可以用二分法或者牛顿迭代代码量都不大。工程上如果不想做浮点方程直接用 0.1°C 间隔的 PT100 分度表查表加上线性插值也能做到 0.1°C 以内的精度。HVAC 应用对绝对精度要求一般是 ±0.2°C 到 ±0.5°C两种做法都够。我个人习惯用方程反解因为代码统一不用维护一张大分度表Flash 空间也更充裕。热电偶的换算思路完全不同先读取 ADC 测量值换算成热电势毫伏值用查表法从热电势反查温度再用前面读到的冷端温度加上查表得到的温差。注意热电偶的毫伏-温度关系是非线性的不能用简单的比例系数必须查分度表。工业标准分度表网上都有生成一个 C 语言数组就行K 型热电偶从 -200°C 到 1300°C 的查询表大约几百个点内存占用不大。冷端补偿的温度读数来自内部温度传感器我这里会在初始化时做一次偏移校准把 ADC 芯片放在已知温度的恒温环境里读一次内部温度把偏差值存 Flash之后每次补偿都用修正后的值能明显改善热电偶在小温差场景的准确性。4. 现场调试常见问题与排查经验4.1 UART 通信乱码和超时的处理我在调试这套方案时遇到的第一类问题是通信乱码。现象是写入寄存器的值和回读值不一致或者 AD 数据不定期变成 0xFFFFFF。排查顺序先看 MCU 和 ADC 的波特率是否一致尤其是内部时钟误差。STM32F072 的 HSI 在出厂校准后精度一般在 ±1%理论上不影响但如果你改过时钟树把 USART1 挂到了 PLL 上BRR 算错就会乱码。我是用逻辑分析仪抓 UART 波形数一下实际位宽这个最直观。第二类问题是超时。ADS122U04 在某些错误状态下不会响应命令比如电源掉电、外接晶振没起振、或上电时序不满足要求。解决方法是给驱动层加超时重试机制STM32 的 USART 有超时寄存器可以用或者简单一点用定时器做超时判断。我一般在初始化流程里加一个 10ms 复位等待然后连续三次写读寄存器成功才继续往下走这样即使现场上电缓慢也不会卡死在启动阶段。还有一类容易被忽略的是接地问题。ADS122U04 与 MCU 在同一个板子上直接连 TX/RX 没问题一旦通过连接器接到外部信号板两块板的地电位可能不同这时候必须共地必要时用光耦隔离或者 RS485 收发器。我现场遇到过手持设备单独供电结果 UART 一直乱码查了半天发现两套设备的地没连在一起信号电平的参考点不一致。这个问题在实验室一般复现不出来一到现场接上长线就会冒出来。4.2 读数跳动、噪声和温漂的排查技巧温度读数在稳定环境中持续跳动是最让人头疼的问题。排查时先把 ADC 原始码打出来如果原始码都稳定那是软件换算或滤波的问题如果原始码在跳就要从硬件查起。最常见的原因三个。第一个是电源纹波。ADS122U04 对 AVDD 上的高频纹波很敏感我遇到过开关电源纹波直接耦合到参考电压上读数跳好几个 LSB。处理办法是把模拟电源用 LDO 单独供电或者在 AVDD 引脚处加强滤波。第二个是参考电阻选错了类型。普通厚膜电阻的温漂参数看着还行实际工作温度漂移却很明显换成金属薄膜电阻后问题明显缓解。第三个是滤波电容位置。输入引脚和参考引脚的去耦电容必须靠近引脚摆远了以后高频路径的环路面积变大噪声拾取能力成倍上升。温度漂移的排查思路略有不同。如果零点或者满量程随时间缓慢偏移重点是检查参考电阻的温度系数。前面已经算过25ppm/°C 的电阻在 50°C 温升下能产生 0.32°C 的温度误差这级别在某些恒温控制场合已经不可接受了。换 5ppm 的电阻误差降到 0.06°C 左右才可控。另外如果整个板子在开机后前几分钟会有一段明显漂移那是 ADC 芯片和参考电阻的自热还没稳定下来软件里可以做上电等待等内部温度稳定后再开始采集。4.3 排查速查表与量产校准建议把前面提到的要点整理成一张排查速查表做方案评审或者调试时对照着用会很方便排查环节常见问题优先处理方向信号接入读数偏大或缓慢增大检查激励电流是否过大导致自热参考电路温漂超标换低 TC 参考电阻检查供电纹波通信链路乱码或超时确认波特率、共地、字节间隔连续软件换算零点偏移检查比例公式里的增益和参考电阻值PCB 布局周期性跳动检查模拟走线是否被数字信号干扰量产校准这件事我也多说一句。最好在 PCB 上预留一组标准测试点把各通道分别切换到一个 100Ω 精密电阻、一个 1000Ω 精密电阻和一个热电偶毫伏源上电自动跑一遍增益校准把实际增益误差存到 Flash 里。这样即使不同批次参考电阻有微小差异也能通过软件校准拉到同一水平对生产一致性帮助很大。很多批量产品的问题不是硬件不行而是没有给软件留出校准手段。我个人多年调试下来的体会是做温度采集软件滤波和平均永远只是治标先把供电、参考电阻、信号路径这三样基本盘确认干净读数自然就稳了。ADS122U04 的好处是它把信号链整合得比较完整软件省了不少事根本精力都可以放在外围这几颗关键器件上。等你把参考电阻选到位、校准脚本跑通剩下的就是很成熟的应用层逻辑了。这套方案我已经在好几个 HVAC 项目里稳定运行你也值得按这个思路试一遍。