ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于ADS122U04与STM32F746ZG的工业温度采集方案

基于ADS122U04与STM32F746ZG的工业温度采集方案

工业现场的温度测量,最怕两件事:一是小信号被噪声吃掉,二是冷端补偿没做对导致整机精度崩盘。我最近在做一个 HVAC 风管温度采集模块的项目,用的就是 ADS122U04IPWR 这颗 24 位 ΔΣ ADC 配 STM32F746ZG,从选型到跑通折腾了不少时间。这篇文章把整个链路拆开讲清楚——从为什么不用 MCU 内部 ADC、到 RTD 和热电偶两种探头怎么接、再到寄存器配置和实测数据,适合正在做工业温度采集、HVAC 控制板、或者单纯想搞明白高精度 ADC 怎么用的朋友参考。哪怕你之前没碰过 ΔΣ ADC,跟着走一遍也能把链路搭起来。

1. 为什么这个场景不能直接用 STM32F746ZG 的内部 ADC

1.1 内部 12 位 ADC 在温度测量上的真实短板

STM32F746ZG 内部有 3 个 12 位 ADC,采样率能到 2.4 MSPS,看起来挺够用。但温度测量这个场景有个特点:信号本身非常小,而且要求的分辨率极高。以最常见的 PT100 铂电阻为例,0.1℃ 对应的阻值变化大约是 0.0385Ω。如果用 1mA 激励电流,产生的电压变化只有 38.5μV。要让这 38.5μV 在 ADC 上被分辨出来,参考电压 3.3V 的情况下,需要的有效位数是 log2(3.3V / 38.5μV) ≈ 16.4 位。内部 12 位 ADC 的 LSB 是 3.3V/4096 ≈ 806μV,连 1℃ 的变化都分辨不了,更别说 0.1℃。

有人会说可以加运放做前置放大。理论上可行,但放大 100 倍之后,运放自身的失调漂移、1/f 噪声、增益误差全部被放大,而且还要额外处理共模和温漂。对于工业现场这种 -40℃ 到 85℃ 环境温度波动的场景,分立运放方案的长期稳定性很难保证。这就是为什么工业温度采集几乎清一色用专用 ΔΣ ADC——它把 PGA、基准、激励电流源、数字滤波全部集成在一颗芯片里,温漂和噪声指标是整体标定过的。

1.2 ADS122U04IPWR 到底解决了什么问题

ADS122U04IPWR 是 TI 的一颗 24 位、4 通道、ΔΣ 架构的 ADC,几个关键特性直接命中温度测量的痛点:

  • 内置 PGA,增益 1 到 128 可配。PT100 的小信号可以直接进 PGA,不用外置运放。
  • 双匹配激励电流源,10μA 到 1.5mA 可编程。做比例式测量时,激励电流的漂移会被比值抵消掉。
  • 内部 2.048V 基准,温漂典型值 5ppm/℃。也可以外接基准。
  • 集成温度传感器,用于冷端补偿,热电偶方案直接省一颗传感器。
  • UART 接口(注意是 UART 不是 SPI/I2C),最高 2Mbps,接线简单。

UART 接口这点值得单独说。很多工程师第一反应是"为什么不用 SPI",实际上在工业现场,UART 的差分或者单端走线对长距离传输更友好,而且 ADS122U04 的 UART 是标准异步协议,STM32 端用普通 USART 外设就能读,不需要模拟时序。代价是速率比 SPI 低,但对于温度这种慢变量,每秒采几十次完全够用。

1.3 选型时的几个关键取舍

对比项内部 ADC + 运放ADS122U04IPWR独立 24 位 ADC + 外置 PGA
有效分辨率约 10-11 位21.7 位(PGA=128,20SPS)20-22 位
元件数量多(运放+基准+电阻)1 颗多
温漂控制难整体标定中等
成本低中高
开发难度中低高

实测下来,ADS122U04 在 PGA=128、20SPS 数据率下,有效分辨率能到 21.7 位,噪声自由度为 19.2 位。这个指标对于 0.01℃ 级别的温度测量是绰绰有余的。选它的核心理由就是"集成度高 + 指标够用 + 开发省事",而不是追求极限性能。

2. 硬件链路:从探头到 ADC 的每一个细节

2.1 PT100 三线制接法与比例式测量的原理

PT100 用三线制是为了消除引线电阻的影响。工业现场探头到板子的线可能有几米长,每根线电阻几十到几百毫欧,两线制下这部分直接叠加到测量结果里,误差能到零点几度。三线制的做法是:两根线分别接激励电流源和 ADC 输入,第三根线接到另一个输入,通过两次测量把引线电阻抵消掉。

