ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于UART串口24位ADC与PIC18F的高精度温度采集系统设计

基于UART串口24位ADC与PIC18F的高精度温度采集系统设计

1. 为什么是 UART 串口 ADC 加 PIC18F?这不是偶然

1.1 工业现场里 SPI 的处境,你应该深有体会

之前帮朋友调试一个 HVAC 水系统的温度采集板,现场反馈数据老是跳。板子上用的是常规 SPI 接口的 24 位 ADC,MCU 和 ADC 之间就一根 PCB 走线,长度不到 5 厘米,按理说不会有什么问题。但现场旁边就是变频水泵,走线一靠近功率驱动部分,转换结果就明显抖动。后来换了带隔离的改法,成本直接上去一截。

工业现场和干净的实验室环境完全是两回事。SPI 接口看起来很快,但它的时钟线、数据线、片选线对走线长度和干扰都比较敏感,距离一拉长就要考虑信号完整性;真要加隔离,至少得隔离四条线,光耦也好、数字隔离器也好,成本和时间都翻倍。UART 就不一样了,点对点两根线(TX、RX),天生就是为"远一点、简单一点"设计的。再加上 UART 本身有起始位、停止位做帧同步,哪怕中间有毛刺干扰,只要波特率误差在容限内,数据基本不会错。

ADS122U04IPWR 的思路很有意思,它把 24 位 Δ-Σ ADC 和 UART 通信接口做在一起。在仪表行业干久了你就知道,"高精度 ADC 带串口"这种组合很少见。常规高精度 ADC 几乎全是 SPI 或者 I2C,串口版本的选项并不多。ADS122U04 的出现,让"模拟前端 + MCU"之间的连接直接从四线降成两线,隔离也只需要两个通道。这一条,放在工业或者 HVAC 现场,价值比多几个采样率选项实在得多。

1.2 PIC18F96J65 在这个方案里扮演什么角色

PIC18F96J65 属于 Microchip 的 PIC18F 增强型系列。你可能更熟悉 PIC18F4620 或者 PIC18F27K42,这一颗的定位和它们类似,属于老牌、成熟、供货稳定的 8 位 MCU 家族。做温控项目选 PIC18F,图的就是它的工程生态——编译器成熟、下载调试器便宜、参考代码多、工程师上手门槛低。很多做暖通自控、工业仪表的公司,产品线里几十年如一日用着 PIC18F 系列,这不是情怀,是维护成本和供应链稳定性的现实考虑。

在这套方案里,PIC18F96J65 要干的事很聚焦:通过 UART 和 ADS122U04 通信,把转换结果读出来,再做温度换算、滤波、越限判断,最后通过另一路串口或者 RS-485 把数据送上位机。它不需要碰模拟信号,那是 ADC 的本职工作;也不需要算复杂的浮点多项式,更重的换算可以根据工程需求放到上位机或者干脆用查表法解决。

有人会问:PIC18F 的频率不算高,跑得动吗?答案是够用。ADS122U04 的采样率最高可以到 120SPS 左右(实际受滤波配置影响),这个量级的通信频率对任何一个 PIC18F 来说都是绰绰有余。真正费时间的是控制逻辑、报警处理、通信协议,这些恰恰是 PIC18F 的老本行。

1.3 两颗芯片的分工,本质上就是模拟与逻辑的分工

把这套电路看成一个团队就清楚了。ADS122U04 是模拟前端专家:它负责把热电偶的微伏级信号、PT100 的毫伏级变化,通过 PGA 放大、24 位 Δ-Σ 调制、数字滤波,变成一串可靠的数字码。PIC18F96J65 则是逻辑中枢:它不管信号有多微弱,只管把数字码读进内存、按协议换算、再按通信协议发出去。

这种分工最大的好处是各干各的、各擅所长。模拟部分由一颗专用芯片完成,信号链路很清晰。而且 ADS122U04 内部集成了精密电流源、故障检测和内部温度传感功能,相当于把模拟前端的"外围配套"也一起打包了。MCU 这边则完全不用关心模拟细节,软件架构清爽很多。

尤其要注意的是,PIC18F96J65 和 ADS122U04 之间用 UART 连接,天然具备"异步隔离"的潜力。你需要做电气隔离时,两个 UART 信号线之间随便插一对数字隔离器或者光耦就完了,不需要像 SPI 那样处理时钟同步问题。这一点在工业现场意义重大——很多温度采集板最终都要过认证,隔离方案越简单,PCB 改版次数越少。

