做暖通空调HVAC和工业温度采集的人大概率都遇到过这种场景温度探头挂在十几米外的管道上走线贴着变频器柜普通ADC量出来的数值跳来跳去0.1℃的精度指标在实验室里好好的一到现场就原形毕露。我最近一套冷站水温监测和空气处理机组AHU送风温度采集方案就是用ADS122U04IPWR这颗24位Δ-Σ ADC配合STM32F415ZG主控重新设计的跑了两轮实测数据稳了干扰也压住了这里把选型逻辑、硬件设计、驱动代码和标定踩坑完整记录下来给正在做工业或HVAC温度采集的同行一个参考。ADS122U04IPWR是TI的4通道、24位Δ-Σ ADC输出接口用的是UART而不是常见的SPI/I2C这个特性在分布式温采场景里非常实用STM32F415ZG则是带FPU的Cortex-M4主控宽温、多UART、内置CAN和以太网MAC做采集网关正合适。整套方案适合PT100/PT1000热电阻、热电偶、以及0~10V/4-20mA变送器信号的小型温采节点无论你是在做AHU盘管水温监测、冷站供回水温度还是工业管道表面温度巡检下面这些内容都能直接用。1. 为什么是ADS122U04IPWR STM32F415ZG而不是其他组合1.1 选型前的需求清单先说我当时定的设计指标这也是很多HVAC和工业温采项目的共同底线测温精度系统级目标±0.1℃PT100传感器本身误差之外的部分探头类型PT100/PT1000热电阻兼顾少量热电偶输入通道数量至少4路后续要扩到8路以上通信距离探头线最长15米经过变频器、接触器所在电气间环境温度控制器侧-20℃~70℃探头侧-40℃~85℃通信接口主控和ADC之间走短距离板级通信但整机对外要能扩展RS-485按这个清单去筛ADC16位的ADS1115/ADS1120这类首先出局16位分辨率在0~100℃范围内能分辨约0.005℃按PT100灵敏度0.385Ω/℃算听起来够用但实际现场噪声一来有效位数直接掉到14位甚至更低想保住0.1℃系统精度非常勉强。24位Δ-Σ架构成了必然选择。1.2 ADS122U04在TI 24位ADC家族里的定位TI的24位Δ-Σ ADC产品线很密ADS122U04属于低速高精度兼低功耗那一档。它和同系列ADS1220SPI接口、ADS124S08多通道、SPI、ADS12568通道、SPI最大的区别就是把通信接口换成了UART。不要小看这个换接口实际项目里差别很大。SPI要占用CLK、MISO、MOSI三根线加至少一根CS主控引脚吃紧不说长距离板间连接时时钟线最容易辐射和受干扰。I2C虽然只占两根线但地址冲突、上拉电阻匹配、长线电容驱动能力都是问题。UART反而是最简单的点对点异步通信波特率9600~19200bps在1米板间走线上非常稳而且后续如果想做多节点采集UART信号再加个电平转换芯片就能扩展到RS-485总线升级路径很顺。ADS122U04内部集成的资源对RTD测量尤其对口4路输入MUX可以配置成2路差分或4路单端、可编程增益放大器PGA1~128倍、24位Δ-Σ调制器、可配置数字滤波器内置50Hz/60Hz工频抑制、低漂移内部基准2.048V、两路匹配IDAC恒流源可用于RTD激励、内部温度传感器、传感器断线检测、以及热电偶测量需要的传感器偏置电压发生器。也就是说一颗芯片把信号调理、基准、激励、滤波全包了外围只需要少量电阻电容。从成本和供货角度讲ADS122U04是量产料工作温度范围-40℃~125℃在HVAC这种夏天高温、冬天低温的恶劣柜内环境里余量很足。IPWR封装是TSSOP-16手工焊接和机器贴片都没问题。1.3 STM32F415ZG相比兄弟型号的取舍主控选了STM32F415ZG而不是更常见的F407、F405也不是性价比更高的F103系列。原因主要有三个第一F415ZG的UART资源多。它有6个UART/USART其中好几个带FIFO和硬件流控。做ADC采集时每个ADS122U04占一个UART板载4颗ADC就是4路UART剩下两个还能留给RS-485和调试串口接口分配从容很多。F103最多只有5个UART而且没有FIFO中断频繁时CPU占用率很高。第二Cortex-M4内核带FPU。温度换算看起来简单但如果是多通道连续采集每路都要先做码值符号扩展、电阻反算、CVD多项式求根没有FPU的话float运算会吃掉不少CPU时间。F415ZG跑168MHz单精度浮点一条指令就能完成乘法数据吞吐量完全不是问题。更关键的是后续如果想在采集节点上顺带做PID控制或者温度趋势预测FPU能力直接决定代码能写到什么复杂程度。第三F415ZG的工作温度范围是-40℃~105℃同时内置CAN控制器和以太网MAC。HVAC项目经常需要把几十个温度节点汇到上位机或者楼宇自控系统里这个选型等于给后续协议转换留了后门。以下是几个候选主控的实际取舍对比主控内核UART数量浮点单元适用场景弃用/选用原因STM32F103RCT6Cortex-M33无简单采集UART不够分配浮点靠软件模拟STM32F405RGT6Cortex-M44单精度FPU中规模采集UART数量略紧无扩展总线余量STM32F407ZGT6Cortex-M46单精度FPU采集网关可用但F415ZG同封装有更高性价比STM32F415ZGT6Cortex-M46单精度FPU采集控制通信最终选用最终板上用了4颗ADS122U04IPWR对应F415ZG的UART3/4/5/6每颗ADC管4路模拟输入单板一共16路温度通道对外再接一个RS-485口整套系统容量对中型AHU机组或者小型冷站来说足够宽裕。2. ADS122U04的工作机制与UART通信细节2.1 内部信号链从引脚到码值ADS122U04的信号链结构可以理解成一条流水线输入MUX选通道 → PGA放大 → Δ-Σ调制器采样 → 数字滤波器抽取 → 结果存入数据寄存器 → 通过UART读出。Δ-Σ架构的核心思路是用很高的采样率对输入信号做过采样再用数字滤波器把带外噪声压掉换取高分辨率。这和逐次逼近型SAR ADC完全不一样SAR是一下子把模拟量和内部DAC比完Δ-Σ是反复比较、统计、滤波所以它的优势是线性度和噪声特性好劣势是输出数据速率不可能太高。ADS122U04的可编程数据速率范围在20SPS到1000SPS左右配合50Hz/60Hz工频抑制模式正好覆盖温采这种慢速高精度场景。PGA增益选择对桥式传感器和RTD很重要。我的经验是PT100在250μA激励下0~200℃对应电压约25mV~77mVPGA选32或64比较合适PT1000因为电阻大10倍同样激励电流下电压也大10倍PGA选4或8就够了。增益选太大会把噪声一起放大选太小又浪费ADC的动态范围这个要结合后文的噪声实测来看。ADS122U04还有一个很实用的功能内置传感器偏置电压发生器。测热电偶时如果没有偏置电压热电偶悬空输入会让ADC读到不确定的电位读数乱跳打开这个功能后输入共模点被稳定钳位冷端补偿再配合芯片内置的温度传感器就能做完整的热电偶测量。我这次主测RTD但这功能在后续扩展热电偶通道时省了一大笔外围电路成本。2.2 UART协议的命令帧结构ADS122U04走得是半双工命令-响应模式主控用UART发送4字节命令帧ADC根据命令类型返回数据帧或状态。所有通信都通过一根发送线主控TX→ADC DIN和一根接收线ADC DOUT→主控RX完成UART格式是8位数据位、无校验、1位停止位。帧结构固定为4字节第1字节是命令码第2、3字节是16位数据或寄存器地址数据第4字节是校验和。校验和算法是0x00 - (CMD DATA_H DATA_L)取模256。这个设计一开始容易被忽略很多人直接发3字节命令ADC根本没反应排了半天发现是帧长不对。实际使用频率最高的几类命令命令功能命令码说明复位0x06恢复默认配置相当于重新上电唤醒0x00从休眠模式唤醒写配置寄存器0x4XX为寄存器地址0~4读配置寄存器0x2X回读配置确认读转换数据0x12读出24位转换结果启动转换0x08单次转换模式下触发一次转换具体命令码以TI官方数据手册SLAS899为准我这边代码里做成了宏定义方便移植时统一修改。建议所有命令帧的组包和解析都收口到一个函数里不要散落在业务代码中不然换芯片或者调时序时会改到怀疑人生。2.3 轮询式读取与寄存器配置策略ADS122U04不像SPI版ADS1220那样有硬件的DRDY引脚它的“转换完成”标志是放在状态寄存器里的NOT_DRDY位。读取状态寄存器需要发送命令所以最常见的做法就是轮询。如果配置成连续转换模式主控只需要周期性发送读数据命令状态位自然就回来了。如果配成单次转换模式每次都要先发启动转换命令再轮询状态再读数据流程长但功耗更低。我这套做的是16通道连续采集因此把4颗ADC都配成了连续转换模式。主控侧使用一个2ms的定时中断每2ms对4颗ADC各发一次读数据命令16路数据全部刷新一遍。此时每颗ADC的数据速率设置在500SPS以上2ms的轮询周期远远够用不会出现读数据命令发过去但数据还是旧码值的情况。一个容易踩的坑ADC上电后默认可能是休眠模式必须先发Wakeup或者Reset命令再写配置寄存器。如果跳过这一步寄存器配置很可能写不进去。我调试时遇到过发完配置命令、回读却全是默认值的情况排查后确认是没做Wakeup。这个细节在数据手册的“Power-Up and Reset”节里写了不过英文手册一翻页就容易被漏掉。首次上电的初始化顺序建议是上电延时100ms → 发送Reset命令 → 再延时10ms → 写5个配置寄存器 → 回读校验 → 启动连续转换。这套顺序在4颗ADC上完全一致如果后续量产时加了看门狗复位后也要把整个初始化串重新走一遍避免ADC停在未配置状态输出空数据。3. STM32F415ZG侧的驱动设计与数据处理3.1 外设资源分配与引脚规划F415ZG的6个UART需要逐一规划用途。板上的4颗ADS122U04分别接USART3、UART4、UART5、USART6每个UART只用TX和RX两个引脚。Debug串口留给USART2对外RS-485串口挂在USART1上并复用其DE控制引脚做收发方向切换。USART3默认引脚在PB10/PB11UART4在PC10/PC11UART5在PC12/PD2USART6在PC6/PC7。做PCB Layout时这些引脚分散在芯片四周走线基本不会交叉对两层板很友好。F415ZG的所有UART都支持DMA发送和接收但ADS122U04命令帧只有4字节、返回帧最多也是4字节完全没必要用DMA直接阻塞发送加中断接收就够了反而代码更简单。要注意的是UART4和UART5在F4系列上不是所有型号都有比如F405RG就没有UART5选型时务必核对引脚定义和数据手册的“UART5 available only on...”备注。F415ZG因为封装大、资源全不存在这个问题。3.2 命令发送与结果读取的代码逻辑驱动层我做成了独立文件ads122u04.c接口只暴露了三个函数初始化、配置寄存器、读取通道数据。底层的帧组包和校验计算全部隐藏起来。上面提到的命令码宏在头文件里统一管理#define ADS122U04_CMD_RESET 0x06 #define ADS122U04_CMD_WAKEUP 0x00 #define ADS122U04_CMD_RDATA 0x12 #define ADS122U04_CMD_START 0x08 #define ADS122U04_CMD_WREG_0 (0x40 | 0x00) #define ADS122U04_CMD_RREG_0 (0x20 | 0x00)组帧函数和校验算法是整个驱动的核心务必确保正确static void ads122u04_send_frame(UART_HandleTypeDef *huart, uint8_t cmd, uint16_t data) { uint8_t buf[4]; buf[0] cmd; buf[1] (data 8) 0xFF; buf[2] data 0xFF; buf[3] (uint8_t)(0x00 - buf[0] - buf[1] - buf[2]); HAL_UART_Transmit(huart, buf, 4, 10); }读取转换数据的流程分两步先发读取命令再等接收4字节返回帧。返回帧的第1字节通常是状态字节NOT_DRDY位表示数据是否新就绪第2~4字节是24位转换结果最高位为符号位。核心读取函数int32_t ads122u04_read_conv(UART_HandleTypeDef *huart) { uint8_t buf[4]; int32_t raw 0; ads122u04_send_frame(huart, ADS122U04_CMD_RDATA, 0x0000); if (HAL_UART_Receive(huart, buf, 4, 10) ! HAL_OK) { return 0x7FFFFF; /* 返回故障标志 */ } raw ((int32_t)buf[1] 16); raw | ((uint32_t)buf[2] 8); raw | buf[3]; /* 24位有符号数扩展到32位 */ if (raw 0x800000) { raw | 0xFF000000; } return raw; }这里最需要留意的是返回的24位码值是无符号拼接但实际是有符号数必须做符号扩展。我见过不少同事漏了这一步导致温度在小数点后一位突然变成负几百度排查起来非常痛苦。每路通道的配置寄存器要独立保存一份结构体因为4颗ADC的增益、输入MUX选择、IDAC电流设置可能不一样。建议把通道号和ADC实例绑定在初始化时用一张配置表一次性写进去后续业务代码只依赖通道号索引不用关心它挂在哪个UART上。3.3 转换码值到电阻再到温度的完整计算链路拿到24位码值后第一步先把它换算成电阻第二步再用RTD公式反解温度。这里有个关键决策选用比例式测量还是绝对电压测量。比例式测量是让同一个IDAC电流同时流过RTD和一颗精密参考电阻RREF将RREF两端电压作为ADC的外部参考电压。这样可以消除电流源的温漂和初始精度误差因为信号电压和参考电压的变化方向、比例完全一致。这也是TI官方推荐的高精度RTD接法。此时电阻计算公式是[ R_{RTD} \frac{code}{2^{23}} \times \frac{R_{REF}}{G} ]其中code是24位有符号码值G是PGA增益RREF是参考电阻阻值。注意这里假设的是外部参考模式且PGA增益为G时信号路径的增益。对应的C代码实现如下float rtd_resistance(int32_t code, float rref, float gain) { return ((float)code * rref) / (gain * 8388608.0f); }得到电阻后PT100/PT1000在0℃以上的电阻-温度特性按照IEC 60751标准可以用Callendar-Van Dusen公式的简化形式描述[ R(t) R_0 \cdot (1 A \cdot t B \cdot t^2) ]其中PT100的R0100ΩA3.9083×10⁻³B-5.775×10⁻⁷。反解这个二次方程在0℃以上的温度就是float rtd_resistance_to_temp(float r, float r0) { float a 3.9083e-3f; float b -5.775e-7f; float c (a * r0) * (a * r0) - 4.0f * b * r0 * (r0 - r); if (c 0.0f) c 0.0f; return (-(a * r0) sqrtf(c)) / (2.0f * b * r0); }在0~850℃范围内这个公式误差在0.01℃以内足够工程使用。0℃以下要加C项但HVAC应用极少涉及低温段我这里没有展开。最后如果用内部2.048V基准而不是外部RREF做参考计算时需要先换成电压再除以激励电流。实际测量中内部基准的温漂通常在10ppm/℃量级如果整机工作环境温度波动大系统精度很难优于0.1℃。所以我的建议很直接RTD测量一律用外部参考电阻的比例式接法把基准温漂从误差链里拿掉。4. 硬件设计实战从传感器到ADC的每一环4.1 RTD的2线、3线、4线接法与误差分析RTD的接线方式决定了系统误差的下限这个必须提前想清楚。2线制最简单传感器两端各拉一根线到ADC但导线本身的电阻直接叠加到测量结果里。以100米长、截面积0.5mm²的铜导线为例单根电阻约3.6Ω折算到PT100就是接近9.4℃的误差根本没法接受。HVAC现场动不动十米二十米走线2线制只适合对精度完全没有要求的场合。3线制是工业最常用的折中方案。原理是让两个IDAC恒流源分别流过RTD的两根导线第三根线只承担电压采样、几乎无电流流过。由于两根导线电阻相等、两个IDAC电流匹配良好导线压降在差分输入端被抵消掉大半。ADS122U04内置两路匹配的IDAC出厂匹配精度很高配合3线接法可以把导线电阻误差压到0.1℃以内。我这次大头是板级到接线端子的短走线3线制已经够用。4线制最彻底两根线给RTD提供激励电流另外两根线专门测电压采样线没有电流流过导线电阻完全不进入测量回路。代价是多一根线、多一个接线端子成本上升。我的经验是探头与控制器分体安装且距离超过10米的高精度测点直接上4线制省去大量现场校准功夫。接法导线电阻影响现场实现成本推荐场景2线制完全叠加最低短距离、精度要求低3线制抵消大部分中工业变送器主流方案4线制完全抵消最高高精度、长距离测点4.2 参考电阻与IDAC激励电流的选型比例式测量里RREF这颗电阻的精度和温漂直接决定最终精度。我选的是0.1%精度、5ppm/℃温漂的金属膜电阻实测下来系统级误差约0.05℃对HVAC场合很充裕。如果预算允许VPG的箔电阻能做到0.01%和0.2ppm/℃但单价可能是普通精密电阻的十倍甚至更多除非做计量级设备否则没必要。IDAC电流源大小的选择要考虑两个矛盾电流大信噪比高但RTD自热效应明显电流小自热小但信号幅度低、对噪声更敏感。以PT100在250μA下的自热来做计算功率PI²×R(250μA)²×200Ω12.5μW这个量级在探头热容量正常的情况下引起的自热误差可以忽略。而250μA对应的信号幅度在0℃时是25mV配上PGA增益32后约0.8V量程信噪比非常舒服。PT1000可以适当降到100μA因为它本身电阻大同样的自热功率下信号电压比PT100高十倍。IDAC还要注意一个方向问题两路IDAC的电流方向要配置正确一旦方向接反RTD上的压降和参考电阻上的压降会互相抵消ADC读数直接跳到零附近这时候第一反应不是去查传感元件而是回头翻寄存器位定义。4.3 PCB布局布线与供电去耦ADS122U04是混合信号器件Layout直接决定噪声表现。参考电阻RREF要尽量靠近REFP/REFN引脚走线要短粗避免引入额外串阻和寄生电感。RTD输入走线建议走差分形式两条线等长平行周围用地线包住。模拟供电用单独的3.3V LDO输出AVDD到DVDD之间加一颗磁珠隔离数字部分和模拟部分的地单点连接不要在ADC下方把模拟地切开。每颗ADS122U04的AVDD和DVDD引脚旁边都放一颗100nF陶瓷电容靠近引脚放置再加一颗10μF钽电容做低频储能。UART走线则可以适当串入33Ω电阻做阻尼减少振铃。输入端的RC滤波也不能省。RTD信号进入AIN引脚前我会在每根采样线上串1kΩ电阻并在差分间放一颗100nF电容。这样构成的低通截止频率约1.6kHz对2kSPS以内的ADC完全够用同时能把变频器辐射过来的高频噪声挡住。RTD探头线引出板外时在端子接口处再放一颗共模电感实测对传导干扰的抑制效果立竿见影。还有一点容易被忽略ADS122U04的复位引脚在系统上电瞬间要保证足够低电平时间。如果MCU的复位引脚和ADC复位引脚接在一起要确认ADC侧能满足最小复位脉冲宽度必要时单独加RC延时否则会出现偶发的ADC配置丢失问题。5. 标定、噪声分析与实测数据5.1 系统级校准流程硬件焊好、驱动跑通之后最重要的事是系统级标定。不要只依赖芯片出厂精度因为RREF的精度、焊接引入的接触电阻、ADC参考输入端的微小漏电流都会造成偏差。我采用的标定分三步。第一步做偏置校准把ADC差分输入短接读取码值理想情况下应该接近0实际会有一个几μV到几十μV的偏置把这个值记录下来并写入A0校准寄存器。第二步做增益校准在输入端接一颗高精度标准电阻箱设置到被测范围的中间值比如PT100的话设250Ω读取电阻计算值和标准值的偏差比例写入FSCA校准寄存器。第三步做全量程验证分别设0℃、50℃、100℃对应的标准电阻值确认整条链路误差落在允许范围内。校准温度点建议选择项目实际工作范围的上下限和中间点而不是只校一个点。我在AHU项目中主要测7℃冷冻水和35℃冷凝水所以重点校准了这三个区间。校准后系统实测精度从没校准前的±0.3℃收敛到了±0.06℃以内。5.2 实测噪声底与有效分辨率噪声测试方法很简单在ADC输入端接一颗高精度低温漂电阻模拟RTD工作在50℃的状态连续采集1000个点看码值分布。以PT100在250μA激励、PGA增益32、数据速率500SPS为例实际跑下来码值峰峰值波动约相当于0.005℃~0.01℃有效分辨率大约17~18位对应到温度就是毫℃级别。这里要区分两个概念有效分辨率和无噪声分辨率。有效分辨率是把峰峰值噪声除以一个系数折算出来的看起来很高但实际工程意义不大无噪声分辨率才是直接看峰峰值跳动得到的可靠值。做温采项目时我建议直接关心温度读数的峰峰值波动比如目标±0.05℃以内那就持续观察24小时看最大最小值之差这样最直观。如果发现噪声偏大先别急着换芯片按这个顺序排查输入滤波电容是否缺失或虚焊、PGA增益是否过高、RREF离芯片是否过远、UART走线是否干扰了模拟输入。有一次实测噪声翻倍查了半天发现是IDAC电流配置从250μA被改成1000μA信号幅度变大但噪声也被放大得更快盲目加电流反而适得其反。5.3 常见故障排查清单这套方案跑下来最可能遇到的故障就那么几类我整理了一份排查清单现象可能原因排查方法ADC读数恒为0UART帧格式不对或未Wakeup回读寄存器确认配置是否写入读数乱码波特率不匹配用逻辑分析仪抓UART波形读数偏大/偏小固定比例增益校准未做或RREF精度差跑完整校准流程读数跳到满码输入断线查看断线检测标志检查探头接线某通道恒为旧值NOT_DRDY状态未更新确认数据速率与轮询周期匹配所有通道一起跳电源纹波示波器量AVDD纹波检查去耦电容还有一个非常隐蔽的细节UART空闲状态下TXD和RXD线要保证高电平。如果MCU的UART引脚默认是浮空状态而ADC侧又是开漏输出会出现首字节丢失或者帧同步错乱。解决办法是把UART收发引脚都配置为推挽输出并在驱动层发命令前清空接收缓冲。实际项目中温度数据和设备状态最好带一个帧序号或者时间戳一起上传。原因很简单UART读数据时如果赶上ADC正在更新读到的码值可能混了一个新一个旧虽然没有大错但计算出的温度会有一个小的毛刺抖动。在数据帧里加上转换序号后上位机可以识别并丢弃乱序帧。这个方法帮我省了大量调试时间强烈建议实现。最后分享一个习惯每次改完固件我会在室温25℃环境下用标准电阻箱给每个通道做一遍全量程复测记录偏差和上次烧录的结果对比。如果偏差超过0.05℃大概率不是算法问题而是硬件有元件漂移或者接触不良。这套回归机制帮我提前发现了两个通道的接插件氧化问题避免了很多现场返工。
阅读完成 · 觉得有帮助?