news 2026/11/5 5:03:06

STM32搭配24位ADC:单线UART与比例式测量的高精度温度采集方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32搭配24位ADC:单线UART与比例式测量的高精度温度采集方案

1. 项目背景:冷冻站和风柜对温度测量的真实要求

先说清楚我为什么会碰这颗芯片。去年做一套工业级HVAC集中控制器,现场环境比想象中复杂:冷冻站供水/回水温差要卡在0.2°C以内,风柜的送风温度要求响应快、读数稳,还有一组管道表面温度要用K型热电偶来测。原来用的方案是16位ADC配独立仪表放大器,一路一路地校准,费时费力不说,换一个批次的传感器就要重新标定一次。拖了一段时间之后,我才把目光转到24位的delta-sigma ADC上,最后选定了TI的ADS122U04IPWR,和手头资源充足的STM32F439ZI搭配,做了一套覆盖PT100、PT1000和K型热电偶的多通道温度采集单元。

先说结论:这套组合在低速、高精度的温度测量场景里非常合适。ADS122U04IPWR本质上是一颗24位、4通道、内置PGA和激励电流源的delta-sigma ADC,采样率不高,但胜在噪声低、内部功能齐全。而STM32F439ZI作为180MHz的Cortex-M4F主控,2MB Flash、256KB RAM跑这种采集任务属于"大材小用",好处是资源充裕,可以把线性化、滤波、通信协议栈这些活全包了,不用再挂第二颗MCU。

这篇文章我会把从选型、硬件搭接、单线UART通信、固件配置到现场标定的完整链路都过一遍。重点放在两个最容易被低估的地方:一个是ADS122U04IPWR那个"单线UART"接口到底怎么跟STM32对接,另一个是比例式RTD测量为什么能抵消激励电流的温漂。这两块搞明白了,其他都是顺水推舟的事。

2. 选型拆解:ADS122U04IPWR到底解决了什么问题

2.1 为什么我没有直接用ADS1220或SPI接口ADC

ADS1220这颗24位ADC在测RTD的圈子里很常见,SPI接口,最高2kSPS,QFN/TSSOP封装。但在这个项目里,我选择ADS122U04IPWR而不是ADS1220,原因很简单:接口形式。ADS122U04IPWR只保留了一个数字引脚DIO,用单线UART协议跟主机通信,而不是标准的SPI四线。这看起来像"降级",实际在HVAC控制器这种引脚紧张、走线受限的板子上非常实用。

你可以算一笔账:一个典型的HVAC采集板要接8路温度输入,如果每颗ADC都走SPI,CS、SCLK、MOSI、MISO四大线全要拉过去,还要处理设备寻址和片选扩展。换成ADS122U04IPWR这种单线方案,每个ADC只需要一根DIO线连到主控的UART引脚。STM32F439ZI上有8个UART/USART,哪怕拿出4个来各接一颗ADS122U04IPWR,也只占用4个引脚,剩下的还能兼做其他功能。

当然,这里有个老生常谈的坑我必须强调:单线UART是半双工的,同一根线上既要发命令又要收数据,方向切换的时序必须处理好,否则通信帧会莫名其妙丢字节。这个问题我后面专门用一章讲。

2.2 STM32F439ZI在这个项目里的角色

有人可能会问:测个温度而已,用得着STM32F439ZI这种旗舰型号吗?说实话,单论采集温度,用一颗STM32G0都绰绰有余。但这个项目里主控还要同时做几件事:跑Modbus TCP协议栈、驱动一块480x272的LCD屏、维护历史曲线数据、处理多路PID控制输出。F439ZI的高主频和2MB Flash给了很大余量,我可以把温度线性化用的多项式计算、滑动平均滤波都放在主循环外的一个任务里跑,完全不用担心和通信任务抢占时间片。

