搞工业温度采集这块时间长了手里总会有几套顺手又省心的组合。最近帮客户做HVAC风管和工业设备表面温度监测的样机主控用了STM32L152ZD前端采集选了TI的ADS122U04IPWR。这颗芯片最吸引我的地方是它作为一颗24位Δ-Σ ADC居然直接走UART接口不占SPI把信号链和低功耗MCU搭配得很舒服。这篇就把这套方案从器件选型、硬件布局到固件计算和实测排障的完整过程写出来给准备做类似温度测量的朋友一个可以直接参考的样本。1. 方案选型为什么是ADS122U04IPWR配STM32L152ZD1.1 这颗UART接口的24位ADC到底特殊在哪ADS122U04本身是一颗四通道、24位的Δ-Σ型ADC带可编程增益放大器PGA、内部2.048V基准电压、两路可编程激励电流源IDAC还集成了芯片温度传感器和两个模拟多路开关。这些功能放在一颗TSSOP-16的小封装里在工业温度采集场景里几乎没有多余的浪费。它最特殊的一点是通信接口为UART。传统ADC基本都是SPI或I2CSPI虽然速度快但需要CS、SCLK、MOSI、MISO至少四根线长线传输时时钟信号容易辐射干扰I2C速率慢、地址冲突也麻烦。UART接口只需要TXD和RXD两根线板级通信时布板简单和MCU之间只要共地就行再往上走还能用现成的隔离芯片做电气隔离。我在实际项目里往往还要把数据传给RS485总线UART接口可以直接对接省去一层协议转换。同系列的ADS1220是SPI版本ADS122U04则是把SPI换成了UART。你可能觉得多此一举但对一些老旧产线上的设备或是对SPI时序敏感的场景用UART简直是降维打击。而且这颗ADC的波特率可以配置从9600bps一直支持到1.2Mbps数据速率和通信速率分开配置采集慢速温度信号时用低波特率反而更稳。1.2 STM32L152ZD能打些什么STM32L152ZD是ST超低功耗家族中的一员Cortex-M3内核主频32MHz带最高384KB Flash和80KB左右的SRAM。这颗芯片虽然算力不算炸裂但在温度采集这个场景里绰绰有余处理热电偶线性化、RTD查表、PID控制全都够用。它有几个点非常贴合HVAC和工业应用。第一工作电压范围宽2.0V到3.6V都能跑配合内部多级低功耗模式对电池供电的无线传感器节点很友好。第二串口资源丰富多个UART可以分别连接ADC、RS485收发器和调试口彼此不打架。第三工业级温度范围在-40°C到85°C环境里稳定运行这比很多消费级MCU适合做设备长期部署。选它没选STM32F系列看重的是L系列在低功耗和引脚丰富度之间的平衡。也有不少人问为什么不用带24位ADC的高端MCU比如STM32G4系列内部就有高精度ADC。但工业温度测量的难点除了采样分辨率还有传感器激励、冷端补偿、PGA增益匹配这些整链路的配合外置ADC把模拟前端做得更干净后端MCU专注逻辑和通信抗干扰能力也更强。这种分立方案在维护和升级上也更灵活——传感器类型变了换ADC配置或换前端电路就行不用动整个主控板。1.3 整机数据链路是怎么设计的整套系统的数据链路分四段传感器信号进来经过RC滤波和IDAC激励进入ADS122U04的模拟输入通道ADC完成24位转换后通过UART把原始码交给STM32L152ZDMCU负责做电压换算、线性化、校准和滤波最终输出温度值温度值一方面本地显示或者通过RS485上传另一方面也能作为HVAC控制回路的反馈量。这里要注意UART虽然只有两根线但通信协议还是要自己定的。我的做法是MCU作为主机ADS122U04作为从机所有转换由主机发命令触发。这样整个系统同步性最好不会出现ADC自己转完但MCU还在忙别的导致数据堆积的问题。命令帧我固定用1个字节的指令加可选的寄存器地址和数据返回数据也是固定长度的原始码字节流方便用状态机解析。2. 硬件设计传感器接入与PCB布局的关键细节2.1 热电偶、RTD、NTC三种传感器怎么接不同温度传感器接入ADS122U04的方式差异很大选型这一步直接决定后面电路形态。热电偶输出的是微伏级的电压信号K型热电偶大约40µV/°C测1000°C也才40mV上下。这时候要用ADC内部PGA放大增益先设到16倍或32倍比较合适。热电偶本身没有激励需求但必须做冷端补偿我习惯用ADS122U04内部的集成温度传感器同时测冷端温度虽然精度比外置PT100冷端补偿略低但胜在省事HVAC场景里常温环境用内部传感器足够。热点偶接入时还要注意极性正负极接反的话读数是负值。RTD铂电阻是电阻型传感器PT100在0°C时是100ΩPT1000是1000Ω。RTD需要恒流源驱动直接用ADS122U04内部的IDAC提供激励电流最方便。两线制接线最简单但导线电阻会直接叠加进测量结果三线制用两根相同规格的导线分压补偿工业现场最常用四线制精度最高适合计量级场合。我的建议是HVAC设备用三线制PT1000功耗小、导线上压降影响低配合IDAC的1mA电流0°C时激励电压才1V给ADC留的输入范围很充足。NTC热敏电阻在HVAC里最常见成本低、灵敏度高但线性度差只适合-20°C到80°C的舒适度检测。NTC接入电路通常是电阻分压方式把NTC接在上臂或下臂另一端接参考电压分压中点进入ADC。分压电阻最好用高精度低温漂的薄膜电阻我吃过这方面的亏普通贴片电阻温漂200ppm/°C环境变个5°C就能带来不小的误差。三种传感器的接入方式我列个表方便对比传感器类型输出信号是否需要激励推荐PGA增益常用接线方式典型应用场景热电偶K/J/T型µV级电压不需要16~128倍直接差分输入工业炉温、高温管道RTD PT100/PT1000电阻变化需要IDAC恒流1~4倍三线或四线HVAC管路、现场校准NTC热敏电阻电阻变化需要分压参考1倍分压电路风管温度、室内温控2.2 激励电流源和参考电压设计这步决定精度上限ADS122U04内部有两路可配置的IDAC激励电流源电流范围从10µA到1.5mA可编程。用在RTD测量上是一个很核心的精度杠杆。选激励电流时有一个平衡电流大了传感器上压降大信噪比高但自热效应也明显PT100在1mA下发热功率是0.1mW长期稳定还能接受电流小了信号幅度小容易被噪声淹没。我实测下来PT100用500µA到1mA之间比较合适PT1000用250µA到500µA。还要注意激励电流会流经参考电阻产生参考电压这个参考电阻的温度漂移会直接进入测量链路一定要选温漂在±5ppm/°C以下的精密电阻最好是金属箔电阻或精密薄膜电阻。参考电压可以选内部2.048V基准也可以外部输入。内部基准好处是集成、少一个器件但温漂系数一般在几十ppm/°C要求高的场合我会用外部低温漂基准芯片再把基准引脚接到ADC的REFP。对HVAC这种环境温度变化较大的应用如果目标是整个温度范围内误差小于0.1°C外部基准基本是必须的。另外ADC的模拟电源AVDD和数字电源DVDD建议分开走即便都用3.3V也要各自加磁珠和去耦电容。ADS122U04的电源抑制比虽然不错但24位ADC对电源纹波极其敏感电源上那点几十毫伏的毛刺放大到24位编码上可能就是几十个LSB的跳变。2.3 PCB布局和长线走线的几个细节PCB布局这块我踩过不少坑总结几条实操经验。第一模拟输入走线要短而粗远离数字走线和开关电源。ADS122U04的模拟输入引脚是高阻抗输入走线稍微长一点就容易拾取噪声我一般把RC滤波电容尽量靠近ADC引脚放让高频干扰在进入ADC之前就被滤掉。第二ADC下方的地平面要完整模拟地和数字地在ADC芯片下方单点连接不要让数字电流穿过模拟区域。如果板子上还有继电器或可控硅必须把它们和模拟区用开槽隔离这在HVAC控制板里特别重要因为空调压缩机的启停会产生很强的电磁干扰。第三UART通信线虽然只有两根但也要注意它们和模拟输入线的间距。RXD和TXD上的开关噪声会通过空间耦合到模拟输入端我给UART线串了33Ω电阻并把它们走在远离模拟输入的另一层。第四如果传感器线从板外接入长度超过1米我建议输入端加共模电感和TVS管并把线缆做成双绞屏蔽线。屏蔽层只在传感器端或采集板端单点接地两端都接地会形成地环路反而引入工频干扰。前阵子客户现场就是温度波动像心跳一样规律后来查到是PLC控制柜和采集板之间地电位差叠加进了信号线。3. 固件实现UART通信与温度换算核心代码3.1 初始化ADC和UART的代码骨架ADS122U04通过UART接收命令MCU侧只要把UART波特率配成和目标一致就可以通信。我先给一个STM32L152ZD的HAL库初始化骨架重点不在库函数而在配置思路。/* UART1 for ADS122U04 */ UART_HandleTypeDef huart1; UART_HandleTypeDef huart2; void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin GPIO_PIN_9|GPIO_PIN_10; /* PA9: TX1, PA10: RX1 */ GPIO_InitStruct.Mode GPIO_MODE_AF_PP; GPIO_InitStruct.Pull GPIO_PULLUP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate GPIO_AF1_USART1; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); } 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(); } }UART波特率我最初用115200后来实际项目中因为线缆较长和隔离器延迟降到9600反而更稳定。温度信号本身变化慢9600bps每秒也能传几十次完整转换结果完全够用。ADC初始化部分的要点是配置寄存器而不是传输大量数据。ADS122U04内部有数个配置寄存器我用宏定义把命令封装成以下形式具体命令码和寄存器位定义要以你手里的数据手册为准/* 复位ADC重新加载默认寄存器 */ void ADS122U04_Reset(void) { uint8_t cmd CMD_RESET; HAL_UART_Transmit(huart1, cmd, 1, 10); HAL_Delay(2); } /* 向指定寄存器写入配置 */ void ADS122U04_WriteReg(uint8_t reg_addr, uint8_t reg_val) { uint8_t buf[3]; buf[0] CMD_WREG | (reg_addr 0x07); buf[1] 0x00; buf[2] reg_val; HAL_UART_Transmit(huart1, buf, 3, 10); } /* 触发一次转换并读取24位原始数据 */ uint32_t ADS122U04_ReadTemp(void) { uint8_t cmd CMD_START; uint8_t raw[3] {0}; HAL_UART_Transmit(huart1, cmd, 1, 10); HAL_UART_Receive(huart1, raw, 3, 100); return ((uint32_t)raw[0] 16) | ((uint32_t)raw[1] 8) | raw[2]; }配置的关键参数有四个输入多路开关选择哪一路通道、PGA增益设多少、数据速率多少、是否开启IDAC电流源。调试时我习惯先用内部温度传感器验证ADC本身是否正常读到片上温度大约25°C再切到外部传感器通道这样能把问题快速分隔到ADC端还是传感器端。3.2 从原始码到物理温度的换算公式ADS122U04返回的是24位二进制补码数据看起来是一串无符号整数实际上正负温度都要正确处理。我先把原始码转成有符号数再换算成电压int32_t raw_signed (int32_t)raw_uint; if (raw_signed 0x800000) { raw_signed | 0xFF000000; /* 扩展到32位有符号 */ } double vref 2.048; /* 实际使用的基准电压 */ double gain 32.0; /* PGA增益 */ double voltage (double)raw_signed * vref / 8388608.0 / gain;这里的8388608就是2的23次方对应24位数据去掉符号位后的满量程。K型热电偶的电压-温度关系近似线性但工程上要用NIST多项式或分段线性表才能做到0.1°C级别。我做了一个简化版在0°C到500°C区间用查表加线性插值表点间隔25°C每两个点之间线性化实测误差在0.15°C以内。查表法比NIST多项式省算力对STM32L152ZD这种主频不高的MCU更友好。热电偶测量还有一个必须处理的问题冷端补偿。ADS122U04采集的是热端和冷端的电势差如果冷端在25°CK型热电偶测300°C时输出约11.4mV但此时ADC实际看到的电压还差一个25°C对应的补偿电势约1.0mV得把这个值加上才能得到真实热端温度。具体流程是先读ADC内部温度传感器得到冷端温度查表得到冷端等效电压把ADC测得的电压加上冷端电压再查总电压对应的温度。很多新手漏掉这一步结果温度怎么都对不上。RTD的换算简单一些用比例法。定义Rref是0°C时的标准电阻Vrtd是RTD两端电压Vref是基准电阻两端电压则Rt Rref * Vrtd / Vref。PT100的电阻-温度关系虽然有Callendar-Van Dusen公式但0°C到100°C区间直接用线性系数0.385Ω/°C也够HVAC用我在0°C到50°C区间实测误差小于0.1°C。NTC的换算我用Steinhart-Hart公式1/T A Bln(R) Cln(R)^3三个系数从NTC厂商数据手册拿计算量稍大但对主频32MHz完全没压力。如果用查表法B常数10K的NTC在25°C附近斜率大约是-4.4%/°C非常高也就是温度变0.1°C会引起电阻千分之几的变化ADC一个LSB对应的温度分辨率能做到0.002°C级别前提是参考电压足够稳。3.3 校准、滤波和故障保护24位ADC的原始精度很高但系统级误差往往来自传感器本身和信号链路的系统性偏差所以校准环节不能省。我做了两级校准。第一级是零点校准在传感器探头放在0°C冰水混合物里时记录ADC原始码把它作为偏移量存进Flash后续每次测量都减掉这个偏移。第二级是增益校准用一个高精度温度源或精密电阻箱模拟已知温度测出实际值和理论值的比例系数并存入。校准完以后正常测量的误差基本能压到设备标称精度以内。滤波方面温度信号属于缓变信号我推荐滑动平均加限幅的组合。滑动平均窗口取8到16点在0.5Hz采样率下也就带来1到2秒的延迟对HVAC系统完全可以接受。限幅滤波是防止传感器断线或接触不良时出现离谱值相邻两次温度采样变化超过5°C就判定为异常直接丢弃并计数连续多次异常就报传感器故障。这个方法简单但非常有效现场出现线缆松动时不会把假数据送去控制回路。固件里还要处理UART通信超时。ADC偶尔会因为干扰没有响应MCU侧用HAL_UART_Receive带超时的接收函数超时后重发命令。连续重发超过3次就把这条通道标记为通信故障接着去查硬件不能无限等下去。4. 实测问题与排查速查实录4.1 现场踩过的几个坑第一个坑是UART电平不匹配。ADS122U04的IO电平取决于DVDD如果DVDD接了5V而STM32是3.3VTXD直接对接会把MCU的引脚钳位到不安全状态。我第一次搭测试板时忽略了这点结果STM32的UART引脚发热、通信时好时坏。后来改成RXD上加一个2K串联电阻加钳位二极管的方式或者直接用双向电平转换芯片才解决。这个必须在原理图阶段就确认好不能靠运气。第二个坑是参考电压被IDAC拖垮。我最初参考电阻用了普通0805贴片电阻温漂大概100ppm/°C实验室环境里看不出来拿到客户厂房后环境从20°C到35°C变化温度读数跟着漂了将近0.8°C。换成精密电阻后立竿见影。这个问题在HVAC现场特别容易碰到因为设备经常在室外机或机房这种温度波动大的地方。第三个坑是传感器线缆太长导致的共模干扰。有一次现场安装距离大约30米走线经过变频器附近温度读数跳得厉害。我在ADC输入端加了共模电感并在软件里把数据速率降到20SPSΔ-Σ ADC的数字滤波特性把高频干扰滤掉了不少跳变幅度骤降。如果还压不住就得考虑在传感器端加变送器把信号先转成4-20mA电流环再用采样电阻还原抗干扰能力完全不同级别。4.2 问题排查速查表把这次调试过程中遇到的现象、原因和解决思路整理成表格方便现场直接对照。现象可能原因排查方法与解决措施UART完全无响应波特率不匹配/电平不匹配/接线错误示波器抓RXD引脚波形确认电平幅值和波特率先用USB转TTL直连ADC验证通信读数固定为满量程传感器断线/输入悬空检查传感器接线断开ADC输入量转换引脚电压热电偶断线时ADC会读到上拉电压读数波动大电源噪声/参考电压不稳/干扰耦合增大RC滤波检查AVDD去耦电容降低数据速率改用屏蔽线温度整体偏移冷端补偿未做/校准偏移丢失检查冷端补偿代码重新做零点校准确认Flash里的校准系数是否被意外覆盖低温和高温段偏差不一致传感器非线性/增益校准不准换用查表插值或专业拟合公式重新做两点或多点校准上电后一段时间读数才稳环境温度冲击/自热效应给传感器足够稳定时间软件做上电后10分钟平滑过渡检查IDAC电流是否偏大导致自热偶尔出现跳变到离谱值偶发干扰/通信字节错位软件增加限幅滤波UART加帧头帧尾校验防止误码直接进解析4.3 关于精度等级的量化参考很多朋友关心这套方案到底能做到多高的精度我用K型热电偶和PT100分别测过一组对比数据这里给出一个参考范围。用内部2.048V基准、PGA增益32倍、数据速率20SPS时ADS122U04的实测噪声折算到温度大概是K型热电偶0.05°C峰峰值左右这是ADC本身的贡献。但加上冷端补偿误差、热电偶精度等级和非线性校正误差之后系统级误差通常在±0.5°C到±1°C其中热电偶本身的允差就是大头。换成PT100三线制、外部低温漂基准后0°C到100°C范围内系统误差能做到±0.15°C以内这已经能满足绝大多数HVAC和工业过程控制的需求。如果目标比这更高就得换更高精度的基准和更严格的四线制传感器了。另外要提功耗STM32L152ZD在停止模式下电流可以掉到微安级别唤醒后采集一次温度再睡整套板子用电池供电的话续航可以做得很长。ADS122U04在低功耗模式下电流也才几十微安两个器件搭配起来非常适合无线温度节点这是这类方案比PLC加变送器方案更有竞争力的地方。说回我个人的实际体会这套方案最花时间的并不是读写ADC那点UART代码而是把精度从“看起来对”做到“长期稳定可靠”。ADS122U04的UART模式有个非常大的调试优势就是你可以不先写STM32代码直接用USB转TTL模块接电脑和ADC通信把原始码读出来验证硬件链路等传感器和前端都确认正常了再回头写MCU代码。这种逐级验证的思路能省掉不少排查时间。再分享一个我习惯的做法产品定型前一定把传感器线缆按现场实际长度和走向测试一遍别只信实验室里那30厘米杜邦线测出来的结果长线状态下的抗干扰表现才是这套方案真正的试金石。