ADS122U04IPWR+PIC18F45K40:UART接口24位温度采集

发布时间:2026/11/4 22:09:28
ADS122U04IPWR+PIC18F45K40:UART接口24位温度采集

做仪表和暖通控制这些年,温度测量看着最简单,落地时却最容易翻车。前阵子我在一个冷水机组项目上要同时测水管温度和室外回风温度,控制器在配电柜里,传感器要走好几米线,最初想用 NTC 加 MCU 内置 ADC,结果被精度和长线传输搞得头大。后来定型成ADS122U04IPWR + PIC18F45K40的方案:一个是带 UART 接口的 24 位低功耗 ADC,一个是 Microchip 的通用 8 位 MCU,通过串口把工业温度传感器的原始信号转换成可靠的温度数据。这篇文章就把这个组合从选型、硬件到软硬联调完整拆开讲,适合正在做 HVAC 控制器、工业变送器或者现场温度采集板的工程师参考。

如果你以前只接触过 SPI 接口的 ADC,第一次看到 UART 接口的 ADC 可能会觉得奇怪,但恰恰是这个接口选择,让这套方案在 HVAC 这类分布式系统中特别好用。下面我会把为什么这么选、具体怎么接、代码怎么写、现场哪些坑必须躲,全部讲透。

1. 方案整体拆解:这套“ADC+MCU”组合解决了什么问题?

1.1 温度测量的真实痛点

工业现场和 HVAC 系统里,温度传感器无非那几种:PT100/PT1000 热电阻、热电偶、NTC 热敏电阻。信号类型看起来简单,真正要测准的时候,问题全冒出来了。

首先是信号太小。热电偶输出的是微伏级别的电压,比如 K 型热电偶在 0℃ 附近也就 39uV/℃ 左右的变化率,哪怕放大几十倍之后,对 ADC 的噪声和漂移要求都非常苛刻。其次是长线传输,传感器可能装在几十米外的风管上,普通 MCU 内置 ADC 根本扛不住共模干扰和线阻压降。第三个问题是引线电阻,RTD 的引线少则零点几欧、多则好几欧,而 PT100 在 0℃ 时的标称电阻恰恰就是 100Ω,引线电阻不抵消掉,测出来的温度可能偏差好几度,这在 HVAC 的 ±0.5℃ 精度要求下完全不可接受。

所以这个项目里,我一开始就排除了“MCU 内置 ADC + NTC”的方案。不是说 NTC 不能用,而是 NTC 的互换性和长期稳定性太差,HVAC 设备一做就是十几年寿命,现场换传感器成本极高。RTD 和热电偶才是中高端温度测量的正路,而这两类传感器都需要高分辨率、低噪声、带可编程增益放大器的外部 ADC。

1.2 为什么是 ADS122U04IPWR:低漂移、高分辨率、UART 直出

ADS122U04 是 TI 的一颗 24 位 ΔΣ ADC,集成了可编程增益放大器(PGA)、两个可用于 RTD 激励的恒流源(IDAC)、内部温度传感器以及数字滤波器。这几个特性叠加在一起,让它特别适合做传感器前端。但真正让我决定选它的,是那个 UART 接口。

我做过的温度采集板里,SPI 接口的 ADC(比如 ADS1248、ADS1120)占了大多数。SPI 本身没啥问题,但在系统集成上很讨厌:SCLK、DIN、DOUT、CS 至少四根线,而且片选信号在长线上容易受干扰,主控和 ADC 之间的地电位稍微不一致,通信就容易出乱码。UART 就省心得多,一根 TX、一根 RX,长线传输可以直接怼 RS-485 收发器,短距离直接两根线拉到主控,布线直觉更接近传统传感器总线。ADS122U04IPWR 的 UART 特性让它能像传感器节点一样挂在系统的串口总线上,MCU 发一条命令它回一帧数据,整个通信模型非常干净。

另外它的功耗也值得一提,正常工作电流在毫安级别,睡眠模式更低,用在电池供电的传感器节点或对功耗敏感的 HVAC 控制器上都很合适。内部 PGA 从 1 到 32 倍可调,热电偶那种微伏信号可以直接放大到 ADC 的满量程附近,不用再外接仪表放大器,物料清单能省掉不少。