在引脚分配上,我给每颗ADS122U04IPWR分配了一个独立的USART_TX引脚做半双工单线通信,这样ADC之间互不干扰,一处通信卡死不会拖垮其他通道。同时用GPIO连接ADC的RESET引脚,方便在固件里做软复位。这个设计思路很直白:主控资源多,就尽量把外设隔离得干净一点,别为了省引脚把问题搞复杂。

2.3 采样率只有20SPS,够不够用

ADS122U04IPWR的数据速率上限就是20SPS,很多人听到这个数字第一反应是"太慢"。但对温度测量来说,20SPS是够用的,甚至可以说是优点。

温度对象的惯性很大,不管是冷冻水还是风道空气,温度变化的时间常数通常以秒甚至分钟计。20SPS的采样率配合数字滤波,得到的是一个极低噪声的稳定读数,反而比高速采样后还要再滤波来得省事。我们在风柜送风温度实测中,ADS122U04IPWR稳定后的码值跳动在1~2个LSB以内,换算成温度大约0.001°C级别的分辨率,这个表现对HVAC应用来说绰绰有余。

需要注意的是,20SPS意味着每次转换需要50ms。如果你在固件里用轮询方式读数据,千万别让主循环里某个耗时操作把读取间隔拖到几百毫秒——转换结果寄存器的数据虽然不会被覆盖丢掉的(因为ADC只在你读取后才更新),但系统的温度响应会看起来"迟钝",容易被误判为传感器故障。

3. 硬件设计与传感器接口:从PT100、热电偶到单线UART

3.1 三线制PT100、比例式测量的搭法

工业HVAC里用得最多的温度传感器是PT100和PT1000。两者原理一样,都是铂电阻阻值随温度变化,只是0°C时的标称阻值不同。PT100在0°C时是100Ω,PT1000是1000Ω。选哪个取决于现场:PT100抗干扰性强、引线电阻影响小,PT1000自热小、耗电低,更适合电池供电的无线传感器。

接PT100最怕的是导线电阻引入误差。二线制接法里,激励电流流过导线产生的压降会直接叠加到测量结果上,几十米的线缆能带来好几度的误差。三线制是工业现场最常用的妥协方案。ADS122U04IPWR内置两个可编程激励电流源IDAC1和IDAC2,正好可以做三线制补偿。

比例式测量的精髓在于:ADC的输出码值不是绝对电压,而是信号电压和参考电压的比值。如果我把IDAC电流同时流过RTD和一个精密参考电阻RREF,那么:

ADC码值 = (IDAC × RRTD) / (IDAC × RREF) × 满量程码 = RRTD / RREF × 满量程码

分子分母里的IDAC被消掉了。这意味着激励电流本身的温度漂移和绝对值误差不会影响测量结果,唯一要保证的是两个IDAC电流匹配度高。这是ADS122U04IPWR这类集成双IDAC的ADC比用分立恒流源方案精度高的根本原因。代价是参考电阻RREF必须选低温漂的精密电阻,我用的是一颗10ppm/°C以下的金属箔电阻,这钱不能省。

3.2 热电偶冷端补偿与热敏电阻通道

测制冷压缩机排气管温度时,PT100的测温范围不够,我用了K型热电偶。热电偶输出的是毫伏级热电势,且测量的是热端和冷端的温差,必须做冷端补偿。ADS122U04IPWR内置一个芯片温度传感器,可以用来估算冷端温度,然后在固件里减去冷端对应的热电势、再查表得到热端温度。

这里的经验是:冷端补偿的精度直接取决于ADC芯片自身那个温度传感器的准确度。如果你的热电偶和ADC芯片不在同一个温度环境下,光靠芯片内部温度传感器补偿是不灵的。我为这个项目做了一块小转接板,把热电偶的接线端子紧贴着ADS122U04IPWR放置,中间用导热垫填充,最大限度让冷端温度靠近芯片温度传感器。

至于NTC热敏电阻,ADS122U04IPWR的PGA增益和IDAC电流都可以随便调,接法更灵活。NTC阻值变化范围很大,25°C时10kΩ、到100°C可能只有几百欧姆,建议根据测量范围选一个合适的激励电流,避免在高温段自热过大。

3.3 DIO线与STM32 USART的半双工连接

硬件上最需要注意的就是这根单线。ADS122U04IPWR的DIO引脚需要跟STM32F439ZI的USART_TX引脚连接。在STM32侧,把USART配置为半双工模式(CubeMX里选"Half Duplex"),引脚就自动变成双向的了,但硬件上要注意三点:

第一,DIO线上必须接一个上拉电阻到VIO电源。我一开始没接上拉,通信时好时坏,后来查了应用笔记才明白,单线UART总线在释放状态需要外部上拉维持高电平。第二,上拉电阻的阻值不要太大,我最后选了4.7kΩ,兼顾了上升沿速度和功耗,再大容易出现信号边沿变缓导致波特率偏差。第三,MCU的USART_TX引脚和ADC的DIO之间可以串一个几百欧姆的电阻做限流和保护,防止两边驱动冲突。这个电阻也会和寄生电容构成低通滤波器,所以阻值别超过1kΩ。

电源方面,ADS122U04IPWR的数字供电和模拟供电建议分开走,模拟供电串一个10Ω电阻加陶瓷电容滤波,DIO参考的VIO电源要和MCU侧电压匹配。我用的VIO是3.3V,MCU也是3.3V,直接对接,没有电平转换的问题。

4. 单线UART通信:时序细节、收发切换与踩坑

4.1 标准UART帧和单线复用

ADS122U04IPWR的通信协议基于标准异步串口帧:起始位、8个数据位、停止位,空闲时总线为高。这和普通UART在帧格式上没有区别,唯一的区别是物理层只有一根线,主机和从机都是开漏驱动,靠外部上拉维持空闲电平。

主机发命令时,DIO线上是主机驱动的UART帧;主机发完命令后,把这根线让出来,由ADS122U04IPWR驱动响应数据。收发的切换完全靠时序约定:主机的命令发出后,必须留出足够的转换方向时间,不能立刻收紧自己的驱动,否则会拉死总线。

实际协议交互大致分两类:写配置寄存器和读转换结果。写寄存器就是主机发一个命令帧加数据帧,读转换结果是主机发读命令,然后等ADC返回3个字节的24位数据。因为是半双工单线,所有通信都是以主机为主宰的,ADC绝不会主动上报数据。这也意味着你需要定期轮询去取转换结果,或者等转换完成再发起读操作。

4.2 STM32F439ZI半双工UART的配置

在STM32F4上启用半双工UART,最方便的做法是用STM32CubeMX配置USART为异步模式,然后在高级参数里打开Half Duplex。生成的HAL代码会设置USART_CR3寄存器的HDSEL位。这个位一旦使能,USART_TX引脚就兼顾收发,内部收发器自动切到单线模式。

实际代码里,需要注意HAL库的半双工模式有个特点:它天然支持"发送完了自动转为接收",因为单线模式下收发器在发送结束后会释放总线。但HAL库的HAL_UART_Transmit和HAL_UART_Receive是独立的调用,中间我习惯插入一个微秒级的延时,比如50μs,给总线足够的稳定时间。

另外有个小坑:半双工模式下,接收是禁止回显的,你发出去的命令字节不会进入接收寄存器。这意味着你需要自己在固件里记录"刚才发的是什么命令",并明确区分当前总线上是命令阶段还是响应阶段。如果搞混了,接收到的字节会对不上号,调试起来特别费劲。我在代码里用了一个简单的状态机,把UART的发送和接收封装成两个状态,彻底杜绝这种混乱。

4.3 波特率容差和方向切换的坑

单线UART对波特率误差很敏感。ADS122U04IPWR内部有自己的时钟源,不支持你从外部给它一个时钟,所以你只能让MCU侧去迁就它。我建议先用逻辑分析仪抓一下芯片复位后能不能收到任何自动返回的信息,或者直接发一条读寄存器命令,看返回的字节是否符合预期帧格式。

我在调试中遇到最典型的问题是:发送命令后没等ADC准备好就切到接收,结果把ADC响应的起始位当成了噪声或者直接漏掉,导致读回来的是错位数据。解决办法是命令发送和总线释放之间加一个明确的延时,我这边用的是一个10MHz步进的定时器延时,先发命令,延时1ms,再使能接收,这样稳得很。

另一个坑是:如果总线上挂载了多颗ADS122U04IPWR,每颗芯片的响应时序由于复位时间不同可能会有微小的错位,最好不要把所有DIO都并联到一根总线上。我的做法是每颗ADC一个UART引脚,用空间换时间,彻底避免地址冲突和总线竞争。如果你非要一根总线挂多个芯片,需要额外引入GPIO控制的片选逻辑,或者利用每颗芯片的DIO使能机制,复杂度会上升很多。

5. 固件实现:从寄存器配置到稳定温度值的处理链

5.1 配置寄存器的目标和换算逻辑

ADS122U04IPWR的寄存器配置是整个固件的核心。寄存器主要控制四类东西:输入多路复用器MUX选择哪两个引脚做差分输入、PGA增益设为多少、数据速率和转换模式、IDAC电流大小以及内部温度传感器是否启用。

我在PT100通道上的配置思路是:输入MUX选择AIN0和AIN1作为差分对,PGA增益设为8,IDAC电流设为1mA,转换模式设为连续转换。为什么增益取8?因为PT100在0°C下100Ω、1mA激励只产生0.1V信号,而PGA=8时满量程范围大约是2.048V/8=0.256V,0.1V正好落在量程的39%左右,既保证了分辨率又留了温升余量。

这里必须提醒一句:不同数据手册版本对寄存器位的定义可能有细微差别,我不建议直接照抄别人工程里的配置字节。最好的做法是拿数据手册的寄存器表,把你要设置的每个字段(MUX选择、增益编码、数据速率、IDAC编码)逐个查出来,然后手动拼成配置字节。我项目里最终验证可用的几个配置值,都是在白板上演算过一遍才写进代码的,这样后面排查问题时心里有数。

5.2 连续转换模式的数据读取

配置完成后,ADC就会以20SPS的速率不停转换。但因为单线UART半双工的限制,你没法让ADC"主动推送"数据,只能靠主机周期性地发读命令去取。

我用的读取流程是:主循环每100ms对四个通道轮询一次,每次轮询发一个读数据命令,然后等待接收3个字节,拼成一个24位有符号数。把这个数字经过比例计算变成RTD阻值,再通过温度线性化查表或者多项式拟合得到温度值。

这里有个细节值得说:24位ADC输出的24位数据是二进制补码格式,正负号别搞错。如果你是单端输入,通常读出来是正的;如果是差分输入接反了,可能得到负数,意味着传感器接反了。我在代码里加了一个符号判断,如果连续多个周期读到的温度值低于-50°C且码值为负,就置一个"输入反接报警"标志,现场接线的人会非常感谢这个设置。

5.3 滤波与传感器线性化

ADC本身的噪声很低,但工业现场会有50Hz工频干扰。delta-sigma ADC内置的sinc滤波器对工频及其整数倍有不错的抑制效果,当数据速率设为20SPS,恰好50Hz干扰会被强烈衰减。这是另一个我觉得选20SPS很合理的原因:50Hz的工频干扰在被采样时会混叠到低频,20SPS配合内部滤波器能得到一个非常干净的读值。

我另外在固件里加了一个简单的滑动平均滤波,窗口长度5个样本。这个滤波要特别注意相位滞后:温度本来就变化慢,5个样本窗口引起的滞后在工程上可以接受。如果窗口设得太长,比如30个样本(1.5秒),PID控制回路就会觉得温度"反应迟钝",反而影响控制稳定性,这点在做风柜温度控制时尤其重要。

线性化方面,PT100和PT1000我都用了IEC 60751标准的多项式拟合,PT100在-200°C到850°C范围内的精度可以做到小数点后一位。热电偶通道则用分段查表加线性插值,每段覆盖50°C,插入点之间用线性插值,实测精度足够。

6. 实测精度、标定流程和效率结论

6.1 误差源分析

24位ADC听起来分辨率很高,但工程上更看重的是有效分辨率。ADS122U04IPWR在20SPS、PGA=8的条件下,无噪声分辨率大概在17到18位左右,换算成PT100的温度分辨率大约万分之一摄氏度。这个数值已经非常够用,但要想真正达到这个精度,必须把外部的误差源压住。

误差源主要来自四个方面:参考电阻RREF的温度系数、激励电流的温漂、ADC的偏移和增益误差、以及PCB漏电流。前面说过,比例式测量抵消了激励电流的绝对值误差,但抵消不了两个IDAC之间的失配。好在内部的IDAC匹配度做得很高,实际影响很小。反而是参考电阻RREF必须严格挑选,我用的是0.1%、5ppm/°C的金属箔电阻,价格比普通电阻贵好几倍,但这颗电阻是整套系统的"基准",省在它身上不划算。

6.2 现场标定怎么做

再好的硬件,批量生产时也会有个体差异,所以标定不能省。我在项目里做了两步标定:第一步是出厂前用精密电阻箱做电气标定,把每个通道的零点和增益误差算出来存入Flash;第二步是在现场用标准水浴或者便携式干井炉做温度点验证,通常只标0°C和100°C两个点就够了。

标定的本质很简单:一次测量是y = kx + b,k是增益误差,b是偏移误差,标定就是用已知标准值求出k和b,然后在固件里做逆运算补偿。需要注意的是,增益误差和偏移误差在不同PGA增益档位下不是完全一样的,如果你在同一个通道上切换过增益,最好每个增益档单独标一次。我在这个项目里PT100通道固定用增益8,所以只标了一组系数。

6.3 实测数据表现与给后来者的建议

整套系统做完之后,我用一个标准铂电阻温度计做对比测试:在5°C到60°C的范围内,每个设定点稳定半小时后记录测量值。结果最大偏差出现在接近环境温区的部分,约0.05°C,其余区间基本都在0.02°C以内。这个指标对冷冻站供水回水温差和风柜送风温度控制来说,已经比绝大多数工程要求的0.2°C精度高出一个数量级了。

最后给准备用这颗芯片的人几点建议:如果你只是做一个常温下测PT100的简单项目,ADS122U04IPWR有点杀鸡用牛刀,成本敏感的话可以看看16位的ADS112U04;如果你的系统已经有现成的SPI总线和空闲引脚,选ADS1220也许更顺手,代码上也更常规。但如果你的场景是"多通道、长距离走线、主控引脚紧张",追求的是长期稳定而不是高速采样,那这颗单线UART的24位ADC就是一个非常合适的选项。

ADS122U04IPWR这套方案最让我满意的不是参数有多高,而是整个链路在每个环节都有明确的取舍依据:单线接口省了引脚、比例式测量省了高精度恒流源、20SPS换来的是极低的噪声和工频抑制。这种"刚刚好"的设计,才是工业测量里最难能可贵的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/5 5:03:05

ADS122U04与STM32F756ZG高精度温度采集系统设计实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/5 5:02:45

S7-200 SMART PLC实现Modbus RTU总线数据侦听与故障诊断

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/5 5:02:28

工业级温度采集系统:ADS122U04IPWR+PIC32MZ硬核设计指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/5 5:01:58

UART接口24位ADC ADS122U04与STM32L4的高精度HVAC测温实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/5 5:01:31

QNX内存分析利器pmap:从原理到实战排查内存泄漏与碎片

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/11/5 5:01:10

工业多路测温方案:24位ADC+PIC32+UART接口实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华