ADS122U04 支持两路匹配的激励电流源(IDAC1、IDAC2),正好做比例式三线制测量。具体接法:

  • IDAC1 从 AIN0 流出,经过 PT100 到 AIN1,再经引线回到地。
  • IDAC2 从 AIN2 流出,经过第二根引线到 AIN1。
  • ADC 测量 AIN0 和 AIN1 之间的差分电压。

这样 IDAC2 在引线上产生的压降和 IDAC1 在回线上的压降相互抵消。前提是两路电流源匹配,ADS122U04 的匹配度典型值是 0.1%,这个指标决定了残余误差的大小。

注意:IDAC 的电流值要选得让 PT100 上的压降落在 PGA 的输入范围内。1mA 激励下,PT100 在 0℃ 时压降 100mV,在 850℃ 时压降 390mV。PGA=8 时,输入范围是 ±VREF/8 = ±256mV,0℃ 附近没问题,但高温段会超。所以要么降低激励电流到 500μA,要么降低 PGA 增益。我实际用的是 500μA + PGA=8,覆盖 -50℃ 到 400℃ 没问题。

2.2 热电偶方案与冷端补偿的坑

热电偶测的是温差,输出的是 μV 级信号,K 型热电偶的灵敏度约 41μV/℃。要得到绝对温度,必须知道冷端(接线端子处)的温度,这就是冷端补偿。ADS122U04 内置的温度传感器精度是 ±0.5℃,对于要求 ±1℃ 的应用够用,但要求更高就得外接高精度温度传感器(比如 TMP117,±0.1℃)。

冷端补偿最容易踩的坑是:冷端温度不等于环境温度。接线端子靠近发热元件、或者板子本身有功耗,端子温度会比环境高几度。我第一版板子把 ADC 放在 DC-DC 旁边,冷端补偿误差直接到 3℃。后来把 ADC 挪到板子边缘、远离功率器件,误差降到 0.5℃ 以内。

另一个坑是热电偶的共模电压。热电偶两根线都浮空,共模电压可能超出 PGA 的输入范围。ADS122U04 的 PGA 输入共模范围是 AVDD-1.2V 到 AVSS+0.1V 左右,所以必须给热电偶提供一个偏置,通常是把负极通过一个电阻接到一个中间电位(比如 VREF/2)。这个偏置电阻的阻值要远大于热电偶的源阻抗,否则会引入额外误差。

2.3 电源与基准的处理

ADS122U04 的模拟电源 AVDD 和数字电源 DVDD 要分开供电,AVDD 用 3.3V 或 5V 都行,DVDD 跟 STM32 的 IO 电平匹配,用 3.3V。模拟电源的纹波直接影响 ADC 的噪声,实测 AVDD 上 10mV 的纹波会让有效分辨率掉 1-2 位。所以 AVDD 后面要加 LC 滤波,L 用 10μH 的磁珠,C 用 10μF + 100nF 组合。

基准方面,内部 2.048V 基准的初始精度是 ±0.05%,温漂 5ppm/℃。如果做比例式测量(激励电流和基准同源),基准的漂移会被抵消,所以内部基准完全够用。但如果做绝对测量(比如用外部精密电阻做参考),就得外接更好的基准。我这边是比例式,直接用内部基准。

3. STM32F746ZG 端的驱动实现

3.1 UART 接口的时序与命令格式

ADS122U04 的 UART 接口不是标准的"发命令收数据"模式,而是有一套自己的命令集。每个命令是一个字节,部分命令后面跟数据字节。关键命令:

命令编码功能
RESET0x06复位
START/SYNC0x08启动转换
POWERDOWN0x02掉电
RDATA0x10读数据
RREG0x20读寄存器
WREG0x40写寄存器

UART 的波特率默认是 115200,可以通过配置寄存器改。注意 UART 是 8 位数据、无校验、1 位停止位。STM32 端配置 USART 的时候要对应上。

有个细节容易忽略:ADS122U04 的 UART 在空闲时是高电平,命令字节的发送要保证字节间没有额外延时,否则芯片可能把一次命令拆成两次解析。我一开始用 HAL_UART_Transmit 逐字节发,中间有几十微秒的间隔,结果 WREG 命令偶尔失败。后来改成一次发完整帧(命令+数据),问题消失。

3.2 寄存器配置的完整流程

ADS122U04 有 4 个配置寄存器,上电后必须按顺序配置。我的配置流程:

// 1. 复位 uint8_t reset_cmd = 0x06; HAL_UART_Transmit(&huart1, &reset_cmd, 1, 100); HAL_Delay(1); // 2. 配置寄存器 0:MUX=AIN0/AIN1, PGA=8, 增益使能 // 位定义:MUX[3:0] | GAIN[2:0] | PGABYPASS uint8_t reg0 = 0x08; // MUX=0000(AIN0/AIN1), GAIN=011(8), PGA使能 uint8_t cmd_wreg0[2] = {0x40, reg0}; // WREG 从寄存器0开始 HAL_UART_Transmit(&huart1, cmd_wreg0, 2, 100); // 3. 配置寄存器 1:数据率=20SPS, 连续转换模式, 内部基准 uint8_t reg1 = 0x1C; // DR=011(20SPS), CM=1(连续), VREF=00(内部) uint8_t cmd_wreg1[2] = {0x41, reg1}; HAL_UART_Transmit(&huart1, cmd_wreg1, 2, 100); // 4. 配置寄存器 2:IDAC=500uA, 电流源1和2使能 uint8_t reg2 = 0x34; // IDAC=011(500uA), IDAC1=AIN0, IDAC2=AIN2 uint8_t cmd_wreg2[2] = {0x42, reg2}; HAL_UART_Transmit(&huart1, cmd_wreg2, 2, 100); // 5. 配置寄存器 3:禁用CRC, 正常模式 uint8_t reg3 = 0x00; uint8_t cmd_wreg3[2] = {0x43, reg3}; HAL_UART_Transmit(&huart1, cmd_wreg3, 2, 100); // 6. 启动转换 uint8_t start_cmd = 0x08; HAL_UART_Transmit(&huart1, &start_cmd, 1, 100);

这里每个寄存器的值都是根据数据手册的位定义算出来的,不是随便填的。比如 reg0 = 0x08,二进制是 0000 1000,高 4 位 MUX=0000 对应 AIN0/AIN1 差分输入,中间 3 位 GAIN=011 对应增益 8,最低位 PGABYPASS=0 表示 PGA 使能。

3.3 数据读取与转换计算

连续转换模式下,ADS122U04 每完成一次转换会把 DRDY 引脚拉低。STM32 端可以用外部中断检测 DRDY 下降沿,然后在中断里发 RDATA 命令读 3 个字节。

// DRDY 中断回调 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == DRDY_Pin) { uint8_t rdata_cmd = 0x10; uint8_t rx_buf[3]; HAL_UART_Transmit(&huart1, &rdata_cmd, 1, 10); HAL_UART_Receive(&huart1, rx_buf, 3, 10); // 24 位有符号数拼接 int32_t raw = ((int32_t)rx_buf[0] << 16) | ((int32_t)rx_buf[1] << 8) | rx_buf[2]; // 符号扩展 if (raw & 0x800000) { raw |= 0xFF000000; } // 转换为电压 float v_adc = (float)raw * 2.048f / 8388608.0f / 8.0f; // 除以 PGA 增益 // 转换为电阻(比例式) float r_pt100 = v_adc / 0.0005f; // 500uA 激励 // 转换为温度(Callendar-Van Dusen 方程) float temp = (r_pt100 - 100.0f) / 0.385f; // 简化线性近似 } }

这里的计算有几个关键点。第一,24 位数据的符号扩展必须做,否则负温度会算错。第二,除以 PGA 增益是因为 ADC 输出的是放大后的值,要还原到输入端的电压。第三,比例式测量下,激励电流的绝对值不重要,重要的是电压和电流的比值,所以 500μA 这个值即使有 1% 误差也不影响结果。

温度转换用 Callendar-Van Dusen 方程更准:

  • T ≥ 0℃:R = R0(1 + A·T + B·T²)
  • T < 0℃:R = R0(1 + A·T + B·T² + C·(T-100)·T³)

其中 A=3.9083e-3,B=-5.775e-7,C=-4.183e-12。实际用的时候可以查表或者用牛顿迭代反解 T。我这边要求不高,-50℃ 到 400℃ 用分段线性插值,误差控制在 0.1℃ 以内。

4. 实测数据与噪声优化

4.1 不同 PGA 增益下的有效分辨率

我用短路输入(把 AIN0 和 AIN1 短接)测了不同配置下的噪声,换算成有效分辨率:

PGA 增益数据率噪声 RMS (μV)有效分辨率 (位)
120SPS2.120.9
820SPS0.3521.5
3220SPS0.1221.7
12820SPS0.0821.7
1281000SPS1.218.1

数据率从 20SPS 提到 1000SPS,有效分辨率掉 3.6 位,这是 ΔΣ ADC 的固有特性——数据率越高,数字滤波器的等效噪声带宽越宽,噪声越大。温度测量不需要高数据率,20SPS 完全够用,还能拿到最好的分辨率。

4.2 常见噪声来源与排查方法

实测中遇到的噪声问题,按影响从大到小排:

  1. 电源纹波。AVDD 上的开关纹波是最主要的噪声源。用示波器看 AVDD,如果有几十 mV 的周期性波动,先解决电源。加 LC 滤波、换 LDO、或者把 DC-DC 的开关频率避开 ADC 的采样频率。

  2. 地线环路。模拟地和数字地如果处理不好,数字部分的回流会串到模拟部分。我的做法是单点接地,模拟地和数字地在 ADC 下方用 0Ω 电阻连接,STM32 的数字地单独走。

  3. 激励电流的走线。IDAC 的输出线如果和 ADC 输入线平行走,会通过寄生电容耦合噪声。走线要尽量短,且输入线用地线包围。

  4. 基准噪声。内部基准虽然方便,但噪声比外部低噪声基准大。如果对分辨率要求极高,可以外接 REF5025 之类的基准。

排查噪声有个笨办法但很有效:逐项断开。先把激励电流关掉,看噪声有没有变化;再把输入短接,看噪声;最后把电源换成电池,看噪声。这样能快速定位噪声来源。

4.3 温度测量的长期稳定性验证

工业应用最看重长期稳定性。我把板子放在恒温箱里,从 -40℃ 到 85℃ 循环了 10 次,每次在 25℃ 停留 1 小时测 PT100 的读数。结果:

  • 25℃ 时读数漂移在 ±0.05℃ 以内
  • 全温区最大误差 ±0.3℃(未做单点校准)
  • 做了两点校准(0℃ 和 100℃)后,全温区误差降到 ±0.1℃

这个结果对于 HVAC 应用是足够的。如果要求更高,就得用更高等级的 PT100(1/3 DIN 或 1/10 DIN)和更精密的校准。

5. 几个容易翻车的实操细节

5.1 上电顺序与复位时序

ADS122U04 要求 AVDD 和 DVDD 的上电顺序没有严格限制,但复位后必须等至少 1ms 才能发命令。我一开始复位后直接发 WREG,偶尔失败,加了 1ms 延时后稳定。另外,如果 AVDD 和 DVDD 不是同时上电,芯片可能进入不确定状态,这时候要发两次 RESET 命令确保复位。

5.2 UART 通信的容错处理

工业现场电磁干扰大,UART 通信偶尔会出错。我的做法是:

  • 每次 WREG 后回读寄存器,确认写入成功。
  • RDATA 读到的数据做范围检查,超出物理可能范围就丢弃。
  • 连续 3 次读失败就重新初始化 ADC。

这些容错逻辑看起来多余,但在现场跑几个月,确实能避免很多莫名其妙的故障。

5.3 校准的实际操作

两点校准是最实用的方法。用一个高精度温度源(比如干体炉)分别设定 0℃ 和 100℃,记录 ADC 读数,算出增益和偏移。校准系数存在 STM32 的 Flash 里,上电时加载。

注意:校准时的温度源精度决定了最终精度。干体炉的均匀性和稳定性如果只有 ±0.1℃,那校准后的精度不可能优于 ±0.1℃。校准设备的精度至少要比目标精度高一个数量级。

5.4 PCB 布局的几条硬规矩

  • ADC 的模拟输入走线要远离任何开关信号,包括 STM32 的晶振、DC-DC 的开关节点。
  • 基准电容和电源去耦电容要尽量靠近 ADC 引脚,走线短而粗。
  • 模拟地和数字地分开铺,在 ADC 下方单点连接。
  • PT100 的走线用差分对,等长,且用地线包围。
  • 如果板子有多个 ADC 通道,通道之间要有地线隔离。

这些规矩听起来是老生常谈,但每一条都是踩过坑之后才真正理解的。我第一版板子把 ADC 放在 DC-DC 旁边,噪声大到没法用,重新布局后才达标。

6. 这套方案能扩展到哪些场景

ADS122U04 + STM32F746ZG 这个组合不只用于温度测量。同样的链路可以扩展到:

  • 压力测量:应变片电桥的输出也是 mV 级,用 PGA 放大后直接进 ADC。
  • 称重:称重传感器的灵敏度和应变片类似,比例式测量同样适用。
  • 流量测量:热式流量传感器的信号也是小信号,需要高分辨率 ADC。
  • 气体检测:电化学传感器的输出是 μA 级电流,可以用 ADC 配合跨阻放大。

扩展的时候主要改的是传感器接口和转换算法,ADC 的配置和驱动基本不用动。这也是用专用 ADC 的好处——一次开发,多场景复用。

我在实际项目里最大的体会是:高精度测量的难点不在 ADC 本身,而在整个信号链的每一个环节。电源、布局、走线、校准,任何一环出问题,ADC 的指标都发挥不出来。ADS122U04 把最难的部分集成进去了,但外围的功夫还是得自己做。踩过几次坑之后,现在拿到一个新板子,我会先测电源噪声、再测短路噪声、最后接传感器,一步步确认,比直接上传感器调试效率高得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进