2. 温度传感器前端电路,决定精度的往往不是 ADC 本身

2.1 热电偶输入:小信号放大、共模范围和冷端补偿

热电偶为啥难测?因为信号太小。K 型热电偶的灵敏度大约是 41μV/°C,也就是说温度变化 1°C,输出电压才变几十微伏。室温下测 0 到 100°C 的变化,满量程也只有 4mV 左右。这要求 ADC 的前级增益必须足够大。ADS122U04 的可编程增益最高可以到 128 倍,配合 24 位分辨率,理论上能分辨微伏级别的电压变化,这也是这类高精度 Δ-Σ ADC 的核心价值所在。

信号小,还有一个容易被忽略的问题:共模输入范围。很多人只盯着增益,忘了查 PGA 的输入范围。ADS122U04 的 PGA 输入端要求信号电压落在合理的共模范围内,如果热电偶的一根线接地、另一根线上叠加了明显的共模噪声,即使差分信号正确,转换结果也可能出现非线性甚至完全错误。实际接法上,我曾经踩过坑:热电偶负端直接接 AGND,结果在电机启动瞬间读数乱跳。后来改成用分压电阻把输入共模抬高到电源中间电位附近,问题立刻消失。所以热电偶输入端不该简单地"负极接地",要留出共模偏置的余量。

冷端补偿(CJC)也是热电偶测量绕不开的环节。ADS122U04 内部有一个温度传感器,很多初学者第一反应是直接用它的读数做冷端补偿。经验上我不推荐这么干,原因有两点:第一,芯片自身会有发热,芯片温度并不等于热电偶端子处的实际温度;第二,热电偶接线端子在 PCB 边缘,和芯片之间隔着走线、铜皮,温差在冷热交替的环境下可能达到好几度,这对温度精度是致命打击。稳妥的做法是在端子附近放一颗 NTC 热敏电阻或者 PT1000,紧贴热电偶冷端,用 ADC 的一个辅助通道去测它,再结合查表做补偿。

2.2 RTD 输入:内置 IDAC 电流源和三线制接法

RTD(热电阻)是 HVAC 里更常见的传感器,PT100、PT1000 用得最多。RTD 的测量原理简单粗暴:给电阻通一个已知电流,测它两端的电压,再反算电阻和温度。这里面最大的敌人是导线电阻。两颗螺丝端子之间的引线,如果长了,导线电阻本身就有几欧姆,PT100 在 0°C 时只有 100 欧姆,导线电阻带来的误差占比非常大。

解决思路有三种:两线制最简单,但精度最差;四线制最准,但要多拉两根线,现场成本高;三线制是工业标准做法,用两路相同的激励电流分别流过传感器和参考路径,只要两条导线电阻相等,误差就能互相抵消。ADS122U04 内部集成了两个精密 IDAC 电流源,正是为三线制、四线制 RTD 测量准备的。设计时让 IDAC1 给传感器提供激励,IDAC2 给参考电阻提供同样的电流,再用差分输入去测传感器上的电压降,导线的压降就被排除了。

选参考电阻也有讲究。RTD 的测量最好做成比率式:ADC 的参考电压取自同一个激励电流流过精密参考电阻产生的压降。这样即便电流源有微小的温漂和波动,激励电流和参考电压同步变化,最终转换结果基本不受影响。这个技巧是仪表设计里非常经典的做法,能省掉很多标定的功夫。

2.3 前端滤波与保护,别让 TVS 管毁了你辛辛苦苦测的小信号

任何一个从外面接传感器的端口,都要考虑 ESD、浪涌和射频干扰。热电偶线可能长达几十米,就像一根天线,把变频器、电机、无线对讲机的干扰全收进来。常规做法是在输入端串 RC 低通滤波器,再接 TVS 管或者瞬态抑制二极管。

RC 滤波器的截止频率要结合 ADC 的数据速率来定。ADS122U04 内部有数字滤波,对外部模拟 RC 的要求是能抑制高频噪声、避免混叠就行。RC 时间常数太大反而坏事:它会拖慢信号建立时间,在通道切换或传感器断路恢复时,要等很久数据才能稳定。一般工程上取几 kΩ 电阻加 100nF 到 1μF 电容的组合,兼顾滤波和响应速度。

