我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

ADS122U04+STM32L4高精度温度采集系统:兼容热电偶/PT100/NTC

ADS122U04+STM32L4高精度温度采集系统:兼容热电偶/PT100/NTC 搞温度测量这活儿说容易也容易说麻烦也真麻烦。你要是拿个 NTC 热敏电阻加个普通 ADC 糊弄事那 25 度能测到 26 度也算能用可一旦放到工业现场或者 HVAC 系统里客户要求的往往是“0.5 度以内”、“全年不漂”、“现场干扰随便来”这就不是一颗内置 ADC 能扛得住的事了。我这次用的组合是 ADS122U04IPWR 这个带 UART 接口的 24 位 Δ-Σ ADC配上 STM32L4A6RG 这颗低功耗 Cortex-M4 主控把热电偶、PT100、NTC 三种最常见的工业温度传感器全给接了一遍。文章会把选型思路、硬件连接、寄存器配置、温度换算算法和调试踩坑都写清楚适合正在做工业采集、HVAC 温控或者手持仪表的朋友参考。1. 方案选型与整体架构1.1 为什么选 ADS122U04IPWR 而不是普通 ADC先说结论普通 MCU 内置 ADC 在温度采集这种场景下最大的痛点不是分辨率而是“信号太小 噪声太大”这对组合。热电偶 K 型在 0 到 200 度范围内灵敏度大概只有 40µV/°C 上下一个 0.1 度的变化对应的电压才 4µV。你就算用 12 位 ADC 也很难分辨出这么小的信号更别说现场还有电机、变频器、电源纹波这些干扰源。ADS122U04IPWR 是 TI 家的 24 位 Δ-Σ ADC内部自带可编程增益放大器PGA1 到 128 倍、2.048V 基准源、温度传感器、以及两路可用于 RTD 激励的电流源。也就是说它把一整套模拟前端都集成进一颗 TSSOP-16 封装里了外部只需要加一些去耦电容和电阻就能干活。这里面比较关键的是“24 位分辨率 PGA”配合 64 倍或 128 倍增益热电偶微伏级的信号可以被放大到 ADC 量程范围内分辨率能到亚微伏级别温度分辨率做到 0.01 度不是问题。再说 UART 接口。ADS1220 系列用的是 SPI这本身没问题但工业现场经常面临传感器和主控距离比较远的情况。SPI 是同步通信SCK、MISO、MOSI、CS 至少四根线距离一长时钟就爱出问题。而 ADS122U04 这个型号里的 U 就代表 UART 输出主控端只需要一根 TX 一根 RX 加一根 GND 就能通信距离一长还可以直接挂 RS485 收发器这个优势在 HVAC 这种传感器分散的场合非常实用。顺便提醒一句ADS122U04 和 ADS1220 虽然功能上很像但引脚和通信协议不兼容选型的时候别买错了。看丝印带 U 的是 UART 接口版本。1.2 STM32L4A6RG 在系统里扮演什么角色STM32L4A6RG 是 STM32L4 系列里的高配型号Cortex-M4F 内核主频跑到 120MHzFlash 有 1MBSRAM 320KB。有人可能觉得这配置拿来读个 ADC 是不是太浪费了但实际做产品你就知道资源这东西“用不用得光是你的设计问题够不够用是硬件选型问题”。温度采集只是前端后面往往还要跑 Modbus RTU 协议、LCD 显示、按键处理、历史数据存储、甚至 LoRa 或以太网通信这些堆下来64KB Flash 的单片机就憋屈了L4A6RG 这个空间基本属于“随便折腾”。选 L4 系列还有一个重要原因低功耗。HVAC 温控器很多时候是 24V 交流供电或者电池供电系统待机电流要求做到微安级。STM32L4 的 STOP 模式加上 LPUART 唤醒、RTC 定时唤醒都是标配配合 ADS122U04 的关断能力可以把整个系统的平均功耗压到很低。后面我会单独讲低功耗软件设计。另一个细节STM32L4 的大多数 GPIO 是 5V 耐压的标注 FT也就是所谓的 5V tolerant。当你的 ADS122U04 用 5V 供电、输出高电平接近 5V 时MCU 引脚可以直接承受不会烧。不过我还是建议串一个 1kΩ 电阻做保护原因后面说。1.3 整体信号链这套系统的信号链路是这样的传感器热电偶/RTD/NTC→ 模拟输入差分或单端 → ADS122U04 内部 PGA 放大 → 24 位 Δ-Σ 调制器 → 数字滤波器 → UART 输出 → STM32L4A6RG 的 USART 接收 → DMA 搬运 → 软件解析原始码 → 滤波算法 → 温度换算 → 显示/通信这里有一个很重要的设计思路ADC 只负责把模拟信号“忠实地”变成数字码所有温度换算在 MCU 端做。为什么因为温度传感器是非线性的热电偶需要查表或者多项式拟合RTD 需要 Callendar-Van Dusen 方程NTC 需要 Steinhart-Hart 方程这些计算放 MCU 端做才有灵活性。而且上位机调试时可以直接读原始 ADC 码方便定位问题到底出在模拟前端还是算法上。三种传感器的配置大致可以整理成下面这个表传感器类型接入方式ADS122U04 内部资源目标精度K/J 型热电偶差分输入 AIN0/AIN1PGA 32~64 倍内部温度传感器做冷端补偿±1℃ 全温度段PT100 三线制差分输入 双电流源激励电流源 1mA第二电流源匹配线阻±0.2℃两点校准后NTC 10k单端输入外部精密电阻分压PGA 1~4 倍内部基准 2.048V±0.3℃单点校准这样一块板子就能覆盖绝大多数工业温度和 HVAC 的测温需求硬件不用改改软件配置就行。这也是这套方案的长期价值一个硬件平台兼容多种传感器。2. 硬件连接与模拟前端设计2.1 电源和去耦这是 24 位 ADC 能不能跑出 24 位性能的前提很多人在 24 位 ADC 上得不到理想精度八成是供电和地线没处理好。ADS122U04 的模拟供电 AVDD 支持 2.3V 到 5.5V数字供电 DVDD 也可以独立接。我建议如果系统主电源是 3.3V那就 AVDD 和 DVDD 都接 3.3V简单省事如果系统里有现成的 5VADC 用 5V 供电也行但要注意此时 UART 高电平和 3.3V MCU 之间的电平匹配后面会说。去耦电容不能省而且要按规格放AVDD 对 AVSS 之间放一个 10µF 钽电容 100nF 陶瓷电容DVDD 对 DGND 之间放 1µF 100nF基准电压 REFP 对 REFN 之间放 1µF 也不能少。这些电容要尽量靠近芯片引脚走线短粗。我见过有人把去耦电容放着没焊结果 ADC 读数跳动十几个 LSB怎么调寄存器都没用焊上电容瞬间就稳了。还有一个关键细节24 位 Δ-Σ ADC 的模拟地和数字地建议在 PCB 上单点连接不要让数字信号的返回电流流进模拟信号的参考地回路。实际布线时把 UART 的 TX/RX 走线远离 AIN0 到 AIN3 的模拟输入走线两路之间留出地线隔离。另外内部基准电压源虽然省事但它的温漂和噪声无论如何都不如一颗好的外部基准。如果你这个项目要跨 0 到 70 度环境而且客户对精度要求是“全温度范围 ±0.5℃”我强烈建议改用外部基准比如 REF33252.5V或者 REF5025低温漂 2.5V。此时 REFP 接基准输出REFN 接模拟地ADC 内部基准选择寄存器的对应位也要改掉。2.2 UART 连接电平匹配和长线传输STM32L4 的 USART2 或 USART3 都可以接 ADS122U04。连线就三根MCU 的 TX 接 ADC 的 UART_RXMCU 的 RX 接 ADC 的 UART_TXGND 必须连。这里最容易出的问题是共地最高频的 UART 不稳定故障就是两个板子各用各的电源、GND 又没连牢导致信号参考点不一致。如果 ADC 用 5V 供电它的 UART 输出高电平接近 5V。STM32L4 的 GPIO 虽然标了 5V 耐压但那是“引脚承受得住不烧坏”不代表你可以在 5V 电平下长期稳定工作。稳妥做法是在 RX 线上串一个 1kΩ 电阻利用单片机引脚内部的保护二极管把电压钳在 VDD 0.3V 左右既保护了引脚又不影响信号。MCU 的 TX 输出 3.3V 到 ADC 的 RXADC 的 RX 一般能识别 0.8×DVDD 以上的高电平如果 DVDD 也是 5V那 3.3V 就不够高这时需要加一个简单的电平转换电路比如用两个 2N7002 搭的 I2C 级别的双向电平转换或者直接用 5V 供电的单片机一侧接口。长线传输的情况下建议加 RS485 收发器比如 MAX485。ADC 的 UART 经过 RS485 转成差分信号传到 50 米外的 MCU接收端再接回 UART。工业现场能用隔离就隔离用光耦或者带隔离的 RS485 模块把传感器端和主控端的电气彻底断开这样地环路噪声就不会进入 ADC 了。2.3 三种传感器接线实操模板热电偶接线最简单正极接 AIN0负极接 AIN1差分输入。但有两个容易忽略的坑第一热电偶的引线是合金材料和铜导线连接的地方本身就是一个“寄生热电偶”会额外产生一个热电势。所以连接端子要尽量靠近冷端温度传感器并且保持两侧端子等温。第二热电偶输出的是微伏级信号PGA 增益如果设得不够大量化噪声就把信号淹没了。K 型热电偶测 0 到 200 度信号范围大约 0 到 8mV我建议 PGA 设 64 倍8mV × 64 512mV接近满量程但不会溢出分辨率最佳。PT100 三线制接法要稍微动点脑筋。三根线的目的是消除引线电阻。工作在 1mA 激励电流下PT100 在 0 度时电阻 100Ω电压 100mV在 100 度时约 138.5Ω电压 138.5mV。假设每根引线电阻 5Ω100 米 0.5mm² 铜线大概就是这量级如果不做补偿5Ω 线阻带来的误差相当于 5Ω/0.385Ω/°C ≈ 13 度这误差绝对不能忍。三线制的思路是一根线走激励电流另一根线走电压检测第三根线走回流。ADS122U04 有两个可编程电流源 IDAC1 和 IDAC2把 IDAC1 接到 AIN0 引线端IDAC2 接到同一点两个电流源大小相等这样在检测回路里两条引线上的压降相互抵消ADC 测到的电压就只剩 RTD 本身的压降了。NTC 更简单用外部精密分压电阻接在电源和 NTC 之间ADC 测分压点电压。这里注意分压电阻一定要选低温漂的1% 精度的 0603 贴片电阻通常温漂 100ppm/°C用在 NTC 分压上会直接变成零点几度的误差。建议至少用 0.1% 精度、25ppm/°C 以下的电阻比如金属薄膜电阻。3. ADS122U04 寄存器配置与 UART 通信实现3.1 寄存器配置目标功能怎么定配置值怎么算ADS122U04 的寄存器结构跟 ADS1220 系列同源都是通过 UART 命令读写配置的核心就四项输入多路选择MUX、PGA 增益、数据速率、基准电压来源。每一类传感器对应一套配置。我先说一个开发阶段的习惯动作拿到芯片先读一遍所有寄存器默认值和手册上的复位值对一下万一 UART 波特率配错、连到了奇怪的状态读出的值会明显不对能省大量排查时间。写寄存器配置时最重要的是理解增益和数据速率的关系。数据速率越高Δ-Σ ADC 内部数字滤波器用到的采样点越少噪声越大。比如 ADS122U04 在 20SPS 下有效分辨率能到 24 位而 2000SPS 下有效分辨率可能跌到 17、18 位。反过来工业 50Hz 工频干扰会让读到的信号叠加明显的 50Hz 纹波。合理做法是如果只需要慢速测量比如 HVAC 室温响应时间几秒就够了数据速率选 20SPS 或 60SPS既能抑制工频又能拿到最高分辨率如果需要快速响应比如电机绕组温度监测可以选 330SPS 或更高配合软件均值滤波。常见配置我整理成下面这个表具体寄存器位以你所拿到的芯片数据手册为准场景MUX 选择PGA 增益数据速率基准电流源K 型热电偶AIN0-AIN1 差分6420 SPS内部 2.048V关闭PT100 三线制AIN0-AIN1 差分860 SPS内部 2.048V1mAIDAC1/IDAC2NTC 10k 分压AIN2-AIN3 单端1~420~60 SPS内部 2.048V关闭这里有一个容易搞混的点PGA 增益的配置值和实际倍数不是“1 对应 1 倍”这么简单寄存器里是二进制编码。比如增益 64 对应的二进制值是 110要写进增益位段。我的习惯是写程序时先在注释里写清楚“目标增益”再写“编码值”免得过一个月回来看代码已经看不懂当初为什么填这么个数字。配置下发的代码结构大概是// 伪代码命令字以手册为准 uint8_t cfg[4]; // 热电偶模式AIN0-AIN1 差分PGA6420SPS内部基准 cfg[0] ADS122U04_REG0_MUX_DIFF_AIN0_AIN1 | ADS122U04_REG0_GAIN_64; cfg[1] ADS122U04_REG1_DATARATE_20SPS | ADS122U04_REG1_CONTINUOUS; cfg[2] ADS122U04_REG2_VREF_INTERNAL; cfg[3] ADS122U04_REG3_IDAC_OFF | ADS122U04_REG3_TEMP_SENSOR_OFF; ads122u04_write_regs(cfg, 4);每一行配置都对应一个明确的意图测热电偶不能用内部电流源因为电流源会在热电偶内阻上产生额外的压降直接污染微伏级信号测 RTD 必须开电流源因为需要恒流激励测 NTC 用外部电阻分压ADC 内部电流源反而多余。这些“为什么”想通了寄存器配置就不是背数据手册而是水到渠成的事。3.2 命令帧与数据帧格式ADS122U04 的 UART 通信本质是主从式的MCU 永远是主机ADC 是被动响应。MCU 发命令ADC 执行后返回应答或者转换数据。常用命令包括复位、读寄存器、写寄存器、启动转换、读取结果。这里要特别说一下“启动转换”和“读取结果”的关系。如果配置成连续转换模式ADC 会一直转换数据准备好了会自动发到 UART 上MCU 只需要接收如果配置成单次转换模式MCU 每次要发一个启动命令然后等转换完成再读结果。单次模式的好处是灵活适合电池供电的低功耗场景——平时 MCU 睡觉醒来发一个命令等几百毫秒收完数据继续睡。连续模式的好处是省事适合实时监测。数据格式可以是二进制3 字节也可以是 ASCII6 个十六进制字符我推荐二进制。转换结果是 24 位二进制补码正数范围 0x000000 到 0x7FFFFF负数从 0x800000 到 0xFFFFFF。MCU 端接收时注意做符号扩展不然负数会变成很大的正数后面换算温度就全乱了。我给出主控端一个简单的 UART 接收和解析代码uint8_t rbuf[3]; int32_t raw_code; // 等待并读取 3 字节转换结果 HAL_UART_Receive(huart2, rbuf, 3, 100); // 合成 24 位数据 raw_code ((int32_t)rbuf[0] 16) | ((uint16_t)rbuf[1] 8) | rbuf[2]; // 24 位补码符号扩展 if (raw_code 0x800000) { raw_code | 0xFF000000; }符号扩展这一行看着简单但真有人在这个地方翻车。如果不做扩展比如 ADC 量程负半段读数 0x800000代表 -4.096V 对应满量程直接当正数算就会得出一个完全错误的温度值。3.3 从原始码换算电压和温度收到原始码之后第一步是换算成电压。公式是电压 原始码 × 基准电压 / (PGA 增益 × 2^23)举例假设基准 2.048VPGA 64原始码是 0x123456十进制 1193046那么电压1193046 × 2.048 / (64 × 8388608) ≈ 0.00455V 4.55mV这个 4.55mV 如果是 K 型热电偶查表可知大约对应 110 度左右。注意公式里的分母是 2^23 而不是 2^24。因为 24 位补码表示的范围是对称的 ±2^23所以满量程对应基准电压而不是两倍基准。这个细节很多人会算错写代码时小心点。NTC 的换算则是先算分压电阻再套 Steinhart-Hart 方程Rntc Rref × (Vref_actual - Vout) / Vout也就是分压点电压 Vout 和 Rref 已知反推 NTC 当前电阻然后把 Rntc 代入方程求温度。这里我强烈建议电压计算全程用浮点别用整数省那点算力STM32L4 有 FPU浮点运算一个周期就完成了精度远比那点效率重要。4. 温度算法热电偶、RTD、NTC 的换算与校准4.1 热电偶冷端补偿别以为测到电压就能查表热电偶测的是热端和冷端参考端之间的温差电动势。你 ADC 读到的电压本质上是“热端温度对应的电动势减去冷端温度对应的电动势”。如果冷端是 0 度那直接查表就行但实际冷端就在接线端子那里温度随环境变所以必须做冷端补偿。冷端补偿的标准做法先用一个温度传感器测出冷端的实际温度比如用 ADS122U04 内置温度传感器或者外接的 TMP117 然后用这个温度反查热电偶分度表得到“冷端在这个温度下应该产生的电动势”把这个电动势加到 ADC 测量值上得到等效于冷端为 0 度时的电动势再查表或者用多项式拟合得到热端温度。ADS122U04 内置温度传感器很方便因为它和模拟输入在同一芯片上如果你把冷端连接器紧贴着 ADC 芯片芯片温度基本就代表冷端温度。这样省一颗外部温度传感器电路设计简化不少。但代价是精度有限因为 ADC 芯片自身有功耗发热会让芯片温度比环境高 1~2 度造成冷端补偿误差。如果你的产品对成本敏感且要求不是超高内置传感器够用如果你要挑战 ±0.5℃ 全温精度建议用一颗外部NTC 贴到端子上。查表方式有讲究。最准的是 NIST ITS-90 多项式但那个公式最高到 9 次方算起来比较烦。工程上常见做法是把分度表做成 lookup table每 10 度存一个值中间用线性插值。K 型热电偶在 0 到 300 度之间的近似灵敏度约 40µV/°C做 10 度间隔的线性插值插值误差一般在 0.1 度以内完全够用。我在项目里甚至用过更简化的办法只补偿一个平均灵敏度 40.44µV/°C × 冷端温度10 度冷端误差约 2µV对应 0.05 度温度误差绝大多数场景都能接受。注意PID 参数、报警阈值这些逻辑跑出来不对先怀疑不是代码 bug 而是冷端补偿没做好这是热电偶测温最典型的隐性误差源。4.2 RTD 线性化与三线制推导PT100 在 0 到 100 度之间电阻从 100Ω 增加到约 138.5Ω基本线性平均灵敏度 0.385Ω/°C。但你要拿到高精度不能只按线性算。标准做法是用 IEC 60751 标准的 Callendar-Van Dusen 方程R(T) R0 × (1 A×T B×T² C×(T-100)×T³)其中 0 度以上 C 项为 0A 3.9083×10⁻³B -5.775×10⁻⁷C -4.183×10⁻¹²仅 0 度以下使用MCU 端实现这个方程很简单直接带入 T 的初值迭代几次也行或者反过来用牛顿法从电阻求解温度。实际上更工程化的做法是查表加插值PT100 的电阻表到处都是存一个 -50 到 200 度、每 1 度的电阻值表格也就几百字节查表加线性插值误差远小于 0.1 度完全够用。推导三线制为什么能消线阻假设两根引线电阻都是 Rw。IDAC1 输出 1mA 经过引线 Rw 到 RTDRTD 电压降为 1mA×RTD再经过第二根引线返回。ADC 差分输入端 AIN0 和 AIN1 之间看到的电压包括RTD 上的压降、上下两段引线上的压降。在理想匹配情况下上下两段引线压降都是 1mA×Rw差分输入两端对称实际输入电压就等于 RTD 的压降引线电阻被抵消。这就是为什么三线制要有“第二个电流源”从同一点注入电流——它制造了一个对称的电流通路。实际调试中检流电阻和引线不可能完全一致剩下的残余误差通常只有零点几欧对应零点几度可以接受。如果你要追求极致就用四线制激励和检测完全分开线阻理论误差为零。4.3 NTC 热敏电阻的 Steinhart-Hart 方程NTC 的电阻和温度关系是高度非线性的常见近似公式是 B 值公式但那东西在宽温度范围误差较大。想精度高用 Steinhart-Hart 方程1/T A B×ln(R) C×(ln(R))³这里 T 是开尔文温度R 是当前电阻。A、B、C 三个系数在 25 度附近由传感器厂家提供或者用三点法自己求解。常见 10k 3950 的 NTC参数大致在 A≈1.129×10⁻³、B≈2.341×10⁻⁴、C≈8.767×10⁻⁸ 附近但每颗传感器实际参数都不同最好从你的传感器数据手册里抄或者自己标定。我这里强烈建议用浮点计算 ln(R)STM32L4 的 FPU 虽有但数学库的 ln 函数还是要消耗少量时间不过 20SPS 的采样率下每秒钟算 20 次CPU 占用几乎可以不考虑。算完之后把开尔文温度减去 273.15 得到摄氏度输出前再加一个线性化的斜率校正——NTC 在 25 度附近灵敏度约 -4.4%/°C所以哪怕 ADC 电压误差 1mV温度误差也可能达到 0.3 度实际使用时最好做一次单点校准来校正分压电阻误差。4.4 校准流程不校准的 24 位 ADC 是浪费24 位 ADC 的线性度很好但系统级的精度受三个东西影响基准电压误差、分压电阻误差、传感器本身的个体差异。这三样都不是靠提高 ADC 位数能解决的必须做校准。我的推荐流程是先把系统打到一个已知温度点最简单是冰水混合物0℃。把传感器插入冰水稳定 5 分钟读取 ADC 码和理论值比较记下偏差。再把系统放到第二个已知温度点通常用精密恒温槽或者沸水100℃但海拔不同沸点也不同最好用标准温度计现场标定。两个点可以求出斜率和截距校准公式就是T_corrected T_raw × slope offset把这两个参数存到 STM32L4 的 Flash 里掉电不丢。每次产品出厂做一次两点校准配合低漂移基准系统精度做到 ±0.2℃RTD和 ±0.5℃热电偶是没问题的。如果现场不具备两点条件至少做一个单点偏移校准用精密参考温度计和系统放一起记下偏差补偿掉系统偏移。这个操作在 HVAC 现场调试时很常用——把参考温度计往管道里一插板子上调个偏移参数5 分钟搞定。5. STM32L4A6RG 软件架构与低功耗设计5.1 UART 接收DMA 空闲中断的组合读取 ADS122U04 数据看起来就是接收 3 个字节但如果用阻塞式 HAL_UART_Receive在等待数据时 CPU 被卡死系统啥也干不了。正确做法是用 DMA 接收 空闲中断UART IDLE来检测一帧数据的结束。基本思路配置 USART2 的 DMA 接收环形缓冲任意时刻数据来了 DMA 自动搬到内存。IDLE 中断触发时当前收到的字节数就是这一帧的长度。这种方式对连续转换模式下的不定长数据流特别好用ADC 持续往 UART 发 3 字节一帧的数据DMA 自动收不占用 CPUMCU 的 while 循环可以专心干别的活。DMA 初始化时注意ADC 的 UART 空闲时是空闲电平不会触发 IDLE 中断只有真正收到数据、然后线上恢复空闲时 IDLE 才置位。所以 IDLE 中断代表“一帧传完了”正是我们想要的边界。帧长度校验一定要做收到 3 字节才是一个完整帧多收少收都要清掉缓冲重新同步。工业现场电磁干扰可能把一帧数据冲散接收状态机要能在错帧后自动恢复。我的做法是开一个环形缓冲区每收到一帧就解析一次帧头和长度不匹配就继续找这样几帧数据被干扰也不会导致整个系统死锁。5.2 数字滤波工频抑制和时间常数Δ-Σ ADC 内置数字滤波器可以抑制工频方法就是选择跟 50Hz 成整倍数关系的数据速率。比如 20SPS、50SPS、60SPS 这些速率下数字滤波器的凹陷点正好落在 50Hz 或 60Hz 上。这是硬件就帮我们干完的事我们要做的就是别去选那些和工频没有整倍数关系的速率比如 330SPS 就很容易引入工频纹波。但选了低数据速率不代表读数绝对平稳。工业现场还有变频器的高频干扰、接触器的浪涌这些汇总到输入端可能超出 ADC 的差分输入范围导致转换结果异常。我的习惯是在 ADC 模拟输入端加一个简单的 RC 低通每路输入串联 1kΩ 电阻对地接 100nF 电容截止频率约 1.6kHz不会影响温度信号的带宽又能有效抑制高频噪声。这个 RC 在 PCB 上面积也不大强烈建议预留。软件上对温度这类“慢变量”再做一阶低通滤波很有效filtered filtered alpha × (new_value - filtered)alpha 的取值取决于你想要的系统响应时间。比如采样率 20SPS想要系统 2 秒的时间常数alpha ≈ 1/(2×20) 0.025。这样既能平滑波动又不会让系统响应变得迟钝。5.3 低功耗让整个系统睡眠HVAC 温控器如果常年在 220V 或者 24V 供电下功耗没那么敏感。但如果是电池供电的无线温度传感器低功耗就是刚需了。这里可以用 STM32L4 的 STOP 2 模式加 RTC 定时唤醒。设计思路是系统每 10 秒醒来一次给 ADC 供电如果 ADC 有独立供电电路可以用 MOS 管开关等待 20ms 稳定发启动转换命令等转换完成收数据算温度然后掉 ADC 电源进入 STOP 2。平均功耗可以做到几十微安到几百微安两节 AA 电池用一年以上没问题。注意 ADC 上电后不能立刻读数。基准和内部模拟电路需要建立时间去耦电容充电、基准稳定都需要时间经验值至少等待 5ms 后再发第一个转换命令转换完成后再等数据稳定 1 到 2 个数据周期再采数。这个等待时间看着费电但远比读回来的数据无效要省。还有一个小技巧如果 ADC 有独立的 RESET 引脚低功耗模式下把 RESET 拉低可以让 ADC 进入最低功耗状态。如果没有可以通过命令把 ADC 内部的所有电路都关成默认禁用状态再让 UART 总线空闲。更彻底的办法是在 ADC 的电源引脚加一颗负载开关由 MCU 的 GPIO 控制不给 ADC 供电就是真正的零功耗。6. 常见问题与排查实录6.1 读回的全是 0 或者满量程现象ADC 返回的原始码要么全是 0x000000要么全是 0x7FFFFF 附近。排查顺序第一步确认 MUX 配置没把输入选成不用通道。有人接的是 AIN0-AIN1寄存器里却选成了 AIN2-AIN3当然读不到信号。第二步确认传感器接线极性热电偶负极接反就是负满量程。第三步用万用表量传感器两端电压如果信号本身只有几毫伏而 PGA 设成 1 倍ADC 分辨率不足以分辨这么多信号也正常先把增益提上去。如果以上都正常检查基准电压对不对。内部基准未使能时会读到一个很奇怪的值。此时读寄存器确认配置是否生效命令写成错的地址静默失效是最难查的。6.2 UART 通信时好时坏这个我遇到太多了。首先查波特率。ADS122U04 的波特率通常由硬件引脚 BM 的电平状态决定而不是全靠软件配。上电时引脚状态不对实际波特率和你代码里配置的 115200 就不一致表现为第一帧能收到偶尔一两个字节后面全是乱码。把 BM 引脚按手册要求设定用示波器量 ADC TX 脚的实际波特率和 MCU 配置比对。第二查共地。两个板子各用各的电源UART 的 GND 不连信号完全没有参考点现象就是“偶尔通一下多数时候乱码”。UART 必须共地这没有商量的余地。第三查线路电容。高速率 115200 下如果线比较长而且没有屏蔽上升沿会变缓。示波器看到弯曲的边沿就说明线电容太大要么降波特率到 9600要么换带屏蔽的线或者加 RS485 收发器。6.3 温度读数跳变 ±0.5℃排除传感器本身噪声后先看是不是数据速率和工频没有匹配好。如果你选了 330SPS 而且现场有变频器那读数波动是必然的。降到 60SPS 或者 20SPS波形立刻平稳。这是最省事也最有效的手段。然后看模拟输入前级滤波。NTC 分压网络阻抗较高如果引脚没有对地电容外界电场会在高阻节点上感应出噪声电压。加一个 100nF 对地电容通常能解决但注意加的电容不能太大不然温度响应会变慢——RC 时间常数 Rntc×C 如果到几十毫秒20SPS 采样下读数会滞后明显。还有一种容易被忽略的情况ADC 断断续续的“漂移”其实是来自内部基准电压的温漂。温度变化时基准变了ADC 读到的码也会变。排查方法用外部基准换掉内部基准如果漂移消失就是内部基准的问题。此时就要考虑换外部基准或者做温度补偿。6.4 RTD 读数系统性偏大这是三线制接线的典型问题。故障现象是读数在 0 度时偏大 5 到 10 度而且偏差随温度变化不大。原因多半是电流源配置只有一个生效另一个电流源没有开或者接错点导致引线电阻没有抵消成功。用万用表测 RTD 两端实际压降再测 AIN0 和 AIN1 之间的 ADC 输入电压两者做对比就能看出来到底引线压降有没有被抵消。三线制的核心是两个电流源要“输出相同电流到同一点”少一根线、少一个电流源都是白搭。6.5 校准后的设备过几天又漂了这种“软漂移”首先要怀疑机械应力RTD 或热电偶的端子松动、线材受热应力产生额外热电势、PCB 焊点冷热疲劳。其次怀疑传感器是否受潮湿度变化会让 NTC 和 RTD 的绝缘电阻下降导致读数漂移。建议产品出厂前做一次高低温循环老化把应力释放掉再校准现场漂移会小很多。7. 实测数据与调试心得7.1 三组传感器的实测表现用油浴标定炉做了一轮对比测试参考温度计是二等标准铂电阻。K 型热电偶 PGA64 20SPS 软件线性化0 到 200 度范围内系统输出和参考最大偏差约 0.8 度冷端补偿用的是 ADS122U04 内部温度传感器如果能换成贴在端子上的高精度 NTC偏差还能压到 0.5 度以内。PT100 三线制 1mA 双电流源 60SPS 查表插值两点校准之后 0 到 150 度范围内偏差约 ±0.1 度这个精度拿来当现场校准参考问题不大。NTC 10k 外部 0.1% 分压电阻单点校准后在 10 到 40 度这个 HVAC 常用区间偏差约 ±0.3 度用在温控器上完全满足。数据速率的权衡在测试里感受很明显330SPS 下读数跳动 ±1 度降到 20SPS 后同一个传感器跳动 ±0.05 度。这就是 Δ-Σ ADC 的特性——它用时间换分辨率你要快就得不到那么高的稳定度。7.2 调试过程中的几个实战心得第一开发前期把 UART 收到的原始字节全部打印成 hex 到串口调试助手。不要急着写温度换算先把“配置是否正确下发”——通过读寄存器确认“转换数据是否正常”——通过看原始码范围确认“电压值是否符合传感器理论输出”——通过手动换算确认。这三层都通了再上温度算法不然出了问题你根本分不清是通信错了还是算法错了。第二原始码、电压、温度三个量同时打印。现场调试时客户说“读数不对”你先看原始码是否变化、电压是否合理、再判断是传感器问题还是算法问题。有些故障是热电偶断线原始码直接跳满量程你要是只看最终温度可能陷入“温度显示异常”的排查陷阱。第三PCB 上给 ADC 留一个跳线帽可以把 AIN0 直接短接到 AVDD 或 GND做自检用。上电自检时读一下这个已知电平点的 ADC 码如果和理论值差太多说明模拟前端已经出问题了系统可以主动报故障而不是默默输出错误温度。这个小设计成本为零但能省很多售后排查时间。7.3 后续可以扩展的方向这套平台其实还能继续做下去。ADS122U04 是 4 通道的目前只接了一路传感器还有三路空闲可以扩展成多路温度采集器。STM32L4A6RG 的资源也没用满加一个 Modbus RTU 从站协议让上位机通过 RS485 远程读取所有通道温度就是一个完整的工业温度采集模块。如果要做无线版本L4A6RG 的 LPUART 可以直接挂 LoRa 或 NB-IoT 模块传感器端和主控端之间依然是 UART 连接整个软件架构不用大改。我个人经验是模板化的信号链设计和分层软件架构是嵌入式产品做系列化的核心——硬件改不改看需求但 ADC 主控 UART 这条骨架可以一直沿用下去。
返回列表