首页 / 资讯中心 / 文章详情

STM32与ADS122U04的高精度温度采集方案解析

STM32与ADS122U04的高精度温度采集方案解析 ★ FEATURED ARTICLE
前一阵给厂里的HVAC控制板做升级客户对温度精度的要求从原来的±0.5℃收紧到了±0.1℃。这块板子主控用的就是STM32F091RC一开始想靠内部ADC蒙混过关账一算就放弃了老老实实加了一颗ADS122U04IPWR。这是一颗带UART接口的24位四通道低功耗Δ-Σ ADC片内集成PGA、双IDAC电流源、内部温度传感器和2.048V基准用来测RTD和热电偶非常顺手。这篇文章把从选型、传感器接线、串口协议、温度换算到调试踩坑的完整过程整理出来适合正在做工业采集、楼宇自控、风柜盘管控制以及各类HVAC仪表的朋友参考也适合第一次用UART接口ADC的嵌入式工程师避雷。1. 为什么这块板子最后选了ADS122U04IPWR而不是SPI接口ADC1.1 STM32F091RC内置12位ADC的温度分辨率算了一笔账就凉了STM32F091RC是Cortex-M0内核48MHz主频片上确实带了12位ADC但拿它测高精度温度纯属为难它。3.3V参考电压下12位ADC一个LSB大约是0.806mV。PT100在0℃附近的灵敏度约为0.385Ω/℃如果用1mA恒流源激励电压灵敏度大约是0.385mV/℃。换算下来内置ADC一位就对应大约2.1℃这还没算上ADC本身的噪声和失调测个大概的过温保护还行想稳定输出0.1℃分辨率就是天方夜谭。外挂ADC几乎是必然选择。ADS122U04IPWR这类24位ADC在内部2.048V参考、PGA1的时候满量程是±2.048V理论LSB约为0.244µV对应到PT100测温大约是0.0006℃/位即便实际有效位数只有18~19位余量也远超需求。真正决定系统精度的不是ADC的位数而是前端传感器、激励电流和参考源的稳定性这个后面会详细算。1.2 SPI版和UART版的取舍关键是总线和传输距离选型时其实犹豫过ADS1220这类SPI接口的经典型号。SPI版资料多、社区案例丰富代码范例随手就能搜到但它有两个问题让我最终放弃。第一是总线占用。当时的板子上已经有SPI Flash和数字隔离器再挂一颗ADC虽然技术上可行但总线上设备多了时序调试和故障排查都会更麻烦。ADS122U04IPWR直接用UARTSTM32F091RC的USART资源充足单独划一个串口给ADC剩下的串口继续留给Modbus或调试分工干净。第二是传输距离。HVAC现场传感器线通常要走几米甚至十几米SPI的SCK/MOSI/MISO在长线上容易受寄生电容和串扰影响速率稍高波形就变形。UART是异步串行线缆阻抗要求宽松得多配合RS485电平转换芯片还能轻松拉出百米传输。特别是有时候一个控制箱要采集多个风管温度点ADS122U04的地址模式允许多片挂在同一条UART总线上这点比SPI版本灵活太多。1.3 ADS122U04IPWR和F091的资源匹配度ADS122U04IPWR的PWR后缀是TSSOP-16封装手工焊接没问题引脚间距也够常规PCB走线。片内集成了24位Δ-Σ ADC、可编程增益PGA增益最高128倍、两路IDAC恒流源、内部温度传感器、内部2.048V基准测RTD不需要外部恒流源芯片测热电偶不需要前端仪表放大器一颗芯片把模拟信号链全包了。STM32F091RC这边压力也很小256KB Flash跑完协议栈和算法之后还剩很多32KB SRAM做查表插值和滑动滤波绰绰有余。整体器件成本不高适合量产的中小型控制器。如果你的产品只需要测一个点也可以考虑用I2C接口的专用温度芯片成本更低但灵活性差很多换传感器类型、接热电偶、做多路采集、远程传输全都受限。外挂高精度ADC方案的意义在于一块板子适配多种传感器输入硬件重新投板次数能省掉不少。2. 传感器接线与模拟前端配置RTD和热电偶的差异比想象的大2.1 三线制RTD接线时两个IDAC配合才能抵消线阻PT100在0℃附近等效电阻约100Ω但传感器到控制板的线缆电阻可能在1~5Ω之间这直接对应好几度的误差所以HVAC现场几乎都用三线制而不是两线制。三线制是一种很巧妙的补偿办法。把PT100一端接AIN0另一端接AIN1同时从AIN1这一端再引一根线接到IDAC2输出IDAC1则从AIN0那一端进入。两个IDAC配置成相同的电流值一路电流经线缆0流过RTD再经线缆1回来另一路经线缆2单独走。这样在差分输入端线缆0和线缆1上的压降方向相反做差之后基本抵消剩下的才是RTD本体的电压。实际使用中有个容易翻车的地方两个IDAC的匹配度并不是100%典型失配在0.1%~0.2%水平对应到线阻1Ω时会产生0.1~0.2%的残余误差大约0.01~0.02℃通常可以接受。要注意IDAC2必须接到RTD的同一节点而不是随便接个GND否则补偿逻辑就错了。四线制则简单粗暴IDAC用于激励AIN0/AIN1走采样线采样线上几乎没有电流线阻压降自然消失精度最高但需要多一根线。HVAC传感器一般预埋三根线所以三线制是最常用选择。两线制只在精度要求不高的检测场景用用于闭环控制容易出问题。2.2 热电偶虽然信号小PGA高增益下更要注意共模电压热电偶的输出是毫伏级信号K型热电偶灵敏度约40µV/℃从-20℃到150℃的测量范围信号大约7mV。用PGA64时满量程约±32mVHVAC范围内余量充足。如果以后要测工业炉膛到700℃以上需要把增益降到32甚至16避免信号削波。但热电偶比RTD麻烦的是冷端补偿。热电偶测到的是测量端与参考端冷端的温差接线端子处的温度必须知道。ADS122U04内部集成了温度传感器可以直接拿来当冷端参考读出芯片附近温度后查表转成对应热电势再与测量电压相加。这个方法省成本但内部温度传感器的精度一般出厂需要做偏移标定标定后冷端补偿大约±1℃水平总体精度取决于传感器等级。想要更高精度可以把冷端传感器换成TMP117这类0.1℃精度的数字温度芯片贴在接线端子旁边。还有一个非常隐蔽的坑PGA高增益下输入共模电压范围很窄。我把热电偶负极直接接GND试过读出来的码值要么跳变要么直接贴满量程看起来像过压保护其实是PGA内部输入级的共模工作点跑到范围外了。正确做法是用两个偏置电阻把AIN0和AIN1的共模电压抬到接近VREF/2再以差分方式接入热电偶信号。别嫌这步麻烦不做的话高增益下很难稳定。2.3 PGA增益、IDAC电流和参考电压要按场景一起配这几个参数是相互耦合的不是随便设个值就能跑。下面是我实际用过的配置组合可以直接照搬。应用场景PGA增益IDAC电流参考源数据速率PT100三线制 0150℃16500µA内部2.048V20SPSK型热电偶 -20150℃64关闭内部2.048V20SPSNTC热敏电阻 10kΩ4250µA内部2.048V20SPS增益的选择原则是让满量程信号占到ADC输入范围的50%以上但又不能超量程。以PT100配500µA电流为例150℃时PT100电阻约158Ω差分电压约为79mVPGA16后放大到1.26V在±2.048V满量程内留有充足余量。IDAC电流也不是越大越好500µA在PT100上产生的自热功率只有25µW实际影响大约0.02℃但如果换成1mA则自热会明显上升HVAC风管里传感器长期被气流吹自热误差会随风速变化很难校准掉所以500µA是个折中值。参考电压方面我不建议直接用MCU供电的3.3V虽然ADS122U04内部基准精度不算顶尖但比普通稳压芯片靠谱。对精度有更高要求可以外接REF5025这类精密基准代价是成本和面积都增加。去耦电容不要省AVDD和DVDD各放一个0.1µF陶瓷电容再并联一个10µF钽电容PCB上的AGND和DGND建议单点连接而不是直接整片铺地了事这一步直接影响ADC底噪。3. STM32F091RC和ADS122U04的串口链路搭建与时序配合3.1 给ADC一个稳定的CLK波特率才谈得上准确ADS122U04的UART波特率不是像普通芯片那样用外部晶振定死的而是由CLK输入时钟通过内部逻辑分频得到。CLK我强烈建议用有源晶振提供4.096MHz信号别图省事直接用STM32F091RC的MCO输出。我一开始就是用的MCO调试时发现每次上电后第一帧数据经常乱码后面才恢复。抓了CLK引脚的波形才发现MCO的输出在MCU时钟初始化阶段还没稳定ADC已经上电开始按错误的参考频率初始化串口参数了。换上有源晶振之后在程序里等晶振稳定200ms再初始化ADC乱码问题彻底消失。波特率不用追求高整个采集链路只有20SPS的读出量用9600或者19200完全够反而抗脉冲干扰余量更好。115200在强电磁环境下面临误码风险工业现场不建议。3.2 寄存器配置序列和命令帧ADS122U04的UART命令风格和SPI版本的ADS122x系列很像有RREG、WREG、RDATA等命令但具体命令字节编码和寄存器位域定义要以TI数据手册为准。下面给出的是程序框架重点是先写配置、回读校验、再启动测量。static void ADS122U04_Init(void) { uint8_t cfg[4]; uint8_t rbuf[4]; /* 等待芯片上电稳定和外部时钟稳定 */ System_DelayMs(200); /* CONFIG0: AIN0/AIN1差分输入PGA增益16 */ /* CONFIG1: 20SPS内部滤波器 */ /* CONFIG2: 内部2.048V基准正常极性 */ /* CONFIG3: IDAC1500uA, IDAC2500uA, 使能内部温度传感器 */ cfg[0] 0x10; cfg[1] 0x20; cfg[2] 0x04; cfg[3] 0x30; /* WREG命令写入 */ ADS122U04_SendCmd(0x40 | (0x00 2), cfg, 4); /* RREG回读校验 */ ADS122U04_SendCmd(0x20 | (0x00 2), rbuf, 4); if (memcmp(cfg, rbuf, 4) ! 0) { /* 配置未写成功这里置错误标志让主循环处理 */ g_adc_error 1; } }这段框架代码里的命令编码逻辑是WREG命令高位是0x40带上起始寄存器地址和寄存器数量RREG类似。实际项目里建议把回读校验做进初始化流程因为UART链路偶发错误时寄存器可能没写进去而转换结果看起来又像是正常的这种隐性故障最磨人。回读能保证每次上电后配置都是确定的。3.3 DRDY信号从芯片到主循环的时序配合ADS122U04的DRDY引脚是转换完成标志数据准备好时会拉低。无论用单次读取模式还是连续读取模式都要让DRDY参与控制否则很容易读到旧数据或者读到一半被新数据覆盖。我的做法是把DRDY接到STM32F091RC的EXTI引脚比如PB0配置成下降沿触发。中断里只置一个标志位主循环检测到标志后发RDATA命令并读取3字节数据。数据格式是24位二进制补码占用3个字节volatile uint8_t g_data_ready 0; void EXTI0_IRQHandler(void) { if (EXTI-PR EXTI_PR_PR0) { EXTI-PR EXTI_PR_PR0; g_data_ready 1; } } int32_t ADS122U04_ReadTemperatureRaw(void) { uint8_t buf[3]; int32_t raw; if (!g_data_ready) { return 0; } g_data_ready 0; /* 发送RDATA命令 */ ADS122U04_SendSingleCmd(0x10); /* 接收3字节 */ ADS122U04_UartReceive(buf, 3, 100); raw (int32_t)((buf[0] 16) | (buf[1] 8) | buf[2]); /* 24位补码符号扩展 */ if (raw 0x800000) { raw | 0xFF000000; } return raw; }有个细节在单次转换模式下DRDY拉低后要及时读取如果拖太久下一次转换可能已经开始旧数据寄存器可能已被覆盖。连续读取模式下DRDY的脉冲时序又与单次模式不同不要把网上SPI版本ADS1220的代码直接搬过来必须用示波器或者逻辑分析仪量一下实际波形。3.4 用DMA加UART空闲中断优化接收效率温度采集虽然数据量不大但主循环如果同时跑PID调节、Modbus协议、按键显示轮询等待3字节串口数据会严重影响实时性。合理做法是用UART接收DMA加空闲中断DMA把数据直接搬进缓冲区UART空闲中断表示一帧接收结束。STM32F091RC的UART支持DMA配置好之后主循环只负责判断帧接收完成标志。一次温度读取的完整流程是DRDY触发标志主循环发RDATA命令DMA等待3字节最终解码。实测下来主循环单次温度采集耗时不到几毫秒即使把滤波器处理放进去也完全不影响其他任务。多片ADS122U04挂在同一条UART线上时地址帧和广播帧的命令设计需要额外加状态机这一块建议先把单片的时序摸透再扩展否则排查起来会非常头疼。4. 从24位原始码到温度值换算、校准与误差账4.1 RTD写入部分芯片直接按公式算别在M0上跑浮点方程组ADS122U04返回的24位码值要先转成电压。以差分输入、双极性输出为例码值转电压公式大致是Vdiff (raw / 2^23) * VREF其中VREF是2.048Vraw是符号扩展后的24位补码。注意如果配置成单极性模式分母要换成2^23以外的对应值这个细节在不同配置里容易搞错建议仔细看数据手册的编码表。得到差分电压后除以IDAC电流就得到RTD电阻。PT100的标准电阻温度关系在0~850℃范围用IEC60751的多项式描述R(t) R0 * (1 A*t B*t^2) A 3.9083e-3 B -5.775e-7但是在Cortex-M0上跑浮点开方解一元二次方程并不划算我实际项目里用的是查表加线性插值。0~200℃范围内按1℃步长生成201个电阻值放在const数组里运行时先二分查找再线性插值温度分辨率轻松到0.01℃Flash消耗才几百字节。HVAC控制环完全够用代码也更可读。4.2 热电偶的线性化处理和冷端补偿计算热电偶的电压-温度关系是高阶多项式NIST给了ITS-90标准系数直接在MCU上跑完整多项式不现实。我的做法是只保留-40℃到200℃这一段的NIST表步长1℃总共约241个点Flash占用不大。换算流程分成三步读取ADC原始码值转换成热电偶差分电压Vtc。读取冷端温度Tc来自ADS122U04内部温度传感器或外部TMP117查表得到Tc对应的热电势E(Tc)。将E(Tc)加上Vtc得到补偿后的总热电势再查表反推实际测量端温度。注意冷端补偿和测量端查表用的是同一张表方向要一致温度到电压查一次电压到温度再查一次。内部温度传感器的输出精度会直接影响最终结果如果对冷端补偿精度要求高建议用独立数字温度传感器并且在校准时把冷端传感器的偏移一起标掉。4.3 两点校准短路测失调精密电阻测增益高精度采集板出厂前必须做两点校准否则每一片板子的PGA失调和增益误差都不同贴得再好的器件也变不成一致性。校准流程不复杂但方法要对失调校准把ADC输入端短接短的粗铜线直接搭在接线端子上读码值平均64次记录为Offset码。注意不是通过PCB走线或长导线短接否则引入的噪声和热电势会把校准搞砸。增益校准用0.05%精度的电阻箱替换RTD分别设100Ω和150Ω两个标准值读码算增益系数或者直接配置一个标准电压源给热电偶通道灌入10mV信号做增益标定。校准后把Offset和Gain系数存到EEPROM或STM32F091RC的Flash里上电时加载。增益64的高增益场景下PGA失调往往比分辨率更影响小信号精度所以增益校准对热电偶通道尤其重要。4.4 误差账要系统算不能只盯着ADC分辨率很多初学者把24位ADC当成了无敌信号链其实温度测量系统的长期精度受限于一堆小误差的叠加。我一般按误差来源排队误差源典型量级应对方式PT100传感器自身离散0.1~0.3℃选A级或1/3DIN级探头IDAC电流温漂0.05~0.2℃选低温漂版本做增益校准内部参考温漂0.1℃量级高要求时外部精密基准PGA失调和温漂小信号时明显两点校准覆盖线缆残余线阻三线制下约0.01~0.05℃保证IDAC匹配PCB漏电、焊接残留高阻时明显清洗板面、加护环真正限制长期精度的是参考源和电流源的温漂而不是ADC位数。ADS122U04的24位精度只是在给信号链留出足够大的余量让你有机会把上述误差逐项校准掉。如果板子用在-10~60℃的室外HVAC环境一个30ppm/℃的基准漂移在50℃温差下就是0.15%的误差反映到PT100在100℃时可能达到0.4℃这一项就吃掉大部分指标预算。所以选器件时别只看分辨率要连温度范围一起规划。5. 实测中的故障排查与几个让我差点换方案的问题5.1 上电第一帧总是乱码CLK配置背锅量波形才定位到第一版样机出来最明显的毛病是每次复位后第一次读温度总是错误值程序里加个重试机制又好了这种偶发问题最难受。排查链路是先看串口工具上的数据发现错误帧的字节间隔都不对说明波特率不对再看ADS122U04引脚上的CLK波形发现MCO输出的频率在上电后头几百毫秒并不在标称值上。原因很简单ADC先上电MCO后起振ADC按错误时钟锁定了波特率直到复位后才正常。修复方法是改用有源晶振给CLK单独供时钟在程序初始化ADC之前先延时200ms等晶振稳定。之后批量测试再没出现第一帧乱码。这个经验对使用外部时钟的ADC和通信芯片都适用时钟稳定之前不要急着给外围芯片发任何数据。5.2 温度卡旧值、偶尔跳变DRDY和读取时刻脱节了有一版固件图省事没有用DRDY中断而是在主循环里发RDATA命令然后接收想当然地认为每次读到的都是新数据。结果发现温度值会莫名其妙地一段时间不变然后又跳一下。用逻辑分析仪把DRDY波形和UART读取时刻对齐后发现主循环发RDATA命令的时机有时落在两次DRDY之间读到的数据是上一轮转换结果而且连续读两次时第二次可能读到同一个值表现为温度“卡住”。修复很直接把DRDY接到EXTI下降沿严格在数据就绪后再启动一次读取流程。改完后连续运行72小时温度输出很干净没有出现旧值现象。5.3 高增益下码值贴满量程不是过压是共模电压超限热电偶通道调试时增益设为64输入一个正常的室温热电偶读到的码值却一直接近满量程。最开始怀疑信号过压或接反线反复检查也没发现问题。后来查阅PGA输入级共模范围才意识到热电偶负极直接接地后输入共模跑到接近GNDPGA内部摆幅受限出现饱和。解决方法是加偏置网络用两个10kΩ电阻把AIN0和AIN1的共模拉到VREF/2附近热电偶信号通过差分方式接到偏置点上方。改完再读码电压输出回归正常。这个坑在低温漂、高增益的精密采集里很典型排查时不要只盯着码值本身要看PGA的工作条件是否满足。5.4 风管里测温误差随风速变化IDAC自热在作怪有客户反映同一个传感器在静止空气和风管吹风条件下读数差了0.1℃以上。排查后发现IDAC电流设置偏大RTD探头的自热在无风条件下积累得更明显有风时热量被气流带走探头温度更接近真实空气温度于是出现随风速变化的读数偏差。处理办法是降低IDAC电流从1mA降到500µA实测自热误差降了一半以上。如果目标是0.1℃以内500µA甚至250µA更稳妥代价是信号幅度变小但24位ADC余量大完全够用。这个场景提醒我们激励电流的选择不能只盯着ADC分辨率还要考虑传感器探头本身的热模型。5.5 变频器一启动温度就跳地环路和大功率干扰现场调试时最头疼的是变频器一开ADC读数跳动从±0.02℃扩大到±0.3℃。查了很久发现两个问题叠加传感器屏蔽层两端都接地形成地环路把变频器的共模干扰直接引入模拟地同时板子上AGND和DGND没有做单点隔离数字部分的开关噪声串进了ADC参考源。修复方案是屏蔽层单端接地去掉板子上一处不必要的铺地连接在ADC输入端加共模电容和差分电容参考引脚处再补一组去耦。改完再开变频器温度跳动回复到正常范围。HVAC现场往往有变频风机、压缩机这类强干扰源模拟前端的地回路问题比ADC芯片本身更容易成为瓶颈。调试这类板子时我的习惯是准备一个外置USB转UART小板把ADC的TXD信号单独引出来监听再用示波器同时量DRDY和串口帧基本能覆盖绝大多数通信类和时序类问题。另外在PCB上预留CLK、DRDY、TXD三个测试点调试时不用拿镊子扒拉着芯片引脚量信号能省下一大堆时间。ADS122U04IPWR和STM32F091RC这套组合整体稳定性不错只要把时钟、地、DRDY时序这三件事处理到位长期跑HVAC应用基本不需要再操心温度采集本身。
阅读完成 · 觉得有帮助?
咨询建站