1. 项目概述:一个 24 位 ADC 与一颗 MCU 如何撑起工业级温度采集
这段时间一直在调一个分布式测温节点的方案,最终落地的核心是两个关键器件:TI 的 ADS122U04IPWR 和瑞萨的 R7KA8M2JFLCAC。前者是一颗带 UART 接口的 24 位 Delta-Sigma ADC,后者是一颗 ARM Cortex-M 内核的 32 位通用 MCU。这套组合把工业机柜里的 RTD 测温点、HVAC 风管里的 NTC 探头、冷水机组回水管上的 4-20mA 温度变送器全部统一收进来了,实测两个月,整体表现很稳。
这篇文章就是把这个项目的完整思路写出来,从硬件选型、传感器接入、UART 通信协议,到固件里的线性化和现场调试的坑,一步步拆开看。如果你正在做温度采集、HVAC 控制器、机房环境监控这类工作,或者只是在纠结“到底用 MCU 内置 ADC 还是外挂一颗 24 位 ADC”,那么这篇文章应该能帮你少走不少弯路。
先说一个我自己的判断:温度采集这类场景,看起来简单,实际上对精度的要求往往不是“量个大概”,而是要在零下 20℃ 到 150℃ 甚至更高的范围内,保持线性、可重复、抗干扰。MCU 内置 ADC 在某些低成本场景确实够用,但只要进入工业现场,或者要和 HVAC 系统的控制逻辑联动,内置 ADC 的共模抑制比、动态范围、稳定性往往就不够看了。这也是为什么我坚持在 R7KA8M2JFLCAC 旁边挂一颗独立的高精度 ADC——哪怕多花几块钱成本,也值得。
1.1 从场景出发拆解需求
工业现场和 HVAC 的温度测量,看起来都叫“测温度”,实际上对系统的要求差异很大,放在同一个方案里就得同时兼顾。
工业场景里常见的是 PT100 三线制、四线制,也有热电偶,测温范围宽,现场电磁干扰大,而且传感器连线动不动就是几十米。HVAC 场景则更常见 NTC 热敏电阻,比如 10K NTC,精度要求没那么极端,但要求长期稳定、一致性好,控制逻辑还要求响应足够快。还有一个共同点是,这两类系统都希望主控平台能同时挂多个通道,不同通道接不同类型的传感器,而不是一种传感器就要换一个方案。
我最后定的架构是:ADS122U04IPWR 负责把所有模拟信号数字化,R7KA8M2JFLCAC 负责读数据、做传感器线性化换算、跑报警判断,再通过现场总线或者内部协议交互。ADC 和 MCU 之间用 UART 互联,而不是传统的 SPI,这个细节后面细说。核心思路就是把“模拟前端”和“控制逻辑”彻底分离,模拟部分交给专用芯片,控制部分交给通用 MCU,各干各的,调试也不容易互相干扰。
1.2 为什么选择外置 ADC 而不是 MCU 内置 ADC
R7KA8M2JFLCAC 这个级别的 MCU 内部通常也有 ADC,如果只是采一个温度点,确实没必要外挂。但我在这个项目里要同时处理多类传感器,还要保证在工业现场的长期稳定性,内置 ADC 有几个很难绕开的问题:
- 内置 ADC 的参考电压精度和温漂通常较弱,温度采集要求好的长期稳定性,这一点很吃亏;
- 内置 ADC 的量程和 PGA 增益调节范围有限,配合不同传感器时灵活性差;
- 最关键的是抗干扰能力。工业现场有变频器、水泵电机、电磁阀,这些设备一动作,地线上和电源线上的噪声就非常难看,外置 ΔΣ ADC 的数字滤波能力明显更强。
ADS122U04IPWR 是一颗非常经典的低功耗 ΔΣ ADC,它有四个模拟输入通道,可以配置成差分或单端输入,内部集成了可编程增益放大器(PGA)、两个恒流源、内部基准,甚至还有一个用于热电偶冷端补偿的内部温度传感器。换句话说,它已经不是一个“裸 ADC”,而是一个模拟前端解决方案。对应到应用上,PT100、热电偶、NTC 这些传感器,不需要再额外堆一堆运放和调理电路,直接接上去就可以,这从 PCB 面积和物料成本上看都是划算的。
2. 两个器件的分工协作,以及 UART 接口的特别之处
2.1 ADS122U04IPWR 的角色:模拟前端与数字转换一体
ADS122U04 名字里的“U”代表的是 UART 接口。这个设计在 TI 的 ADC 系列里比较有特色,它把原本用 SPI 或 I2C 和主控通信的方式,改成了 UART 帧通信。这样做的一个直观好处是接线少,主控端只需要一对 TX/RX 引脚就能完成配置和读取,而且 UART 本身就是所有 MCU 最基础的外设,不需要去适配 SPI 时序,尤其是在主控引脚紧张的时候,这个优势更明显。
芯片内部集成了很多对温度采集非常实用的模块:
- 24 位 ΔΣ 调制器,内置数字滤波器;
- 可编程增益放大,增益从 1 到 128 可调;
- 两个可配置的恒流源(IDAC),输出电流从 10μA 到 1.5mA 可调;
- 内部 2.048V 基准电压,也可以使用外部基准;
- 内部温度传感器,用于热电偶冷端补偿;
- 四个输入通道,支持差分和单端两种接入方式。
从这个清单可以看出,这个 ADC 就是为传感器测量准备的,而不是通用电压采集。特别是两个 IDAC 恒流源,做 PT100 三线制的时候,一路电流激励,一路做线阻补偿,硬件上不需要额外加任何电流源电路,直接把 PT100 的传感器端子接到 ADC 输入通道上就行。
从实际使用体验来说,这颗芯片的内部基准温漂做得相当不错,在 0℃ 到 70℃ 的温度范围内,我不需要另买高精度基准 IC,直接使用内部基准,就能把 PT100 测温误差控制在比较理想的范围。对于 HVAC 和大部分工业机柜场景,这个精度已经足够。
2.2 R7KA8M2JFLCAC 的角色:数据消费方与控制逻辑核心
R7KA8M2JFLCAC 这颗 MCU,不是那种特别夸张的高端型号,但它的资源优势非常合适这个项目。它有足够的 UART 外设,其中一个固定分给 ADC,另外的可以对接现场总线;它有 DMA 和中断机制,可以做到 ADC 数据到手后直接搬运到内存,不占用 CPU 计算时间;它的运算能力对于做浮点线性化换算也够用。
在这个系统里,MCU 的主要工作有四个:
第一,初始化 ADS122U04IPWR。包括设置转换速率、PGA 增益、输入通道选择、IDAC 电流大小,全部是通过 UART 写寄存器完成的。
第二,周期读取转换结果。接收 ADC 回传的数据帧,校验帧头、校验码,然后解析出各个通道的原始 ADC 码。
第三,把 ADC 原始码换算成物理温度。不同传感器对应不同的算法:PT100 用查表或多项式拟合,NTC 用 Steinhart-Hart 方程或 B 值方程,热电偶需要做冷端补偿再加查表,这些全部在 MCU 里定时完成。
第四,数据上报与报警逻辑。换算出来的温度值最终要通过 Modbus 或者 CAN 报文发给上位机,同时 MCU 自己也要做超温、传感器断线这类判断,一旦发现异常直接本地处理。
还有一个细节值得提,R7KA8M2JFLCAC 的低功耗模式我研究了一下。HVAC 系统里面很多节点并不是不间断满负荷工作的,利用 MCU 的睡眠模式,再让 ADC 工作在较低转换速率下,整个节点在电池供电或者功率受限场景下也能跑。具体能省多少电和转换速率强相关,但这个方案的上限比普通“MCU 内置 ADC + 不断轮询”的做法高不少。
2.3 为什么用 UART 而不是 SPI
选型的时候,我一度想用带 SPI 接口的同类 ADC,因为大部分工程师对 SPI 更熟。后来实际对比,UART 方案在这个项目里优势很明显。
SPI 通信需要四根线或者至少三根线,而且主控必须作为主机主动发起时钟,长时间占用 MCU 时间。UART 只需要两根线,ADC 转换完成后可以主动往外发数据,MCU 只需要在中断里收,不需要频繁拉低片选去“催”数据。尤其在通道较多、转换频率又高的场景,这个区别会直接影响 CPU 占用率。
当然,UART 接口在同步方面有一个问题:它没有像 SPI 那样的硬件握手线,主控和 ADC 之间需要一个帧对齐机制。ADS122U04 在芯片内部设计了帧同步逻辑,初始化的时候通过特殊命令对齐帧边界,之后只要约定好波特率,就不会乱。这部分的时序细节比较敏感,后面章节我单独讲操作步骤。
3. 硬件设计要点:从传感器接入到布局布线
3.1 PT100 三线制的连接与线阻补偿
工业场景里 PT100 三线制是最常见的接法,就是因为它能抵消导线电阻。ADS122U04 的两个 IDAC 恒流源在这里用得恰到好处。
我实际的接法是这样的:IDAC1 输出接到 PT100 的一个端子,同时这个端子作为一路 ADC 输入的正端;PT100 的另一个端子接 IDAC2,同时作为 ADC 输入负端的一部分;另一根补偿线接到这第二个端子附近的公共点。ADC 差分输入端测到的电压,是 PT100 两端电压减去公共引线电阻上产生的压降,因为流过那根公共线的电流方向正好相反,线阻误差就抵消了。
如果只用单 IDAC,那 PT100 两根引线的电阻误差是直接串进测量回路里的。要知道铜导线温度系数大约是 0.4%/℃,100 米长的 0.5mm² 线,在温差变化 50℃ 的时候,等效误差可能达到好几欧姆,对应到 PT100 上就是几度甚至十几度的偏差,这是完全不可接受的。所以我在项目里强制要求所有远程 PT100 都走三线制接法。
TSSOP 封装的 ADS122U04 引脚间距比较小,做三线制接入的时候,走线上尽量让 IDAC 和差分输入端就近布置,避免长距离平行走线引入耦合噪声。我在第一版 PCB 上就因为把 IDAC 走线拉得太远,结果测量值在加热设备启动的时候出现了明显跳动,后来缩短走线并加宽了线间距才解决。
3.2 NTC 热敏电阻的接入与分压方式
HVAC 场景里大量使用 NTC,常见的是 10K NTC,25℃ 时阻值是 10kΩ。NTC 的特点是阻值随温度非线性变化,而且需要一个小电流流过它才能转换成电压信号。
用 ADS122U04 的时候,可以直接用内部 IDAC 给 NTC 供电,比如设置 100μA 的恒定电流,流过 NTC 后在 ADC 输入引脚上产生电压。这种方法的好处是激励电流恒定,电压和阻值成正比,后续换算比较干净。不过要注意一点,NTC 的阻值在低温时很大,100μA 电流在 -40℃ 时可能产生几伏的压降,要保证电压不超过 ADC 的输入范围。
我实际更常用的做法是用一个高质量参考电阻和 NTC 组成分压网络,然后用 ADC 比例测量法:同时采参考电阻上的电压和 NTC 上的电压,做比值换算。这样即使供电电压有轻微波动,也不影响测量结果。参考电阻我选了 0.1% 精度的 10kΩ 金属箔电阻,温漂控制在 5ppm/℃ 以内,整体成本也就几块钱,但精度保障很值得。
3.3 模拟部分与 MCU 部分的布局隔离
ADS122U04IPWR 属于高精度模拟器件,虽然它的数字滤波能力很强大,但硬件布局如果不注意,再好的 ADC 也会被噪声拉下水。
我在这块板上的布局策略是:模拟部分(ADC、传感器滤波电容、参考电阻)放在板子左侧,MCU 放在右侧,中间用地平面隔开。ADS122U04 的模拟电源和数字电源引脚分别独立走线,在靠近引脚的地方各放一个 10μF 钽电容和一个 0.1μF 陶瓷电容并联,做高频低频两级去耦。
还有一个很容易踩的坑是地线处理。UART 的 TX/RX 是数字信号,如果和模拟输入走线在 PCB 上平行走太长,数字边沿的跳变会通过寄生电容耦合到模拟信号上。我的板子上所有 UART 走线都刻意避开 ADC 模拟引脚,并且两侧都加了一条地线做屏蔽。虽然这不是什么高科技,但在实际测试中,这个布局调整让噪声底从大概正负 0.5℃ 的波动降到了正负 0.1℃ 以内。
3.4 电源的考虑
ADS122U04 的模拟供电我选了 3.3V 单独 LDO,没有直接用系统的 24V 转 5V 再降压。LDO 选择了低噪声型号,输出端对地加了 1μF 陶瓷电容。这个项目的实测经验是,用开关电源供电时,如果不加 π 型滤波,ADC 采样结果的噪声幅度会明显增大,表现为温度读数上随机跳动。后来我在 ADC 的电源入口串联了一个 10Ω 电阻和一个 4.7μF 电容组成 RC 滤波,再进 LDO,问题基本消失。
MCU 的电源和 ADC 的电源,我用了同一个 LDO 的两个输出支路,但在这个 LDO 和 ADC 引脚之间又串了一个磁珠。实测下来,MCU 频繁刷新 LED 和通信时,确实没有看到 ADC 测量数据受影响,这个磁珠起到了很好的隔离作用。
4. 固件实现:寄存器配置、线性化算法与 UART 数据解析
4.1 初始化序列与寄存器配置
ADS122U04IPWR 的初始化需要通过 UART 发送命令来写寄存器。这个初始化顺序非常重要,芯片上电后并不会像有些 ADC 那样直接开始转换,而是要等主机完成时钟同步和帧同步。
我总结的初始化流程是这样的:
- 等待 MCU 的 UART 外设就绪,设置波特率 115200,8 位数据,无校验,1 位停止位;
- ADC 上电后拉高复位引脚,等待至少 10ms 让内部晶振起振稳定;
- 发送复位命令,让芯片进入已知状态;
- 逐条写入寄存器配置,包括采样速率、PGA 增益、输入多路复用通道、IDAC 电流档位;
- 发送开始转换命令,等待转换完成事件;
- 接收第一帧数据,检查帧头帧尾,确认同步成功。
实际写配置的时候,以其中一个通道为例,我需要设置的是:AIN0 和 AIN1 作为差分输入对,PGA 增益设为 32,转换速率设为 20SPS,内部基准电压 2.048V,IDAC1 输出 1mA 用于 PT100 激励。这些参数写进去后,读回校验一遍。
这里有一个很重要的经验:写配置后一定要回读。我第一次调的时候,因为波特率不匹配,写寄存器的命令看似发出去了,但 ADC 根本没有收到,回读出来的全是默认值。花了一个多小时排查才意识到是 MCU 侧 UART 波特率配置差了 0.5%,导致帧全部错位。后来的所有初始化代码里都强制加了回读比对,一旦不一致直接重新初始化,避免了现场出现无法解释的间歇性故障。
4.2 UART 数据帧的接收与对齐
ADS122U04 在 UART 模式下,寄存器配置、命令、转换数据都通过 UART 帧传输。芯片有专门的数据格式,尾部和头部有标识位,MCU 端必须要按芯片手册的帧格式去解析。
我用的是一种简单但不脆弱的方式:采用状态机逐字节解析。状态机从空闲态开始,检测到帧头后进入载荷收集状态,收够固定长度的数据后进入校验状态,验证通过则整帧上报到应用层。
调试初期遇到得很典型的现象是:偶尔解析出来的温度值会突然跳变到一个离谱的值,跳一次之后就恢复正常。最后定位下来,原因是上电瞬间 MCU 的 UART 接收产生了一帧残缺数据,之后所有数据全部错位,但没有溢出也没有断连。解决办法是在状态机里遇到不合法帧头时,直接丢弃当前累积的所有字节,并重新回到空闲态等待下一个有效帧头。这不是什么复杂的代码技巧,但现场稳定性就靠这种细节撑着。
4.3 原始码到物理温度的换算方法
ADC 返回的是 24 位原始码。对于比例测量场景,先把原始码归一化,再结合传感器参数计算温度。
PT100 的换算听起来简单,就是把 ADC 测到的电阻值算出来,然后根据电阻值反查温度。但 PT100 的阻值和温度关系本身是非线性的,IEC 60751 标准给出的关系在 0℃ 以上和 0℃ 以下分别用不同多项式拟合。如果直接用线性近似到整个量程,误差会在 100℃ 点上达到好几度。
我在 MCU 里用的是多项式分段拟合,0℃ 以上用一次多项式近似都行,但为了精度我做到了二次拟合。代码里预存一组系数,运行时计算T = a0 + a1*R + a2*R*R,在 -50℃ 到 200℃ 量程范围内,拟合残差控制在 0.05℃ 以内,MCU 的浮点运算能力完全扛得住。
NTC 则完全不同。NTC 的温度特性是指数级的,我用 B 值方程:
T = 1 / (1/T0 + (1/B)*ln(R/R0)) - 273.15其中 T0 是 298.15K,R0 是 10kΩ,B 值根据 NTC 规格书填。这个公式用标准 C 语言的数学库函数就能实现,执行一次大概几十微秒,算不上负担。
热电偶用 ADS122U04 的时候,冷端补偿是关键。芯片内部温度传感器可以用来测量冷端温度,然后在软件里叠加修正值。我用的标准化查表法,冷端温度每 0.1℃ 一个修正值,插值之后和热端读数相加。实践下来,在 0℃ 到 60℃ 的冷端范围内,整体误差控制得很好,完全满足工业上 K 型热电偶 ±1℃ 的要求。
4.4 报警与断线检测逻辑
工业温度采集不能只看正常数据,传感器断线、短路、漂移这些异常必须能检测出来。ADS122U04 内部有激励电流源和传感器开路检测电路,配置好之后,如果传感器导线断裂,ADC 会输出靠近电源轨的电压,这个特征值直接就可以用。
我在 MCU 里也做了一层软件保护:如果连续 5 次采样值出现满偏码,就判定断线;如果采样值在设定阈值之外持续 10 秒,就上报温度异常。这样做的好处是,不至于因为一次偶发噪声就触发误报警,同时又能对真实故障做出及时响应。
室温环境里验证这些逻辑没什么问题,真正体现出价值是在一个冷冻水系统的现场。当时有一路 PT100 接线端子松动,接触电阻变大,测量值呈现缓慢漂移而不是一下子跳变,软件报警没有立刻触发,但已经能看出数据曲线异常。我后来在代码里加了对相邻两次采样差值的监控,一旦变化速率超过物理上不可能的上限,就直接标记数据异常。这个方法对 HVAC 这类温度变化相对平缓的应用特别有效。
5. 调试实录与常见问题排查
5.1 上电后读数全部是零
第一次打板回来后,上电测试,ADC 的读数一直都是零。我第一反应是焊接问题,但用示波器量 MCU 的 UART TX 引脚,波形是有的,ADC 的 TX 引脚也有数据。后来发现问题是 ADC 的复位引脚一直被我拉在低电平,芯片被按在复位状态,自然不可能工作。
这个坑看起来低级,但在实际项目中很容易出现。复位引脚上的上拉电阻后配到 MCU 的 GPIO,而 MCU 上电初始化阶段 GPIO 默认输出低电平,就把 ADC 按死在复位态了。解决办法是在 MCU 启动代码里把复位引脚尽快配置为高电平,或者在硬件上直接用上拉电阻挂到 3.3V,再通过开漏输出控制复位。
5.2 读数跳变且毫无规律
有一段时间测出来的温度值像心率图一样上下跳,排查了很久后来定位到是 MCU 的调试下载接口影响了 ADC。因为我用 J-Link 在线调试,调试口也会占用 MCU 的一些资源和时钟,导致实时性不稳定,而 UART 又没有缓冲区,某一帧数据丢了之后就导致后续解析错乱。
后面我改用板载 BOOT 方式烧录程序后脱机运行,问题彻底消失。实际上真实现场不可能一直挂着调试器跑的,所以这个现象并不影响最终交付,但它提醒我一件事:ADC 采集的实时性和调试器占用是两回事,开发阶段和成品阶段的环境必须分开验证。
5.3 长距离传感器线上的压降问题
HVAC 现场有些传感器并不是装在控制柜旁边,而是分布在风管、水管的各个角落,连线长度可能达到二三十米甚至更长。第一版代码里我把 IDAC 电流设成了 1mA,本以为没问题,实际测下来发现部分点位温度读数偏高,原因就是长引线的线阻上产生了额外压降。
后来我把长距离的 PT100 全部改成三线制,同时把 IDAC 电流提高到 1.5mA,信号幅度大了,线阻压降的影响比例就变小了。另外还需要注意,长线上会耦合交流噪声,ADC 的模拟滤波器和数字滤波器要同时配合,我最终把采样速率从 100SPS 降到了 20SPS,噪声抑制效果立竿见影。采样速率降低后的响应时间大概是 50ms,对温度控制来说完全够用。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查与对策 |
|---|---|---|
| 上电后读数全零 | 复位引脚一直被拉低 | 检查复位引脚默认电平,配置为上拉输出 |
| 读数固定为满码 | 传感器断线 | 查看断线检测标志,检查接线端子 |
| 读数缓慢漂移 | 接线端子氧化或松动 | 重新压接端子,加扭矩检查 |
| 读数波动大 | 开关电源噪声耦合 | 增加 LC 或 RC 滤波,检查地平面 |
| 通信间歇性异常 | 波特率偏差或帧失步 | 验证波特率精度,完善帧状态机 |
| 某通道读数为零 | IDAC 电流源没有给到该通道 | 检查通道配置,确认激励源输出引脚的选择 |
| 温度偏高且随线长变化 | 线阻影响未补偿 | 改为三线制,调整 IDAC 电流 |
5.5 现场校准那点事
ADS122U04 在出厂前有内部校准,但现场整体误差并不完全取决于 ADC 本身。传感器、分压电阻、接插件的误差都会叠加。我实际做了一件看上去很土但非常有用的事:拿一个经过第三方检定的水浴槽,配合标准铂电阻温度计,在 0℃、25℃、50℃、75℃、100℃ 五个温度点做系统级校准。然后把每个点的误差做线性插值,得到一个修正系数表,写进 R7KA8M2JFLCAC 的 Flash。
这个校准做完后,整套节点的最大误差从没校准前的 ±0.6℃ 降到了 ±0.15℃ 以内,效果非常明显。哪怕只做一个两点校准(0℃ 和 100℃),也能把大多数场景下的误差大幅压制。对于 HVAC 项目,预算允许的话建议至少做两点校准,比换更贵的传感器划算得多。
6. 这套组合后续还能怎么扩展
AVADS122U04 加 R7KA8M2JFLCAC 的组合还有一些我还没完全发挥的功能,写下来供大家参考。
一个是 ADC 的四个通道可以支持多种传感器混接。我现在只用了 PT100、NTC、热电偶各一个通道,还剩下一个通道闲置。如果后续需要增加湿度传感器或者压力传感器,同样可以通过差分输入接进来,只是线性化算法换一下。MCU 侧已经预留了 UART 通信口,多加一个传感器不需要改硬件,这个扩展性对产品迭代很友好。
另一个是数据上报协议。目前 R7KA8M2JFLCAC 通过 Modbus 协议上报温度值,与楼宇自控系统对接。因为 MCU 的资源还很富余,后续可以加一个本地缓存,把温度历史数据存到外部 Flash 里,掉电不丢失。这样如果上位机连续采集模块短时间断网,数据也不会全丢,补传机制做起来也不难。
最后是低功耗方向。HVAC 系统里有一部分传感器节点未来可能会往无线方向发展,那就需要把平均功耗降下来。ADS122U04 本来就有低功耗模式,R7KA8M2JFLCAC 也支持多种睡眠状态。目前这个组合在电池供电场景下的功耗还有优化空间,我有计划之后做一个低功耗版本,把转换速率降到 5SPS,MCU 长时间睡在待机态,只靠 RTC 唤醒去读一次数据,预计平均功耗能控制在微安级别。这个方向等我做完之后再单独写一篇分享。
回头来看,这个项目选型上没有追求“新”和“贵”,而是把注意力放在了匹配度上。ADS122U04IPWR 解决的是模拟信号质量的问题,R7KA8M2JFLCAC 解决的是数据处理和交互的问题。现场两个多月的运行数据说明,这套组合在工业现场和 HVAC 场景下都有足够的稳定性和精度。如果你现在也在规划类似的温度采集节点,可以从这套架构出发做裁剪,根据自己的传感器类型和通信方式灵活调整。