TVS 管要注意漏电流问题。普通 TVS 管在低压下也有微安级的漏电流,热电偶源阻抗低还好,要是接高阻传感器或者小电流激励的 RTD,漏电流会在测量回路上产生不可忽视的电压。高精度、高阻场景下,要么选漏电小的专用 TVS,要么加大 RC 串联电阻限定漏电流路径。这种细节,模拟仿真是看不出来的,只有整机测试才能暴露。

3. 从串口链路到固件实现:ADS122U04 通信协议怎么看

3.1 命令帧、数据帧和"主发字节才能读数据"的机制

ADS122U04 的 UART 接口和我们平时用的 ASCII 串口协议不太一样。平时我们用串口,通常是一来一回、一问一答。ADS122U04 则更接近 SPI 的思维方式:帧同步完全靠主机。MCU 发给 ADC 的每一个字节,不仅是命令,还为 ADC 的数据输出提供"移出时钟"。换句话说,你要读 ADC 的数据,就得主动往串口发字节,ADC 会随着你的发送过程把数据一位一位送出来。这个机制看起来绕,但实际用起来很顺手,因为它意味着接收缓冲区永远不会被堆满,你只要按节奏问,它就按节奏答。

命令帧的长度是固定的,一般三字节起底。第一字节是命令码,第二、三字节带有地址、寄存器数据或者校验信息。具体每个命令码对应什么操作,务必以官方数据手册中"UART Command"章节的时序为准,不同批次芯片的寄存器映射也可能有差异。我的习惯是先把数据手册里给出的时序图翻译成一张状态表:发送什么字节、期望接收什么字节、什么时候需要等待、什么时候算超时,写驱动时对着表逐行填代码,比对着英文时序文档写靠谱得多。

读取转换数据时,主机会先发读数据命令,然后连续发送四个字节时钟(具体数量视数据帧长度而定,通常为状态字节加 24 位数据共 32 位)。ADC 在接收到时钟字节的同时,从 DOUT 引脚逐字节送出数据。MCU 端 UART 接收中断收到的内容,按顺序拼装成一个 32 位的整型变量,再拆出状态位和有效数据位。整个过程其实就是"每发一个字节,就接收一个字节",逻辑上并不复杂。

3.2 寄存器配置:增益、通道、数据速率、参考源

ADS122U04 的配置寄存器大概分为几块:输入多路开关选择(MUX)、PGA 增益、数据速率/滤波模式、转换模式(单次/连续)、参考电压来源,以及 IDAC 电流设置。对温度测量来说,这些配置寄存器怎么填,取决于前端传感器类型,我把常用的搭配整理成了下面的对照表:

配置项热电偶(K 型)PT100 三线制PT1000 两线制
PGA 增益32 或 64(信号小)8 或 164 或 8
MUX 通道差分通道,接热电偶两端差分通道,跨 RTD差分通道,跨 RTD
IDAC 电流关闭250μA 或 500μA250μA
参考源外部基准(1.65V~2.5V)外部基准电阻外部基准电阻
数据速率20SPS 或更高20SPS20SPS

需要说明的是,上表只是工程上的起点,具体位域值要以你拿到的数据手册中的寄存器位定义为准。配置寄存器通常支持写后读回验证,固件初始化里建议把关键寄存器内容读回来比对,防止因波特率误码导致配置写错。我碰到过一个案例,就是初始化阶段偶发一位错误,把 MUX 通道写歪了,导致明明接的是 1 通道,读到的却是 3 通道的数据,排查了很久才怀疑到寄存器配置上。

3.3 状态字节、故障位和数据有效判断

转换数据的第一个字节是状态字节,里面藏着很多调试时有用的信息。比如过载状态位、内部温度传感器状态、PGA 饱和标志等。写驱动时千万别把状态字节丢掉,只取后 24 位就当温度算。正确的做法是:先做状态字节检查,如果发现 PGA 饱和或者输入过载,就要认为本次数据无效,将结果丢弃并置一个故障标志,等下一个转换周期重新读取。

