
这活儿是从一台组合式空调机组的改造开始的。甲方要求监控盘管进出水温度、混风段、送风段总共 7 个温度点精度要求 ±0.2°C现场已经有两条 100 米长的布线通道环境里还并排跑着变频器和高功率风机。拿到需求后我没有马上画板子而是先把信号链在脑子里过了一遍传感器是什么信号多微弱走线有多长电源稳不稳采集板离主控板有多远。最终方案核心落在 ADS122U04IPWR 和 STM32L031C6 这一对组合上也就是标题里提到的用一颗带 UART 接口的 24 位 Δ-Σ ADC 配合一颗超低功耗 MCU把工业级和 HVAC 场景里的多点温度测量做扎实。这篇记录适合正在做嵌入式测温、暖通控制器、工业采集模块或者被模拟前端精度问题折磨过的朋友翻一翻。1. 项目背景为什么是 UART 接口的 24 位 ADC1.1 工业与 HVAC 温度采集的现场约束设计产品时选型顺序从来不是哪个芯片功能多而是现场给了什么约束。HVAC 机组的测点类型其实很杂盘管进出水是水管温度用套管式 PT100 或贴片探头风道温度有时用长探头冷凝器排气温度量程相对宽还有一些状态位只需要 NTC。这些传感器信号幅度从几百微伏到几百毫伏都不等普通 MCU 内置 12 位 ADC 在精度和可编程增益上都差一口气外接分立仪表放大器又面临温漂大、生产一致性差的问题。这时候一颗集成度高的 Δ-Σ ADC 就非常有吸引力。ADS122U04IPWR 是 TI 的 24 位转换器四个差分输入通道等效八个单端输入内部带 PGA 可编程增益放大器、低温漂基准电压源、两个匹配的恒流源而且直接引出 UART 接口。它等于把整个精密模拟前端全包了外围基本就是几个电容电阻硬件设计难度一下子降下来了。HVAC 现场另一个痛点是采集板和主控板经常分开安装为了减少走线阻抗和噪声耦合合理的拓扑是 ADC 小板尽量靠近传感器通过数字接口把结果送回主控。SPI 虽然快但四根线在稍长距离和强干扰下要额外做隔离和电平转换UART 只有两根数据线加光耦或数字隔离非常方便。STM32L031C6 自带的 USART 和 LPUART 正好配合这种结构。1.2 方案对比为什么不是 DS18B20、MAX31865 或 ADS1220我常被人问做温度采集用 DS18B20 不就行了吗这里要分场景。DS18B20 便宜、单总线但只有 12 位分辨率长期稳定性和互换性都一般做室温显示没问题做 ±0.3°C 以内的工业测量底气不足。MAX31865 是专门做 PT100/PT1000 的芯片集成度很高但它只能测电阻型传感器热电偶和电压型信号还得另想办法接口又是 SPI隔离时引脚多。ADS1220 本身性能很强但它和 STM32 之间走 SPI在需要电气隔离的工业现场要多花成本。既然有 UART 接口的 ADS122U04直接把 SPI 那几根线换成 TX、RX隔离和布线都省事。从系统成本看ADS122U04 加上一颗 STM32L031C6总价并不比专用 RTD 芯片 另一颗 MCU贵而且灵活性更高既能测 RTD也能测热电偶以后传感器类型变了不用重新画板。选这个组合的真正逻辑是用高集成度 ADC 把模拟前端的不确定性降到最低用 UART 接口降低系统连接成本再用 STM32L0 系列的低功耗特性让整个节点可以长期通电甚至未来改造成电池供电。这套架构不是某个单点的性能最强而是整体方案最扎实。2. ADS122U04 与 STM32L031 关键特性拆解2.1 ADS122U04 的模拟信号链先看 ADS122U04 内部结构大致是输入多路复用器 MUX、可编程增益放大器 PGA、Δ-Σ 调制器、数字滤波器、24 位转换结果最后从 UART 接口输出。它内部还集成了低温漂基准源、两个 IDAC 激励电流源、一个内部温度传感器。这里详细说下 Δ-Σ 架构。Δ-Σ 调制器用远高于奈奎斯特频率的速率对输入信号采样把量化误差推向高频然后通过数字滤波器把带外噪声滤掉。你可以把它理解成一把精度很高的秤连续称很多次再取平均最后的分辨率远高于单次称重。所以 ADS122U04 标称 24 位不是说每次转换都能稳定输出 24 个有效位而是在低数据速率下有效分辨率能达到 20 位以上。对于温度变化缓慢的 HVAC 场景20 SPS 的数据速率正好换来了极低的噪声温度分辨率做到 0.01°C 级别是够用的。它测 RTD 的原理是比率式测量用 IDAC 给传感器和参考电阻提供同一个电流ADC 同时测量两个电压的比值。因为电流完全一致恒流源的实际电流精度、温漂都不会进入最终结果省掉了一大块校准工作。代价只是需要一颗高精度、低温度系数的参考电阻。2.2 STM32L031C6 的角色定位STM32L031C6 是 Cortex-M0 内核主频最高 32 MHz内置 32 KB Flash、8 KB RAM运行模式功耗大约 87 μA/MHz停止模式加 RTC 唤醒不到 1 μA。这颗芯片在项目里的定位很明确它不负责复杂的信号处理而是做 ADC 的初始化、数据读取、温度换算和控制逻辑。在这个项目里STM32L031C6 的具体任务包括上电后配置 ADS122U04 的寄存器设置输入通道、PGA 增益、转换速率和 IDAC 电流定时读取转换结果把原始码换算成电阻和温度再把温度值通过 RS-485 或者本机总线送到主控。顺便还能驱动显示屏、按键、继电器等外设。8 KB RAM 对这类任务绰绰有余32 KB Flash 存完固件和查找表之后还有不少余量。有人可能会问L031 的 UART 最高速率够不够ADS122U04 在默认 8N1 格式下我实际用 9600 波特率跑得很稳。HVAC 的温度数据量很小单通道每秒读 20 次一次读四个字节加上命令字节也就 100 字节每秒9600 波特率完全能承受。如果板上距离短也可以直接上 115200但现场长线环境还是低速更可靠。2.3 工作温度、封装与供应链友好度ADS122U04 的供电范围是 2.3 V 到 5.5 V可直接用 3.3 VSTM32L031C6 同样是 1.8 V 到 3.6 V系统统一 3.3 V逻辑电平匹配不用做电平转换。ADC 的工作温度范围是 -40°C 到 125°CHVAC 户外机组的电控箱夏天可能到 70°C冬天夜间零下这个范围足够。STM32L031C6 也提供 -40°C 到 125°C 的工业级选项。封装方面ADS122U04IPWR 是 TSSOP-16手工焊接、AOI 检测都方便STM32L031C6 是 LQFP-48常规 PCB 加工和贴片没有任何难度。选型落到这两个具体型号是因为它们在市场上流通量大、采购周期短不会出现画完板子买不到料的情况。3. 硬件设计实操信号链、电源与布局3.1 传感器选型NTC、PT100 还是 PT1000先把传感器的选型说透。HVAC 里常见三类NTC 热敏电阻便宜、灵敏度高、响应快但非线性严重、互换性差、时间长了会漂移。适合消费级室温探头不适合做计量级温度。PT100经典工业测温元件0°C 时阻值 100Ω精度高、稳定性好。缺点是自身阻值小对导线电阻特别敏感远距离测量必须三线或四线制。PT1000阻值是 PT100 的十倍自热效应更小对线阻和接触电阻的敏感度低很多。HVAC 和仪表行业越来越流行。我建议新项目优先用 PT1000。同样的 1 米长铜导线在 PT100 上可能带来 0.3°C 级误差在 PT1000 上就只有 0.03°C 级。如果现场传感器已经固定是 PT100那就老老实实做三线制把导线电阻的影响降到最低。3.2 模拟输入电路滤波、保护和差分对称传感器信号很微弱模拟前端必须做滤波和钳位保护。我用一阶 RC 差分低通滤波器截止频率放在几百赫兹到 1.6 kHz 之间。以 20 SPS 的转换速率来说这个带宽足够宽不会拖慢温度响应又能滤掉变频器产生的高频谐波。算一下R 取 1kΩC 取 100nF截止频率约 1.6 kHzfc 1 / (2πRC) ≈ 1.6 kHz。电容务必选 C0G/NP0 材质X7R 在直流偏压下容量会下降介质损耗也会影响测量稳定。输入端我还加了一对肖特基二极管 BAT54S 做钳位配合串联电阻限制电流把瞬态高压限制在电源轨以内。HVAC 现场 220V 动力线和信号线走同一个线槽的情况不少见这个保护成本很低但能避免大量售后问题。差分输入的两条走线必须等长、对称、紧贴走不能跨分割区。如果板子上还有 DC-DC 或继电器驱动ADC 的模拟电源要用磁珠加电容单独滤波避免开关噪声通过电源耦合进参考电压。3.3 参考电压与参考电阻的选择比率式 RTD 测量中最核心的器件是那颗参考电阻。以我常用的配置为例PT1000IDAC 电流 1mA参考电阻选 2kΩ那么在参考电阻两端产生的参考电压 Vref 1mA × 2kΩ 2V。PT1000 在 0°C 时阻值 1000Ω测量电压 1V约为参考电压的一半150°C 时 PT1000 约 1573Ω测量电压 1.573V约为参考的 78%动态范围用得很充分。参考电阻的精度直接进最终结果所以我选 0.1% 精度、温度系数 10ppm/°C 的精密薄膜电阻。量产成本压力大的话25ppm/°C 也能用但温漂性能要自己评估。这里不建议用普通厚膜电阻温度系数动辄 100ppm/°C现场温差一大误差会非常难看。3.4 PCB 布局的几条硬经验布局这关我踩过几次坑总结几条硬经验ADC 放在传感器接口连接器旁边模拟走线越短越好。晶振、继电器驱动、DC-DC 这些噪声源远离 ADC 的 REFP/REFN 引脚。底层大面积铺地模拟地和数字地单点连接不要在 ADC 下面走数字信号线。UART 的 TX、RX 串联 1kΩ 电阻既能抑制振铃又能在异常情况下保护引脚。REFP 和 REFN 之间放 10μF 低 ESR 陶瓷电容这个很关键后面调试部分还会提到。4. 固件实现细节4.1 ADS122U04 的 UART 命令协议ADS122U04 的 UART 默认是 8 数据位、无校验、1 停止位。它把 ADC 的寄存器操作和转换结果都封装成命令帧常用的命令如下命令字节值说明RREG0x20 寄存器地址读寄存器ADC 返回一个字节WREG0x40 寄存器地址写寄存器需要紧跟一个数据字节RDATA0x1C读取一次转换结果返回 4 字节RDATAC0x1D进入连续读取模式只要 ENS 拉低就一直输出SDATAC0x1F退出连续读取模式START0x08启动一次转换PWDN0x02进入掉电模式RESET0x06复位所有寄存器时序上需要注意写寄存器是一发一应但 ADC 的响应不是立即出现的中间要留一点时间。读数据时发送 RDATA 后等待响应帧响应帧的第一个字节是状态字节包含 DRDY 位后三个字节才是 24 位转换结果。如果通信状态不明最稳妥的办法是先发 RESET再重新初始化。4.2 STM32L031C6 的 UART 初始化我用的是 HAL 库也可以用寄存器操作核心配置一样。这里给出一个最小初始化#include stm32l0xx_hal.h UART_HandleTypeDef huart1; void MX_USART1_UART_Init(void) { huart1.Instance USART1; huart1.Init.BaudRate 9600; huart1.Init.WordLength UART_WORDLENGTH_8B; huart1.Init.StopBits UART_STOPBITS_1; huart1.Init.Parity UART_PARITY_NONE; huart1.Init.Mode UART_MODE_TX_RX; huart1.Init.HwFlowCtl UART_HWCONTROL_NONE; huart1.Init.OverSampling UART_OVERSAMPLING_16; if (HAL_UART_Init(huart1) ! HAL_OK) { Error_Handler(); } }注意引脚复用查一下 STM32L031 的数据手册确认 USART1_TX 和 USART1_RX 对应的是哪两个引脚然后在 HAL_UART_MspInit 里把 GPIO 模式改成 AF 模式。一个容易犯的错是 GPIO 时钟没开UART 怎么调都不通。另外系统时钟如果用内部 HSI16UART 波特率误差要算一下如果误差超过 ±3%ADC 端可能收不到正确的起始位。4.3 ADS122U04 初始化与寄存器配置ADS122U04 上电后我建议先发 RESET 命令等 100ms再发 SDATAC 退出可能的连续读取状态最后逐寄存器写配置。下面是一份可读性优先的演示代码具体寄存器位字段要对着数据手册核对static void ads122u_write_reg(uint8_t reg, uint8_t value) { uint8_t frame[2] { 0x40 | reg, value }; HAL_UART_Transmit(huart1, frame, 2, 50); } void ads122u_init(void) { uint8_t cmd 0x06; // RESET HAL_UART_Transmit(huart1, cmd, 1, 50); HAL_Delay(100); cmd 0x1F; // SDATAC HAL_UART_Transmit(huart1, cmd, 1, 50); // REG0AIN0/AIN1 差分输入、使能 PGA、增益 1 ads122u_write_reg(0, 0x00); // REG1内部基准、单次转换模式、20SPS ads122u_write_reg(1, 0x00); // REG2参考源配置保持默认按原理图调整 ads122u_write_reg(2, 0x00); // REG3IDAC 电流源路由和电流值按原理图设置 // 例如 ads122u_write_reg(3, 0xA0); }第 3 个寄存器一般要设 IDAC 的电流大小和流向这个必须和硬件电路对应起来。如果你用 1mA 激励就要在 REG3 里把 IDAC 电流设为对应的编码同时把 IDAC 输出引脚映射到实际连接传感器的引脚上。不同批次的寄存器位可能略有差异最稳妥的做法是每次拿到样品先读一遍所有寄存器确认复位默认值和手册一致。4.4 单次转换模式与读取流程HVAC 多点测量我推荐用单次转换模式流程清晰功耗也可控。步骤如下配置 MUX 选择当前要测的通道。发送 START 命令启动转换。等待转换完成20SPS 对应 50ms代码里延时 60ms 比较稳。发送 RDATA 命令读取 4 字节响应。把后 3 字节拼成 24 位有符号数。读取代码示例int32_t ads122u_read_once(void) { uint8_t cmd; uint8_t buf[4]; int32_t code; cmd 0x08; // START HAL_UART_Transmit(huart1, cmd, 1, 50); HAL_Delay(60); // 等待 20SPS 转换完成 cmd 0x1C; // RDATA HAL_UART_Transmit(huart1, cmd, 1, 50); if (HAL_UART_Receive(huart1, buf, 4, 100) HAL_OK) { code ((int32_t)buf[1] 16) | ((int32_t)buf[2] 8) | buf[3]; if (code 0x800000) code - 0x1000000; // 转成有符号数 return code; } return 0; // 读取失败 }如果切换通道后第一个转换结果不好可以读两次第一次的结果丢弃第二次作为有效值。我的实测经验是通道切换后残留电荷会让第一次读数偏移几个 LSB丢掉第一次就干净了。4.5 校准系数存储STM32L031C6 内部没有 EEPROM只有 Flash。校准系数可以放在最后一个 Flash 扇区但要考虑擦写寿命和写操作对程序的冲击。更稳妥的做法是在板上加一颗几毛钱的 I2C EEPROM比如 AT24C02出厂时通过上位机写入每路传感器的偏置和增益系数。HVAC 大批量生产时每台设备在恒温槽里做两点校准系数存进 EEPROM运行逻辑在启动时读取。5. 温度计算、标定与精度实测5.1 从 ADC 原始码到电阻值ADS122U04 的转换结果是 24 位二进制补码。差分输入下满量程对应的码值是 2^23。如果参考电压 Vref 由同一个激励电流在参考电阻上产生那么 RTD 电阻可以这样算R_rtd (Code / 2^23) × R_ref举个例子Pt1000IDAC1mARref2kΩVref2V。0°C 时 RTD 阻值 1000Ω测量电压 1V占满量程一半Code 约等于 4194304。反算电阻R_rtd 4194304 / 8388608 × 2000 ≈ 1000Ω完全对得上。这个公式成立的前提是激励电流流经 RTD 和参考电阻的路径完全一致而且 ADC 的参考输入正确跨在参考电阻两端。比率式测量最大的优势是 IDAC 电流的绝对值漂移不掉进结果AVDD 电源电压波动也会被抵消。设计时唯一要保证的是电流在测量窗口内稳定不要求长期精密。5.2 从电阻值到温度PT1000 在 0°C 到 850°C 范围可以用 Callendar-Van Dusen 方程描述R(T) R0 × (1 A×T B×T²)其中 R0 1000ΩA 3.9083×10⁻³B -5.775×10⁻⁷。0°C 以下再加一个三次项R(T) R0 × (1 A×T B×T² C×(T-100)×T³)C -4.183×10⁻¹²。实际代码里我一般在 -40°C 到 150°C 之间用查找表加线性插值分辨率 0.1°C 的表格只有 1900 个点Flash 占用很小。想更精确在线性插值结果上做一次牛顿迭代就能把误差压到 0.01°C 以内。Cortex-M0 没有硬件 FPU但温度换算频率很低用单精度浮点完全没有压力。5.3 标定方法单点与两点校准即使硬件设计得当误差来源依然存在参考电阻本身的精度、ADC 的偏移和增益误差、传感器自身的公差。A 级 Pt1000 在 0°C 时标准公差就有 ±0.15°C所以整机想做到 ±0.2°C必须校准。单点校准适合偏移误差为主的系统在已知温度下测出实际偏差修正整个量程的偏移量。两点校准更完整在 0°C 附近和 100°C 附近分别放标准温度源记录两组误差算出增益修正系数 a 和偏移修正系数 b使显示温度 y a × x b。校准系数存到外部 EEPROM生产线上每台设备跑一遍快速校准几分钟搞定。5.4 样机实测数据参考我在样机上用冰点槽和恒温槽做了对比参考温度计是 Fluke 标准表。校准后的一组成果如下测点标准温度样机读数偏差冰点槽0.00°C0.04°C0.04°C恒温槽25.00°C25.02°C0.02°C恒温槽70.00°C69.94°C-0.06°C恒温槽100.00°C100.08°C0.08°C这个结果说明经过两点校准后系统在 0°C 到 100°C 范围内可以稳定在 ±0.1°C 以内。需要注意的是样机数据是理想实验室条件下得到的量产时每台设备的传感器个体差异、安装方式、走线长度都会影响最终精度所以生产校准流程和质检标准同样重要。6. 调试中的典型问题与解决实录6.1 UART 通信无响应排查上电后发 RDATAMCU 收不到任何字节这是最常见的坑。排查步骤先用逻辑分析仪抓 TX 线确认 MCU 确实发出了完整波形波特率偏差不能太大。STM32L031C6 如果内部时钟没配准9600 波特率可能差出 3% 以上。检查 ADC 的 RESET 引脚。数据手册要求上电后等待复位完成我原来初始化太快后来在 RESET 命令后加了 100ms 延时问题就消失了。确认电平匹配。ADC 用 3.3V 供电时和 MCU 直连没问题如果 ADC 单独用 5VTX 线上最好串 1kΩ 电阻。检查 ADC 是否被之前配置成了连续读取模式。这种情况要先发 SDATAC再发 RESET顺序不能反过来。6.2 读数跳变与参考电容的教训有一次样机把 ADC 放得离 DC-DC 很近测量结果的低几位一直在跳。我最初以为是布局问题换了几个滤波电容都没用。最后按数据手册要求在 REFP 和 REFN 之间并联一颗 10μF 低 ESR 陶瓷电容同时在 AVDD 到 GND 之间加 1μF 和 0.1μF 去耦跳变立刻小了下去。原理是 Δ-Σ ADC 在采样瞬间需要参考源快速补充电荷参考电容太小会导致参考电压出现毛刺。这颗电容的位置比电源去耦电容更讲究要靠近 REFP/REFN 引脚走线短而粗不能和数字信号共用一个过孔。6.3 长导线压降与两线制陷阱最早用过两线制接 PT100现场导线长 5 米读出来的温度比实际高了 1°C 多。算一下就知道问题在哪铜导线每米大约 0.1Ω两线制来回 10 米就是 1ΩPT100 本身才 100Ω1Ω 的导线电阻直接引入约 2.5°C 的误差。换成三线制后导线电阻通过差分测量和恒流源补偿问题彻底消失。这里有个经验现场线长超过 2 米就不要用两线制要么三线要么四线。软件补偿只能补固定线阻铜的电阻率随温度变化现场温差一大软件补偿会越补越乱。6.4 上电时序与反向供电HVAC 控制器里常见 24V AC 转 5V 再转 3.3V 的供电架构。有次测试 24V 断电后MCU 已经复位了但 ADS122U04 还在微弱工作量了一下发现是 MCU 的 UART TX 引脚通过内部保护二极管给 ADC 反灌了电流。解决办法是在 UART 的 TX 和 RX 线上加 10kΩ 下拉电阻同时把 ADC 的 RESET 引脚用 10kΩ 上拉到高电平确保 MCU 掉电时 ADC 处于复位状态。这个小改动成本极低但对现场故障率影响很大。7. 方案扩展与配置速查7.1 这套组合还能做什么除了 RTD 测温ADS122U04 的高增益 PGA 也很适合热电偶。把增益设到 16 到 64 倍配合内部温度传感器测量冷端温度加上热电偶查表就能做多通道热电偶采集。STM32L031C6 的 LPUART 可以在低功耗模式下定时唤醒结合 ADS122U04 的掉电模式整个节点的平均功耗可以做到几十微安级别非常适合智能温控阀、无线温度标签这类电池供电场景。工业场景中还可以把 UART 信号通过 RS-485 收发器转成差分总线多个采集点挂到同一条总线上主控轮询各节点。这样做的好处是 ADC 依然靠近传感器而数字总线可以拉得很远。不过要注意每个节点必须有独立的地址识别机制ADS122U04 本身没有地址地址逻辑要在 STM32L031 的固件里自己实现。7.2 我的一些真实教训做这个项目前后花了不少时间真正提升系统稳定性的往往不是高大上的算法而是这些细节不要迷信 24 位这个数字要关心的是有效分辨率。20 SPS 下低噪声是它的优势但数据速率一高跳字明显变大选型时要按实际速率评估。模拟前端越简单越好但滤波电容和参考电容绝对不能省。原理图评审时要专门检查 IDAC 的回流路径电流从哪里出来最后必须回到同一个参考电阻上。回流路径错一次整个量程都会错。固件要加超时和重试机制不能死等 UART 响应。现场干扰导致偶发通信错误是正常的重点是怎么恢复。7.3 可复用的最小配置速查表最后给一份可以直接抄作业的配置速查项目配置传感器PT1000三线制IDAC 电流1mA参考电阻2kΩ0.1%10ppm/°CADC 输入AIN0/AIN1 差分PGA 增益1数据速率20 SPS转换模式单次转换 START 命令UART96008N1电阻换算R Code / 2^23 × Rref温度换算CVD 方程或查找表这套配置在 HVAC 控制器、工业采集模块、实验室恒温设备上都可以直接套用改动传感器类型或者量程时只需要调整 IDAC 电流和增益两个参数。我这几年做测温项目最大的体会是温度测量看着简单真正决定成败的往往是那些不起眼的地方参考电容、三线制、波特率余量、上电时序。ADS122U04 和 STM32L031 这套组合算不上花哨但足够稳适合想把工业级测温做扎实又不愿意在模拟前端上无限投入的项目。回头如果要做多通道温控节点我还会沿用这个架构只是会把 MCU 换成更低功耗的型号把整个节点的功耗再压一档。