1.3 PIC18F45K40 的角色:系统控制与通信中枢

ADS122U04 负责把模拟信号变成数字码值,但它不是主控,它等命令、发数据,不处理工程单位,也不跑通信协议。这些活儿全部交给 PIC18F45K40。

PIC18F45K40 是 Microchip 的 8 位 MCU,32KB Flash、2048B RAM,内部 32MHz 振荡器,带两个 EUSART、多个定时器、12 位 ADC 等等。放在这个方案里,它的任务很聚焦:上电后初始化 ADS122U04 的寄存器,周期性通过 UART 读取转换结果,再把原始码值换算成温度和工程值,最后通过 Modbus/RS-485 或者模拟输出送给上位机。

选这颗 MCU 还有一个重要原因,它的 EUSART 模块做串口通信非常省心,而且支持 5V 供电。工业现场 24V 供电很普遍,从 24V 降到 5V 给整个板子供电,比单独做 3.3V 电源轨要稳。ADS122U04 本身也支持 2.3V 到 5.5V 的模拟供电,和 PIC 共用一组 5V 电源非常方便,省去电平转换芯片。

整体系统框图就是:传感器(RTD/热电偶)→ ADS122U04 → UART → PIC18F45K40 → 通信总线/显示/上位机。这个架构最大的好处是 ADC 和 MCU 之间只走数字协议,无惧模拟信号跨板传输。

2. 硬件搭建:从传感器到 MCU 的关键连接

2.1 UART 电平匹配与连接细节

ADS122U04 和 PIC18F45K40 的电压域如果一致(比如都用 5V 或都用 3.3V),UART 就直接交叉连接:ADC 的 TXD 接 MCU 的 RX,ADC 的 RXD 接 MCU 的 TX,两边共地即可。

如果 ADC 用 3.3V、MCU 用 5V,就需要电平转换。这儿有个容易踩的坑:UART 的静态电平。ADS122U04 的 TX 空闲时是高电平,如果它供电 3.3V,这个高电平对 5V 的 PIC 来说虽然能识别,但接近门限边缘,长线或者电源噪声一大就容易误码。最稳妥的做法还是统一供电电压,我一个项目里为了省电平转换芯片,让两边的电压域不一致,调试时波特率一高就偶发乱码,最后改成统一 3.3V 电压域才消停。

上电时序也要注意。ADS122U04 上电之后需要一段时间完成内部复位,PIC 这一侧的 UART 需要等 ADC 稳定之后再去初始化,否则第一条命令大概率被吞掉。我的习惯是 PIC 上电后延时至少 100ms,再开始和 ADC 通信。

2.2 RTD 的激励电流配置与引线电阻抵消

ADS122U04 内部有两个匹配的 IDAC 恒流源,专门用来给 RTD 供电。测量 PT100/PT1000 的时候,用内部 IDAC 比外部恒流源稳定得多,至少两个 IDAC 之间的匹配度是出厂校准过的,不会出现两路电流不一致导致的测量偏差。

三线制 RTD 抵消引线电阻的原理说起来不复杂:两根引线上的电压降如果完全相等,在差分测量里就能抵消掉。实际接法上,ADS122U04 的典型三线制方案是用两个 IDAC 分别从两根线注入电流,公共返回线接到 AVSS 附近的低阻抗点,PGA 测量的是 RTD 两端的差分电压。只要两根引线的材质、长度、温度一致,线阻带来的误差就被压到很低。这个接线方法在数据手册里有专门的图,我强烈建议第一次做的同学照着参考设计改,不要自己发明接法。

激励电流大小的选择要算一笔账。以 PT100 为例,0℃ 时电阻 100Ω,100℃ 时约 138.5Ω,灵敏度大概 0.385Ω/℃。如果激励电流取 500μA,温度每变化 1℃ 产生的电压变化就是 500μA × 0.385Ω ≈ 192.5μV,配合 PGA=8 的增益,输入 ADC 的电压约 1.54mV/LSB 级别,完全落在 24 位 ADC 的高分辨区间里。电流取太大,RTD 会自热,尤其 PT1000 这种阻值高的传感器,250μA 电流就能产生 62.5μW 的功率,在自热系数高的封装上足以让读数偏高 0.1℃ 以上。

2.3 热电偶输入与冷端补偿的电路处理

热电偶和 RTD 的测量思路不一样。RTD 是测电阻,热电偶是测电压,而且是一个微伏级的直流电压。

ADS122U04 处理热电偶时,我会把 PGA 开到 16 或 32 倍,然后利用它内置的温度传感器做冷端补偿。这里有个很关键的工程细节:ADC 内部温度传感器测的是芯片结温,而冷端补偿需要的温度是热电偶接线端子处的温度,两者严格来说不是同一个点。所以做冷端补偿时,要让热电偶的冷端靠近 ADC 芯片,并且铺一块等温铜皮,让冷端温度尽量和芯片温度保持一致。

如果冷端温度测不准,热电偶的测量误差是非常夸张的。举个例子,K 型热电偶测量 200℃ 目标温度时,冷端如果偏差 5℃,最终读数就会差 5℃,这不是 ADC 精度能补回来的。我在自己的板子上是把热电偶的接线端子放在 ADC 芯片 5mm 以内,然后整块区域做成等温块,实测冷端补偿精度能到 ±0.5℃ 以内。

2.4 电源与 PCB 走线的抗噪设计

ADS122U04 是 24 位 ADC,分辨率高到什么程度?它一个 LSB 对应的电压可能是几十纳伏级别。这种精度下,电源上的一点点纹波、地线上的一个尖峰,最终都会变成温度读数上的跳动。所以硬件设计上必须把抗噪放到和原理图同等重要的位置。

我的经验是这样几条:第一,模拟电源和数字电源尽量分开走,ADS122U04 的 AVDD 引脚前面放一个 10μF 钽电容加一个 100nF 陶瓷电容,两个电容并联是最常规的配置;第二,传感器输入线的参考地要单点连接,避免地环路;第三,板上如果有继电器、开关电源这类噪声源,要和 ADC 输入区拉开距离,并且用铺地隔离;第四,HVAC 项目里变频器是最大的干扰源,温度传感器走线如果和变频器动力线平行,建议用屏蔽线并在 PIC 侧单端接地。

我曾经在一块板子上把 PT100 的输入线绕着继电器走了一圈,结果温度读数跳动了 0.3℃,当时查了很久才发现是继电器线圈吸合瞬间的磁场耦合到传感器线上。后来把走线挪开,问题立刻消失。

3. 软件驱动与测量流程

3.1 ADS122U04 的寄存器初始化流程

ADS122U04 的 UART 是主机请求、从机响应的模式。所有配置都写在寄存器里,主机通过 UART 发送读/写寄存器命令去配置它。芯片的寄存器不多,核心是输入多路复用选择、PGA 增益、IDAC 电流大小、数据率、滤波模式、转换模式这几个域。

我常用的初始化顺序是这样:

// 伪代码,具体寄存器地址以数据手册为准 uint8_t regs[5]; // 配置输入多路复用:差分输入 AIN0/AIN1,PGA=8 regs[0] = 0x20; // 以数据手册寄存器域定义为准 // 配置 IDAC1 输出到 AIN0,IDAC 电流 500uA regs[1] = 0x25; // 示例值,根据实际需求配置 // 配置数据率:20SPS,FIR 滤波,50/60Hz 抑制 regs[2] = 0x20; // 示例值 // 配置转换模式:连续转换 regs[3] = 0x00; ADS_WriteReg(0x00, regs, 5); // 读取寄存器回读校验 ADS_ReadReg(0x00, regs, 5);

写寄存器之后要回读,这是调试 ADC 时的基本习惯。很多时候芯片没被正确唤醒、命令被吞掉、波特率不匹配,回读和写入值不一致,问题就能提前暴露出来。

转换方式上,我建议默认用连续转换模式。ADS122U04 的 UART 是半双工请求响应,连续转换模式下主机随时可以发 RDATA 命令获取最新一次转换结果,代码逻辑最简单,适合周期性采样的控制器。

3.2 PIC 端 UART 驱动要点

PIC18F45K40 的 EUSART 模块初始化和发送接收并不复杂,但有几个细节直接影响稳定性。

波特率误差是第一关。如果 PIC 用内部 RC 振荡器跑 1MHz、4MHz、32MHz 这些频率,而 UART 波特率又要求 115200,SPBRG 算出来的误差可能超过 2%,通信就会不稳定。我通常选用 32MHz 内部振荡器,然后波特率配 9600 或者 115200。ADS122U04 的命令帧和响应帧都很短,9600 波特率完全够用,而且长线上更稳。

发送命令和接收响应要有超时机制。不要用阻塞式接收等死,万一 ADC 没响应,MCU 会卡死在 UART 接收上,看门狗都能被拖垮。我写驱动时会用一个简单的状态机,发送 RDATA 之后启动一个定时器,超时 100ms 就重发或者报错,这样系统里任何异常都不会导致整个采集链路僵死。

// XC8 环境下的简要代码 void UART_Init(uint32_t baud) { // 配置 TX1/RX1 引脚、使能 EUSART1 // 设置 SPBRG 产生目标波特率 } uint8_t UART_ReadTimeout(uint16_t timeout_ms) { while (!PIR1bits.RC1IF) { if (--timeout_ms == 0) return 0xFF; // 超时 __delay_ms(1); } return RCREG; }

3.3 RTD 原始码值到温度值的换算

拿到了三字节原始码值,首先要拼成有符号整数,然后除以满量程得到比例,再乘以基准电压和 PGA 的倒数,就能得到实际的差分电压。

以 PT100 为例,整个换算链路是:码值 → 电压 → 电阻 → 温度。ADS122U04 的基准电压由外部参考电阻和 IDAC 电流共同决定,如果 VREF = I_IDAC × R_REF,那么用电桥或比例测量方式可以直接用码值比例反推 RTD 电阻,省掉中间电压换算的浮点运算。简单点说,就是靠同一个 IDAC 电流流过参考电阻和 RTD,得到一个比率式的测量结果,这种“比率测量”方式对参考电流的绝对精度不敏感,即使电流漂移了,比值的误差也被抵消了,这是用 ADC 测 RTD 时最优雅的思路。

得到电阻值后,PT100 的温度曲线在 0~100℃ 范围接近线性,大约每摄氏度 0.385Ω。但想做到 ±0.2℃ 精度,纯线性逼近不够,我通常会在 MCU 里放一张分度表,用分段线性插值。

// 伪代码:查表 + 线性插值 double Pt100_Temperature(double resistance) { // 查表定位 R <= resistance <= R_next // 然后按比例插值得到温度 double frac = (resistance - R[i]) / (R[i+1] - R[i]); return T[i] + frac * (T[i+1] - T[i]); }

PIC18F45K40 做浮点运算速度一般,所以工业项目里我会预先在 PC 上生成一张 0.1℃ 间隔的电阻值表,下载到 MCU 的 Flash 里,运行时用二分查找加插值,速度很快,误差很小。

3.4 热电偶的冷端补偿计算代码

热电偶测量时,主机需要读两次数:一次热电偶的输出电压,一次内部温度传感器测出的冷端温度。补偿逻辑是先把冷端温度查表转换成对应的热电势,然后和实测热电势相加,再反查表得到真实温度。这个计算量在 8 位 MCU 上有压力,但可以用分段查表。

读取内部温度传感器很简单,配置 ADC 为内部温度测量模式,启动转换,读回码值,然后按数据手册给出的线性公式换算成摄氏温度。这个值就是冷端温度的参考。我实际使用的补偿代码结构:

// 伪代码:K 型热电偶冷端补偿流程 double compensated_temp(double tc_uv, double cold_c) { double cold_uv = K_type_lookup(cold_c); // 查冷端热电势 double total_uv = tc_uv + cold_uv; // 补偿 return K_type_reverse_lookup(total_uv); // 反查真实温度 }

这个过程中,查表精度和表格步进决定了最终精度。K 型热电偶在 -40~400℃ 范围,我用 1℃ 步进的表格,线性插值后误差可以控制在 ±0.3℃ 以内。如果想更准,可以换成 NIST 多项式,但 8 位 MCU 上做多项式除法会比较吃力,查表法是性价比最高的方案。

4. 标定要点与误差控制

4.1 误差来源清单与数量级

ADS122U04 本身是 24 位 ADC,理论分辨率极高,但系统的最终误差由一堆小项叠加而成。我习惯把误差来源列一张表,每项逐一控制。

误差来源典型量级消除/抑制手段
ADC 增益误差±0.1% 级别系统标定时修正
ADC 偏移误差±几 LSB差分测量、自动校零
IDAC 电流温漂几十 ppm/℃采用比率式测量
RTD 引线电阻0.1~几 Ω三线/四线制接法
RTD 自热0.01~0.2℃降低激励电流
冷端补偿误差±0.2~±0.5℃等温块设计、校准
参考电阻精度1%~0.1%选低温漂金属膜电阻

参考电阻的选择经常被忽略。我见过有人随手拿一个 1% 精度 0805 贴片电阻做 1.5kΩ 基准,结果整个系统误差直接拉满。比率测量可以抵消 IDAC 电流的绝对值漂移,但抵消不了参考电阻本身的误差。我会选 ±0.1% 精度、±25ppm/℃ 温漂的金属膜电阻,成本多几毛钱,但整个精度等级完全不同。

4.2 两点标定与软件修正

即使器件选得再好,生产批次差异还是存在。解决的办法是做两点标定。一般是把传感器放进标准恒温槽,取两个温度点(比如 0℃ 和 100℃),记录 ADC 原始码值或计算出的电阻值,然后算出比例误差和偏移误差。

假设标定前 MCU 计算出的温度是 T_raw,而标准温度计读数是 T_std,两个标定点分别是 (T_raw1, T_std1) 和 (T_raw2, T_std2),那么线性修正公式就是:

T_corrected = T_raw + K * (T_raw - T_raw1) + B K = (T_std2 - T_std1) / (T_raw2 - T_raw1) - 1 B = T_std1 - T_raw1

在生产线上,这个标定信息可以存到 PIC 的 Data EEPROM 里,每块板子在出厂前单独烧录一组系数。这个做法能有效弥补传感器个体差异、PCB 焊接应力、参考电阻精度带来的系统误差,实测可以把 0~100℃ 范围的误差从 ±0.5℃ 收敛到 ±0.15℃ 以内。

不过要提醒一句,两点标定只能修正线性的增益和偏移误差,不能修正非线性。如果你的温区跨度特别大,比如 -40℃ 到 150℃,建议做三点标定,用二次曲线拟合。

4.3 工业与 HVAC 的工况差异处理

同一个温度测量方案,放在 HVAC 和工业现场,关注点其实不太一样。

HVAC 场景里,温度变化缓慢,几十秒钟变 1℃ 是常态,所以对响应速度要求不高,反而对长期稳定性、低功耗、批量一致性更敏感。这种情况下,可以把 ADC 数据率放到 20SPS 甚至更低,数字滤波器开到最强,测量结果非常平滑。而且 HVAC 控制器的安装环境相对友好,温度范围窄,标定一次基本能管很多年。

工业场景则不同,环境温度可能从 -20℃ 到 70℃ 波动,现场有大功率变频器、继电器、电机启停,电磁干扰极其凶悍。这种环境下,除了 PCB 抗噪设计要加固,软件上也要做处理:比如多次采样取中值滤波、异常值剔除、看门狗喂狗逻辑,以及 ADC 通信失败后的重连策略。PLC 上位机的通信协议也要加上校验,Modbus CRC 是底线。

我在工业项目里还会把 PIC 的配置位里的看门狗使能打开,同时给 ADC 通信加一个心跳计数。连续 3 次通信失败就重新初始化 ADC,避免现场出现“死机只能断电重启”的状况。

5. 现场调试中踩过的坑与排查建议

5.1 UART 无响应或乱码

最常遇到的启动问题就是第一条命令发出去之后,ADC 不理不睬。排查思路按顺序来:先量 ADC 的电源电压,确认在 2.3V~5.5V 范围;再用示波器看 MCU TX 引脚有没有波形,排除引脚配置错误;最后检查波特率误差,特别是 PIC 内部振荡器精度不足时,115200 波特率在长线上极易出问题。

还有一个很容易被忽略的点:ADS122U04 的 UART 空闲状态。如果 MCU 上电瞬间,TXD 引脚被拉低超过几个毫秒,ADC 可能会误判为起始位,导致后续所有命令都“错位”。解决方法是 MCU 初始化时先把 TX 引脚设为高电平,再去配置 UART 外设。这个细节耗费了我整整一个下午,写驱动时可以提前预防。

5.2 温度读数跳变

读数跳变的原因往往是输入信号越过了 PGA 允许的范围。ADS122U04 的 PGA 有共模输入范围和满量程限制,热电偶信号如果在高增益下接近满量程,噪声会被放大得非常夸张。排查时先把增益降低一档试试,比如从 PGA=32 降到 PGA=8,看跳变幅度是否明显下降。

另一种常见原因是长线传输时传感器引线攫取到了共模干扰。特别是三线制 RTD,如果屏蔽层两端都接地,地环路会让 50Hz 工频干扰直接耦合进测量链路。屏蔽层应该只在信号源侧单端接地,这条规则在几乎所有工业仪表设计中都成立。

5.3 自热效应导致读数偏高

自热效应在 PT1000 上最容易暴露。PT1000 室温电阻 1000Ω,如果激励电流设到 1mA,功耗就是 1mW,在小型封装上足以让传感器自身温度上升 0.1~0.3℃,而整个过程完全由电流产生,外部校准根本校准不掉,因为改变环境温度时,自热温升会随着传感器散热条件变化而变化。

判断是不是自热问题的方法很简单:把激励电流减小一半,如果读数下降且稳定在新的数值,说明原来的电流偏大了。解决方式就是把 IDAC 电流从 1mA 降到 250μA 或 500μA,代价是信号幅度减半,但对 24 位 ADC 来说完全够用。

5.4 现场工频干扰导致的偶发错误

HVAC 现场最大的环境干扰源就是 50Hz 工频。ADS122U04 的数字滤波器如果配置为 20SPS 或更低,理论上对 50Hz 及其倍数有很好的抑制度。问题往往出在配置上,如果你为了追求响应速度选了 1000SPS 的滤波器配置,50Hz 干扰就会明显渗透进来。

我在项目里有个原则:对温度这种缓变量,采样率能低就不要高。20SPS 的更新率对 HVAC 和大多数工业过程控制完全足够,而滤波效果天差地别。如果确实需要更快的响应,可以保持高采样率,然后在 MCU 端做一个滑动平均,效果也接近。

5.5 问题排查速查表

现象优先排查常见根因
完全无数据上电时序/电源ADC 未复位完成或电压不合规
乱码波特率/电平匹配振荡器误差、电压域不一致
读数跳动大PGA 范围/滤波配置输入超量程、工频干扰
读数整体偏高IDAC 电流/自热激励电流大、热耦合
读数缓慢漂移参考电阻温漂基准电阻选了普通贴片
通信偶发失败看门狗/超时机制缺少重连和初始化逻辑

6. 我的一些体会

ADS122U04IPWR 和 PIC18F45K40 这套组合,我自己在工业温控器和 HVAC 水系统控制器上都跑过。说实话,ADS 这颗 ADC 最打动我的并不是“24 位”这个数字,而是 UART 接口带来的系统设计自由度。它把 ADC 变成了一个可以挂在串口总线上的传感器前端,PIC 这边只需要一个普通 UART 外设就能驱动,代码量比 SPI 驱动还少,调试时用一根串口线就能直接看寄存器,效率高很多。

最后分享一个小技巧,如果你第一次调通这套方案,别急着接真实传感器,先用一个精密电阻箱模拟 RTD 的阻值,验证 ADC 码值和换算公式是否准确。这能帮你把软件问题、硬件问题和传感器本身的问题彻底分开,调试时少走一半弯路。