这里还要说一个"数据过期"的问题。有些项目把 ADC 配置成连续转换模式,MCU 这边 100ms 读一次,但 ADC 实际已经转了更多的数据,你读到的可能只是缓冲区里的最新值。如果 PID 控制算法要求严格的采样间隔,建议使用单次转换模式:每次需要数据时,先发触发命令,等待 DRDY 信号(ADS122U04 支持通过 DOUT/DRDY 引脚指示转换完成),再读数据。虽然多了等待时间,但数据的时间戳是可控的,控制算法不会因为数据节奏不均匀而抖动。

4. 从原始码算成温度:算法细节与实测校准

4.1 先把数字码换算成电压值

ADS122U04 是 24 位 ADC,输出是二进制补码格式。换算公式并不复杂:

电压值 = (原始码 / 2^23) × (参考电压 / PGA 增益)

举例来说,如果参考电压是 2.048V,PGA 增益是 32,原始码读到 0x400000(8388608),那么电压大约是 (8388608 / 8388608) × (2.048 / 32) = 0.064V,也就是 64mV。注意式子里分母是 2^23 而不是 2^24,因为 24 位补码的满量程对应正负半个参考电压,换算时要把符号位考虑进去。

写代码时要把这个计算放在 float 或者足够宽的定点数环境里执行,PIC18F 上如果用 8 位单片机做浮点计算会慢一些,但温度采样本来就不是高速场景,几百毫秒才算一次,浮点性能完全够用。如果想提速,可以先把(参考电压/PGA增益)这个系数算成常量,每次换算就是一次乘法和一次移位。

4.2 热电偶温度换算:查表法比多项式更适合 MCU

从电压反推热电偶温度,正经做法是用 NIST 多项式。K 型热电偶的多项式系数一长串,从 -200°C 到 1370°C 分成多段,每段系数都不同。在 PC 上跑这没问题,但塞进 PIC18F 里,代码空间和浮点计算量都不太好看,而且系数表本身也容易抄错。

工程实践中我更推荐分段查表法:在程序里内置一张电压-温度对照表(从 -200°C 到 +1300°C 每隔 10°C 一个点),运行时先用线性插值求出精度达到 0.1°C 的温度值。查表法的好处是逻辑透明、依赖少,而且表格可以用脚本从 NIST 数据自动生成,不会有人工抄写的误差。

热电偶的完整测温流程是:

  1. 读取 ADC 原始码,换算成热电偶回路的总电压 V_total。
  2. 读取冷端温度 T_cj(来自板载 NTC 或 PT1000)。
  3. 查表得到 T_cj 对应的热电偶电势 E_cj。
  4. 计算热端电势 E_hot = V_total + E_cj。
  5. 用 E_hot 查表反查热端温度 T_hot,这就是最终被测温度。

很多人漏掉的就是第 3、4 步。如果环境温度变化不大,你可能感觉不出来;但 HVAC 现场一年四季温差几十度,不加冷端补偿的读数偏差会大到完全不可用。

4.3 RTD 的 Callendar-Van Dusen 换算和线性化

PT100 的温度-电阻关系用 Callendar-Van Dusen 方程描述,正温段比较简单:

R(T) = R0 × [1 + A×T + B×T²]

其中 R0 是 0°C 时的标称阻值(PT100 就是 100Ω),A、B 是常数。反推温度就是解这个一元二次方程,代码里用求根公式就能搞定。工程实现时我通常会加上一个简单的迭代修正,或者直接分段线性化——0°C 到 100°C 之间 PT100 平均灵敏度约 0.385Ω/°C,100°C 以下用线性逼近就能做到 0.2°C 以内,很多 HVAC 项目完全够用。

如果做的是高精度工业测温,那么 CVD 方程的 C 系数(负温段)和一个小的自热修正都得加进去。自热修正是很多项目的隐性误差来源:IDAC 激励电流流过 RTD 时本身会产生焦耳热,电流越大,自热越明显。250μA 激励在 100Ω 的 PT100 上产生约 6.25mW 功率,这个量级对普通工业 RTD 影响不大,但如果你把激励电流设到 1mA,自热误差就可能超过 0.1°C。所以,激励电流选择要结合 RTD 的热响应特性和精度要求来权衡。

5. 真实项目里那些与你较劲的问题:供电、隔离与排查链路

5.1 供电和地线布局,比传感器本身更影响精度

24 位 ADC 的分辨率很高,但也意味着它对电源噪声和地电位差更敏感。ADS122U04 通常有独立的模拟电源和数字电源引脚,原理图上建议分成 AVDD 和 DVDD 两路供电,每路都有各自的去耦电容,且电容要尽量靠近芯片引脚摆放。数字地和模拟地在 ADC 芯片附近单点汇合,不要让数字地电流流过模拟地回路。

参考电压引脚的去耦更关键。参考电压是整个转换的"尺子",它稍微抖一下,转换结果就跟着系统性偏移。如果是外部基准(比如 REF5025 这类精密基准),基准输出到 ADC 参考引脚的走线尽量短、加宽,旁边放至少 10μF 的钽电容和 0.1μF 陶瓷电容并联去耦。我见过不少板子,传感器和 ADC 都选得很好,就是基准去耦电容放得太随意,结果实测精度只有理论值的一半。

电源本身如果需要从 24V 工业电源取电,建议先用 DC-DC 降到 5V 左右,再经 LDO 得到模拟电源。DC-DC 的开关噪声是模拟电路的常见干扰源,LDO 的电源抑制比能挡掉一大部分,但关键还是要让 DC-DC 的走线远离模拟信号区域。

5.2 采样速率、分辨率与 50/60Hz 抑制的取舍

ADS122U04 的数据速率配置和数字滤波模式会影响有效分辨率。滤波带宽越窄,抑制工频干扰的能力越强,但响应越慢。HVAC 这种 60 秒积累一次数据的应用,用 20SPS 甚至更低速率完全没问题,50/60Hz 工频干扰会被内置 SINC 滤波器吃掉。但如果你要做的不是 HVAC 而是电机保护或者快速温控,20SPS 可能不够用,这时候就得把速率提到 500SPS 以上,代价是噪声指标变差、有效位数下降。

目标应用推荐数据速率滤波器模式权衡说明
HVAC 房间温度20SPSSINC3 + 50/60Hz 抑制精度优先,响应慢可接受
冷冻水/热水温度20~40SPSSINC3兼顾精度和报警响应
工业过程控制100~500SPSSINC3 快速滤波牺牲部分分辨率换速度
快速温度巡检≥1000SPS不推荐分辨率损失严重,慎用

这个取舍没有标准答案,完全取决于现场温度变化有多快。我的经验是:先确定系统允许的温度响应滞后时间,再反推最低采样率,最后在这个采样率下查数据手册的有效分辨率表,看能不能满足精度指标。三个参数能闭环,方案才算成立。

5.3 现场排障链路:从症状定位到抓帧验证

真到了现场,温度数据不对通常表现为三种症状:乱跳、漂移、固定值。

乱跳,优先怀疑干扰和接线。用示波器看 ADC 输入前端,重点查传感器线是不是和动力线走了同一个线槽,屏蔽层是不是只在单端接地,UART 通信线有没有靠近电源走线。这时候可以先把 PGA 增益调低一档,如果乱跳现象明显减轻,基本可以判定是前级噪声过大,而不是通信问题。

漂移,优先怀疑冷端补偿和基准。用手摸一下板子上的冷端测温点,看读数会不会跟着手心温度变化;再用万用表实测基准电压,看它是否稳定。我遇到过一种情况:基准电压随着板温上升而下降,读数持续漂移,最后发现是基准芯片旁边的散热过孔把热传导到了基准的敏感引脚。

固定值不动,优先怀疑通信链路和数据有效位。把 MCU 发出去的配置命令原样抓出来,和 ADC 实际收到的内容对比;再用读寄存器命令逐字节读回配置,确认芯片确实按你的预期工作了。UART 波特率误差在高波特率下是隐形杀手,超过 3% 的误差就可能造成整帧错位,这种问题最隐蔽,也最值得在排查一开始就排除。

这三大类问题排查完,还有一招很实用:把 ADC 输入短接成内部的二分之一电源电压(伪差分),看读值是否稳定在被测电源的 2.048V 附近。这个"自检"能区分问题在前级传感器电路还是在 ADC/软件链路,能帮你快速缩小排查范围。

我自己做这种项目的习惯是:PCB 还在画的时候,就把上位机的串口解析脚本写好,等板子回来一上电就能立刻看到寄存器读回的原始波形和数据值。少做一步验证,就可能多花一周在现场对着示波器猜问题。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进