资讯详情

资讯详情

UART接口24位ADC搭配RS485,解决远距离温度监控难题

去年接了一个循环水温度监控项目控制柜到传感器节点直线距离不到三十米结果第一版方案差点翻车。当时我按习惯选了SPI接口的24位ADCPCB打样回来短距离调试一切正常线一拉到现场就开始丢数据示波器上时钟线的振铃看得人头皮发麻。后来换成了带UART接口的ADS122U04IPWR配合手头现成的STM32F100ZE做主控用一对双绞线加RS485收发器把数据传回来三十米距离稳如老狗。这篇文章就把这套方案的选型逻辑、电路细节、代码框架和调测经验完整整理一遍尤其适合做工业设备温度监控和HVAC暖通控制器开发的同行参考。1. 为什么 UART 接口的 24 位 ADC 能同时解决信号弱和距离远两个痛点1.1 温度信号到底有多弱先说清楚一个容易被忽略的事实测温信号是典型的微伏级信号。以工业里最常见的Pt100铂电阻为例0°C附近它的灵敏度大约是0.385Ω/°C。如果用1mA的恒流源激励那么温度每变化1°C产生的电压变化只有0.385mV目标精度如果是0.1°C那就是38.5µV想做0.01°C的分辨率就得处理3.85µV的信号。这个量级靠普通12位或16位ADC根本没法看。即便ADS122U04IPWR这类24位ADC在满量程±2.048V下理论LSB也才244nV左右听起来绰绰有余但ADC本身有噪声、参考有漂移、前端有干扰实际有效分辨率通常会打不少折扣。所以这颗芯片内部集成了可编程增益放大器PGA先把几十微伏的信号放大到伏级再由24位ADC数字化这才是真正的杀鸡也要用牛刀——不是性能过剩而是信号本身就这么苛刻。1.2 SPI和I2C在长线场景为什么容易翻车最初我选SPI是因为大多数高精度ADC都是SPI接口可选的型号多、资料也全。但SPI是同步串行总线主机要主动输出SCK时钟数据线和时钟线必须严格对齐。控制器到传感器之间走线一长线的分布电容、反射、串扰都会让沿变脏时钟和数据的相对时序偏移误码率直线上升。更麻烦的是隔离工业现场往往要加数字隔离器SPI至少得隔离SCK、MOSI、MISO、CS四根线成本高不说每一根线都是潜在的干扰入口。I2C也指望不上。它是开漏输出靠上拉电阻驱动总线总线电容一大上升沿就变得非常平缓传输距离基本被限制在一米以内。再加上I2C地址有限多节点扩展也要费一番功夫。在HVAC现场传感器散落在风管、水管、机房各个角落动不动就是十几米几十米的走线这两种总线都不合适。1.3 UART方案的本质优势UART是异步串行收发双方各走各的时钟只要波特率一致靠帧起始位就能把数据对齐对线缆的要求天然比SPI低。配合RS485收发器改成差分传输后几十米、几百米都很正常抗共模干扰能力也强。最赚的一点是隔离成本UART只需要隔离TX和RX两根线如果做半双工RS485一个光耦或数字隔离器就够用省下来的物料和PCB面积非常可观。ADS122U04IPWR这颗芯片比较特殊的地方在于它把模拟前端PGA、基准、IDAC电流源、内部温度传感器和UART通信做到了同一颗IC里主机端不再需要处理微伏级模拟信号只负责按命令帧读写寄存器、收24位转换结果。配合STM32F100ZE这种低成本、多路USART的Cortex-M3单片机一个HVAC控制器主板上留几个USART口就能挂好几个温度采集节点。下面这张表格应该能把方案优势说得更直白总线类型典型传输距离抗干扰能力隔离成本多节点能力远距离测温实用性SPI30cm~1m一般SCK沿线质量敏感高需隔离4路信号靠CS扩展节点受限基本不可用I2C1m以内一般开漏易受噪声需隔离SCL/SDA仍受电容限制地址有限不可用UARTRS485几十米~几百米好差分信号抗共模干扰低1~2路隔离可组多从机总线推荐2. ADS122U04IPWR 外围电路设计照着搭不返工2.1 供电、基准和去耦工业设备里通常没有干净的3.3V控制器板上可能是24V转5V的开关电源纹波不小。我的做法是先让24V经过一级DC-DC降到5V左右再用低压差LDO比如LM1117-3.3或更安静的型号给ADS122U04的模拟供电。开关电源的纹波哪怕只有几十毫伏经过ADC内部电路后都会直接变成读数跳动省这一步后面调试会非常痛苦。去耦电容要贴近电源引脚放常规组合是10µF钽电容加0.1µF陶瓷电容并联数字电源和模拟电源之间加一个磁珠隔开更好。基准源方面ADS122U04内部集成基准一般应用够用但如果项目指标是长期0.1°C级精度建议外部基准供电选择低温漂的精密基准芯片常见2.5V或2.048V规格。这里有个设计平衡参考电压越高ADC满量程越大对应每个LSB代表的电压也越大分辨率会变粗参考电压太低前端PGA输出容易饱和。要结合传感器输出范围算好再定。2.2 UART电气接口与远传设计芯片的UART接口默认支持短距离TTL电平直连调试阶段和主控在同一块板上时直接连PA10/PA9这种USART引脚就好。如果要拉到现场几十米必须加RS485收发器比如MAX3485、ISL3170这类3.3V半双工芯片。接线时注意A/B端子不要接反总线两端各并一个120Ω终端电阻环评大的地方还要加TVS管。波特率建议从9600起步完成通信验证稳定后再切换到115200。调试初期我遇到过用115200连不上、发命令没响应的情况后来发现是收发器方向切换时序没处理好——半双工RS485在发送完命令后要马上把驱动器关闭、切换到接收模式这个切换如果太急最后一个字节会被吞掉。一个小技巧是发送完成后延时2~3个字节时间再切接收简单可靠。2.3 模拟输入滤波与传感器保护每个模拟输入AIN0~AIN3建议都串一个100Ω电阻并加10nF对地电容构成一阶RC低通。截止频率大概在159kHz左右能滤掉大部分射频干扰和高频噪声对RTD这类低阻传感器也不会引入明显误差。RC滤波好处是成本几乎为零但一定要放在靠近ADC引脚的位置走线长了电容本身就成了天线。如果输入接的是热电偶建议在AIN正负输入端各加一个偏置电阻到GND比如1MΩ左右。热电偶内阻很低但开路时输入会悬空芯片内部没有强下拉输入电位可能漂到中间某个随机值导致读数乱跳。加上偏置电阻后开路时输入被拉到GND程序就能根据超量程判断出传感器断线而不是报一个几百度的假温度。2.4 PCB布局里最值得注意的两件事第一件是模拟地和数字地要分区然后单点汇接。刚开始我画的板子地平面是一整块RS485收发器的数字噪声直接耦合到了模拟输入读数在±0.3°C左右来回跳。后来把模拟区域和数字区域分开只在电源输入处用一个0Ω电阻连接跳变立刻收敛到±0.02°C级别。第二件是IDAC电流走线要远离UART数据线。IDAC输出的是直流激励电流本身不产生噪声但它走的路径如果和数字信号线平行数字跳变产生的容性耦合会影响激励回路稳定性进而影响测量结果。这类细节在原理图上完全看不出来只能靠布线阶段提前规划所以画PCB之前先想想模拟信号是从哪一路进的、数字信号又从哪一路出的。3. 传感器链路Pt100 三线制与热电偶冷端补偿3.1 为什么三线制比两线制准这么多两线制接线最简单拿两根线把RTD接到ADC就行但引线电阻全都会算进测量结果里。假设导线是0.5mm²铜线来回走20米铜的电阻率约0.0175Ω·mm²/m这20米导线的电阻就有0.7Ω左右。对Pt100来说0.7Ω意味着接近1.8°C的误差这在工业测温里根本没法接受。三线制的核心思想是让电流回路和电压测量的路径分开。具体接线是RTD的一端引出两根规格完全相同的线分别接到ADC的差分输入端高端和激励电流源另一端引出一根线接到差分输入端低端和公共回路。由于三根线的长度、材质一致导线电阻相等电流在回路和测量路径上产生的压降会在差分测量中相互抵消引线电阻带来的误差被压到很低。四线制更准但要多拉一根线实际成本和施工复杂度的提升不小工业/HVAC场景三线制是性价比最高的。3.2 IDAC激励电流的大小怎么选ADS122U04内部有IDAC恒流源可以直接给RTD提供激励。电流选得太大会产生自热效应电流流过RTD本身会发热把铂电阻的温度抬起来测出来的温度就偏高。1mA电流在100Ω的Pt100上功耗是0.1mW普通封装探头温升大概零点零几度如果改成2mA功耗直接变4倍自热误差可能到0.1°C以上这就不能忍了。所以我的默认选择是1mA除非传感器封装导热特别差再考虑降到0.5mA。IDAC还有个很实用的玩法让激励电流同时流过RTD和一个精密基准电阻分别测量两路的电压比值。这样IDAC本身的温漂在比值中会相互抵消相当于做了一次比例测量对长期稳定性和温漂指标提升非常明显。3.3 PGA增益和参考电压怎么搭配输入范围和增益的选择要一起算。假设系统要测的温度范围是-50°C到150°CPt100在这个区间对应电阻大约80.31Ω到157.33Ω以0°C时100Ω为基准。用1mA激励信号电压就是80.31mV到157.33mV选PGA增益8后ADC输入端的电压范围是642mV到1259mV在2.048V参考下余量充足还能留出一定过冲空间。如果测量范围收窄到0°C到100°C信号电压是100mV到138.5mV此时选PGA8后最大只有1.108V依然合适但要是贪心选PGA16100°C时放大后达到2.216V已经超过2.048V参考电压ADC会饱和读数直接废掉。所以先算信号范围再倒推增益和参考值顺序千万别反。3.4 热电偶接入的要点热电偶输出的是毫伏级热电动势比如K型热电偶灵敏度大约是41µV/°C测量几百摄氏度的信号满量程也就几十毫伏。这时PGA要选64或128输入范围才能匹配。热电偶本身不接IDAC激励它的信号是自发电的接反了极性会把温度符号反过来现场很容易踩坑。另外一个绕不开的问题是冷端补偿。热电偶测的是热端和冷端的温差要得到真实温度必须知道冷端也就是接线端子处的温度。最省事的办法是直接用ADS122U04内部集成的温度传感器读冷端温度或者外接一个NTC/DS18B20放在接线端子附近把这路温度读数加上去。实际操作中还有个隐蔽坑接线端子如果用了不同材质的金属接点本身会产生附加热电动势。所以冷端位置要尽量远离热源端子材质尽量统一避免人为制造第二个热电偶。4. STM32F100ZE 驱动与温度换算代码4.1 软件整体流程STM32F100ZE的主频虽然是24MHz但对温度采集这种慢速应用完全够用。软件流程可以归纳成四条上电延时等待电源稳定、发送NOP命令和ADC建链、写配置寄存器设定测量参数、周期轮询读取24位转换结果。ADS122U04的命令码和寄存器映射以最新版数据手册为准下面代码里的宏定义是示意用的框架读者务必替换成手册里的实际数值。先看USART初始化和命令发送的基础框架/* STM32F100ZE 使用 USART2CubeMX 配置为异步 115200 8N1 */ /* 命令码宏实际值请对照 ADS122U04 数据手册更新 */ #define ADS122U04_CMD_NOP 0x00U #define ADS122U04_CMD_RREG 0x20U #define ADS122U04_CMD_WREG 0x40U #define ADS122U04_CMD_RDATA 0x10U /* 向 ADC 发送配置帧命令 寄存器数量 寄存器值 */ uint8_t cfg_buf[5] { ADS122U04_CMD_WREG, 0x02, /* 连续配置2个寄存器 */ config_reg0, /* 多路开关/输入选择 */ config_reg1 /* PGA增益/参考源/数据速率 */ }; HAL_UART_Transmit(huart2, cfg_buf, 5, 100); /* 等待一小段让 ADC 完成配置 */ HAL_Delay(5); /* 读取24位转换结果 */ uint8_t resp[3]; HAL_UART_Receive(huart2, resp, 3, 20);4.2 24位数据的拼接与电压换算ADC返回的24位数据通常按二进制补码格式组织高位在前。把三个字节拼成一个32位整数后要先做符号扩展再用满量程去换电压。代码大概是这个意思int32_t code ((int32_t)resp[0] 16) | ((int32_t)resp[1] 8) | (int32_t)resp[2]; if (code 0x800000) { code | 0xFF000000; /* 符号扩展为32位有符号数 */ } double vref 2.048; /* 实际参考电压按硬件填入 */ double gain 8.0; /* PGA增益 */ double voltage code * vref / 8388608.0 / gain;这里容易出两个问题一是字节顺序搞反拼出来的数据乱跳二是忽略符号扩展负温度时读出的是巨大正数。调试时建议先把ADC输入端短接看码值是否接近0再用一个已知电压灌入做验证这样能快速排除拼接错误。4.3 电阻转温度计算对于Pt1000°C以上时电阻和温度的关系可以用Callendar-Van Dusen公式描述R(T) R0 × (1 A×T B×T²)其中R0100ΩA3.9083e-3B-5.775e-7。实际程序里经常做的是反问题测得R反解T。这个方程是二次的直接用求根公式能解但我更推荐牛顿迭代代码写起来直观扩展成更复杂的分度表也不费劲double rtd_to_temp(double r_rtd) { double r0 100.0; double a 3.9083e-3; double b -5.775e-7; double t (r_rtd / r0 - 1.0) / a; /* 线性近似作为初值 */ for (int i 0; i 5; i) { double f r0 * (1.0 a * t b * t * t) - r_rtd; double df r0 * (a 2.0 * b * t); t - f / df; } return t; }如果测温范围覆盖负温-200°C到0°C区间公式里要加入C×(T-100)×T³项但工程上更省事的做法是直接预置一张分度表用线性插值查表计算量小且不怕公式边界搞错。4.4 通信异常恢复机制UART虽然比SPI皮实但现场电磁干扰强的时候也会出现帧错位或响应超时。我的经验是一定要设计重同步机制检测到接收超时或数据非法时连续发送几个NOP指令让ADC回到已知状态然后再重新发起读取如果连续三次都不成功就拉高复位相关引脚或重新初始化寄存器。程序里还要给每次UART收发加超时绝不能阻塞在HAL_UART_Receive里死等否则一旦ADC不响应整个MCU就卡死了。5. 精度、标定与实测排查5.1 误差源先分清是谁的锅温度测不准往往不是ADC芯片不行而是误差源太多且互相叠加。我把常见的几类整理成了一张表误差源典型影响抑制手段ADC增益误差读数整体偏大或偏小软件增益校准参考电压漂移随温度缓慢变化选低温漂基准恒温IDAC电流温漂激励电流变化导致电阻计算偏差比例测量法消掉IDAC影响引线电阻两线制最明显可达1°C以上三线制/四线制接线自热效应读数持续偏高减小IDAC至1mA以下电源纹波和数字噪声码值随机跳动LDO供电、去耦、模拟数字分地工频干扰50Hz读数周期性波动RC滤波、整周期平均5.2 标定流程怎么做如果项目只要求±0.5°C直接用芯片默认参数可能就够了。但要做0.1°C级别精度标定绕不开。我的习惯是分两步第一步做失调校准把输入端短接或用精密电阻比如精确100.00Ω作为已知零点读到的码值作为offset存下来第二步做增益校准用一只精密电阻比如138.50Ω对应100°C左右作为标准算出一个校准斜率。之后每次测量都按校正温度 原始温度 × gain_cal offset_cal处理。有条件的话再用恒温槽或干井炉配合二等标准铂电阻做三点验证25°C、60°C、100°C各测一轮确认线性度。如果没有恒温槽至少也要用多只精密电阻覆盖目标温度范围把整个链路校准一遍。5.3 数字滤波怎么选工业测温不像示波器那样追求响应速度HVAC场景温度变化周期都是秒级甚至分钟级所以数字滤波可以大胆一点。最简单的做法是连续读8次取平均代价是吞吐率降8倍如果现场有偶发干扰再加一级中值滤波把最大最小值剔掉。我现在这个项目用的是滑动平均窗口16效果是读数稳定度从±0.05°C降到±0.01°C量级而且控制环也不会觉得温度反应变慢。还有个细节滤波窗口最好是10ms或20ms的整数倍这样50Hz工频干扰能在统计意义上被压掉比单纯靠RC滤波效果更明显。5.4 现场常见异常排查调试期间我把可能碰到的怪现象和原因整理成了一个对照表直接按表排查能省不少时间现象可能原因处理方法读回数据全是0xFFUART帧不同步、波特率错误发NOP重同步检查双方波特率数据来回跳幅度很大电源纹波、模拟地未分检查LDO纹波调整地线数值整体偏高增益误差、基准偏大做增益校准数值缓慢向一个方向飘IDAC温漂、探头自热比例测量法降低激励电流读数周期性波动50Hz工频串入屏蔽层单端接地、整周期平均6. HVAC 项目里的部署要点和个人体会6.1 多节点总线拓扑HVAC系统里典型的温度点包括风管送风温度、回风温度、水管供回水温度、室外补偿温度等分布范围广但每个点的数据量不大。用STM32F100ZE做总控通过RS485总线上挂多个ADS122U04节点每个节点负责本地一个或两个测温点主站轮询是非常经典的架构。节点和主站之间唯一的纽带就是那对A/B双绞线敷设方便检修也容易定位。6.2 隔离供电与探头防护现场有水泵、变频器强电干扰躲不掉所以节点供电我建议用隔离DC-DC模块485通信再用ADM2483这类隔离收发器做到电和信号双重隔离。传感器探头的金属外壳接地要看情况通常接仪表地而不是动力地否则会形成地环路反而把变频器噪声灌进来。露在室外的传感器还要加防雷措施TVS管和气体放电管成本不高关键时刻能救命。6.3 采样周期与超量程保护HVAC温度采集周期设置在0.5秒到10秒都很常见完全不需要让ADS122U04跑在最高数据速率。反而是把数据速率调低一点比如几十SPS配合数字滤波能得到更稳定的读数。程序里一定要做超量程判断温度超出传感器范围或ADC码值接近满量程时直接上报故障而不是把异常数值送进控制逻辑。这个保护逻辑看着简单真省过事——探头被老鼠咬断线时如果没有判断控制器可能会按高温报警去关设备实际只是断线了。6.4 最后分享几个实际项目里的土办法凡是碰到UART通信不稳先把波特率降回9600试一轮稳定了再往上加别迷信115200一定更好。凡是碰到读数跳变先去摸电源芯片烫不烫、纹波大不大大概率是电源而不是ADC软件的问题。凡是碰到温度偏高但很稳定先怀疑自热和引线电阻三线制接法和IDAC电流值优先检查。这套方案我从前年做到现在从实验室跑到现场已经稳定跑过了两个夏天和一个冬天。ADS122U04IPWR加STM32F100ZE的组合说不上多高端但在工业/HVAC这种温度和距离都较真的场景里恰好把每一分成本都花在了刀刃上。如果你也在做类似的东西希望这篇笔记能帮你少走几步弯路。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →