
把 ADS122U04IPWR 和 PIC18F4680 放在同一个项目里乍一看有点“老搭档”的意思一个是 TI 的 24 位四通道 ADC一个是 Microchip 的经典 8 位单片机都算不上新器件。但我在 HVAC 风柜控制系统和设备温度监测项目里实际用下来这套组合测 PT100 和 K 型热电偶精度和稳定性都相当能打调试过程也不折腾。ADS122U04 负责把毫伏级小信号变成可靠的数字量PIC18F4680 负责读取、换算、报警和对外通信两颗芯片各干各的活配合得很省心。这篇就把我实际搭建这套温度测量方案的过程、参数配置和踩过的坑都写出来给做工业现场采集或暖通控制的朋友做个参考。1. 方案背景为什么用一颗UART型ADC配一颗老MCU1.1 这个搭配解决什么问题温度采集看着简单真正在工业和 HVAC 现场做起来难的是最前面那一截模拟信号。传感器输出的是毫伏甚至微伏级信号现场又有变频器、继电器、压缩机启动干扰如果直接用单片机内置 ADC分辨率不够噪声也压不住。ADS122U04 就是干这个脏活累活的——24 位 Δ-Σ ADC带可编程增益放大器和两个匹配电流源能把 RTD、热电偶这种小信号放大并数字化。PIC18F4680 不需要碰模拟前端只管通过 UART 把转换结果读回来、做线性化、做报警和通信逻辑。这里有个很实际的点ADS122U04 用 UART 而不是 SPI/I2C 输出数据。这个选择在现场调试时特别舒服。单片机只要会串口就能把它当“温度变送器”用甚至很多带串口的 PLC、触摸屏、组态软件都可以通过协议直接读它的数据不需要额外写驱动。对于老工程师来说UART 比 SPI 友好太多示波器探针一夹就能看到完整的数据流出了问题也容易判断是通信还是采样环节。1.2 温度测量场景与传感器选型HVAC 行业用得最多的是 PT100 和 PT1000风管温度、冷冻水供水回水温度、风机盘管出风温度量程一般在 -40~150°CPT100 完全覆盖。工业上的应用更杂罐体管道温度、电机轴承温度、变压器绕组温度多数也选 PT100 贴装而燃烧烟气、排烟温度这种 300°C 以上的场合就得换 K 型热电偶。ADS122U04 内部带了冷端补偿用的片内温度传感器和可编程电流源所以 K 型热电偶也能直接接只是信号极性要接对。选择传感器时要算清楚PT100 的灵敏度约 0.385Ω/°C在 500μA 激励电流下对应约 0.19mV/°C 的信号变化。如果追求高分辨率必须靠 ADC 的 PGA 增益或者用 PT1000 把信号幅度放大十倍。HVAC 里温控精度要求没那么高PT100 加增益 1 就够了工业过程控制如果要求 0.1°C 级别的分辨率建议 PT1000 或者把增益提高到 8。1.3 与常见温度采集方案对比不少朋友会问为什么不用 DS18B20或者干脆上一颗集成温度变送器模块我列过一张对比表选型逻辑很清楚方案分辨率与精度通信方式冷端补偿现场适配适合场景DS18B2012位±0.5°C1-Wire无简单但线缆受限房间温度、低成本MAX3186515位/16位分辨率SPI无需要额外驱动RTD 专用板卡ADS122U04 PIC18F468024位 ADCUART内置灵活可接RS485工业与 HVAC一体化温变模块精度高4-20mA看模块接线简单点对点远传选择 ADS122U04 加 PIC18F4680 的真实原因一个是供货稳定这两颗芯片都属于长生命周期器件批量产品不用担心轻易停产另一个是灵活性模块化变送器把什么都封装好了但你在现场想改滤波参数、想加断线判断、想自定义报警阈值都没法动。自己用 ADC 加 MCU 做所有环节都可控。1.4 对“8位机够不够用”的看法有人质疑 PIC18F4680 这颗 8 位机性能太弱。温度采集不是图像处理ADS122U04 的数据率最高也就几十 SPSPIC18F4680 跑 40MHz 根本没有任何压力。反而 8 位机的优势很实在开发环境 MPLAB X XC8 成熟稳定寄存器直接操作没有复杂的操作系统和驱动层代码执行时间可以精确到周期。用在工业设备上少一层中间件就少一层故障风险。2. 硬件设计从传感器到ADC再到MCU的完整链路2.1 传感器接口与比例式测量设计RTD 和热电偶的接法差别很大工程上最讲究的是 RTD 的接线制式。2 线制最简单但两米长的线缆本身就有一两欧的电阻PT100 在 0°C 时是 100Ω线阻导致的误差可能接近 1°C所以工业现场我至少用 3 线制。3 线制的典型做法是把 RTD 一端接 AIN1另一端接 AIN2公共端接 AIN3两个恒流源分别激励 RTD 和补偿回路这样引线电阻带来的压降能在差分测量中抵消大半。ADS122U04 的基准电压也来自同一个激励电流源这构成了比例式测量。原理不复杂基准电压 Vref 是电流源 I 流过精密电阻 R_BIAS 产生的RTD 上的电压是同一个电流源 I 流过 R_RTD 产生的。ADC 输出码值正比于两段电压的比值所以电源电压波动、电流源温度漂移都会在除法中消掉。这句话值得反复体会很多人做高精度测量时拼命用高精度基准 IC其实在这里反而引入了额外温度系数。我给一个实际项目里的参数激励电流 500μA基准电阻 3300Ω基准电压 1.65V增益 1。PT100 在 0°C 时阻值 100Ω两端电压只有 50mVADC 输出码大约在满量程的 3% 位置比例换算后能得到约 0.01°C 的温度分辨力。如果觉得这个位置信号利用不充分可以把增益调到 8或者换 PT1000 传感器。2.2 激励电流选多大一个不能拍脑袋的参数IDAC 电流不是随便设的。电流越大RTD 上的信号电压越大测量分辨率越高但自热效应也越明显。PT100 的测温电流标准上限一般是 1mA经验值 500μA 在绝大多数工业场景里是平衡点。我实际算过500μA 流过 100Ω 的 PT100发热功率只有 25μW对温度测量的影响可以忽略换成 1mA 就是 100μW在导热不好的安装座里可能带来零点几度的误差。低阻值 RTD 还可以用脉冲激励来减小自热但 ADS122U04 的 IDAC 是持续输出的。在管道安装、导热良好的场合500μA 没问题如果是贴装在塑料外壳里建议降到 250μA或者使用 PT1000 降低工作电流。2.3 稳压、滤波与隔离设计ADS122U04 的供电范围宽1.8V 到 5.5V 都能工作但模拟部分对电源噪声很敏感。我在板子上单独用一颗低噪声 LDO 给 ADC 供电数字电源用磁珠加电容隔离。如果你直接用 24V 开关电源降压给整个系统供电ADC 电源引脚前至少要放一个 10Ω 电阻加 10μF 电容组成的 π 型滤波否则转换结果里会看到明显的电源纹波分量。输入端的 RC 滤波同样不能省。ADS122U04 是高输入阻抗的 Δ-Σ ADC用 1kΩ 电阻加 1nF 电容组成低通截止频率大约 160kHz主要作用是抑制射频干扰和混叠噪声。在电机、变频器附近的现场这个 RC 滤波救了很多次数据。需要特别提醒的是RC 电阻太大会和传感器阻抗分压所以 1kΩ 已经是上限再大就可能引入误差。UART 信号隔离也是工业现场的刚需。HVAC 柜里变频器启停瞬间地电位会被打得很乱如果 ADC 和 MCU 共地共模噪声直接进模拟前端。我在实际项目里用高速光耦或者数字隔离器把 UART 信号隔开模拟地和数字地只在电源输入端单点连接。有些人省掉这步也能跑但遇到继电器动作时读数跳动大概率就是地环路的问题。2.4 PCB布局与抗干扰经验板子布局我遵循三个原则模拟前端成一个独立区域数字控制器放另一边电源走向尽量垂直。ADC 芯片底下尽量不要走数字线REF 引脚的去耦电容必须紧贴引脚因为基准电压任何一点毛刺都会直接反映到转换结果上。RTD 输入走线要短如果必须走长线至少用包地的形式两侧铺地铜并打满过孔。现场线缆处理比 PCB 更关键。RTD 信号线用屏蔽双绞线屏蔽层在控制器端单点接地千万别两端都接。我见过一个项目两端都接地后形成了地环路屏蔽层反而成了天线读数在 0.2°C 范围内乱跳。改成单端接地后数据立刻安静下来。3. 固件实现让PIC把ADC“用顺手”3.1 UART总线上的ADC通信流程ADS122U04 上电后处于待机状态必须由 MCU 发命令才能开始转换。整体流程是这样的上电延时等待芯片稳定发送复位命令写入配置寄存器发送启动命令然后循环等待 DRDY 标志通过发送读数据命令把 24 位转换结果读回来。听起来简单但严谨的做法是把通信逻辑做成一个小状态机防止任何一条命令出错后整个采集流程卡死。PIC18F4680 的 EUSART 用中断接收比较省心。我习惯把接收缓冲设成环形队列主循环里从队列取字节再按协议解析。这里不建议用阻塞式接收因为温度采集系统往往还有报警、按键、通信等其他任务一个阻塞函数就可能影响全局。伪代码大概是这样static void adc_task(void) { switch (state) { case IDLE: uart_send(CMD_START); state WAIT_DRDY; break; case WAIT_DRDY: if (drdy_flag) { uart_send(CMD_RDATA); state READ_DATA; } break; case READ_DATA: if (rx_cnt 3) { raw_code (rx_buf[0] 16) | (rx_buf[1] 8) | rx_buf[2]; process_temperature(raw_code); state IDLE; } break; } }注意 ADS122U04 返回数据的最高位经常是 DRDY 状态位读取后要先判断这次数据是否有效再参与计算。我在最早一版代码里忽略了这一点偶尔会把转换尚未完成时的旧数据当成新数据用导致温度值偶尔跳变。加上状态判断后问题消失。3.2 初始化序列与寄存器配置寄存器配置是整个固件里最不能抄错的环节。我项目里使用的关键配置是AIN1/AIN2 差分输入模式、增益 1、数据速率 20SPS、外部基准、IDAC1 作为激励源、电流 500μA、同时开启 50/60Hz 抑制。写寄存器时建议一次写完四个寄存器然后读回来校验一遍。TI 的芯片支持回读千万别省这一步。我自己遇到过一次写寄存器时因为 UART 线干扰导致某一位没写成功芯片还是按默认速率工作但读回来的数据完全不对排查了很久才发现是配置没生效。具体命令码以数据手册为准不同版本固件可能有差异。但流程是一致的复位后写配置寄存器、回读校验、启动转换。回读校验这步看似多花几十毫秒对生产环境来说却是避免整批设备异常的有效手段。3.3 从ADC码到电阻值再到温度换算先把 ADC 原始码换算成 RTD 阻值再通过传感器线性化公式换成温度。比例关系可以写成R_rtd R_bias × code / 2^23用这个式子的时候要注意满量程码和基准电压、增益必须在同一条件下定义如果增益不是 1还要额外除以增益。我习惯把这段换算封装成一个独立函数方便在不同配置下复用。RTD 阻值和温度的关系不是完全线性的IEC 60751 标准里给出了多项式。我在代码里用牛顿迭代求解从线性近似值开始迭代四五次就能收敛到 0.01°C 以内。核心代码长这样#define R0 100.0f // PT100 at 0C #define A 3.9083e-3f #define B -5.775e-7f float rtd_to_temp(float R) { float t (R / R0 - 1.0f) / 0.00385f; // 线性初值 for (int i 0; i 6; i) { float r_calc R0 * (1.0f A * t B * t * t); float drdt R0 * (A 2.0f * B * t); t - (r_calc - R) / drdt; } return t; }如果量程会到 0°C 以下多项式里还要加上 C 系数的三次项这个按标准文件补上就行。对于不想算多项式的朋友用查表加线性插值也完全可以1024 个点的表在 PIC18F4680 的 Flash 里放得下省去浮点库也可以。3.4 错误处理、看门狗与断线检测温度采集系统最怕的不是测不准而是传感器坏了还给出一个“正常的温度值”。我用断线检测逻辑很直接正常工作时 RTD 的电压范围是已知的如果 ADC 输入开路输入会被拉到接近基准电压的位置读数接近满量程如果短路读数接近零。代码里设置阈值判断后直接上报断线或短路故障不参与温度控制逻辑。PIC18F4680 的看门狗必须开。工业现场程序跑飞不是小概率事件我在 HVAC 控制板上遇到过电源瞬态导致死循环的事没有看门狗恢复就得人工断电重启。看门狗周期设成 1 秒主循环里正常完成任务后清狗卡死时自动复位系统恢复运行的同时也能通过 UART 发一条重启记录。UART 通信失败的自动恢复也很重要。我写了一个简单机制连续发送命令没有响应先复位 ADC重新初始化如果连续三次初始化失败就置故障标志并点亮 LED。这套逻辑让现场维护人员不需要懂寄存器只看指示灯就能判断是传感器问题、通信问题还是 ADC 芯片问题。4. 实测数据与问题排查实录4.1 两组现场实测数据我在 HVAC 风柜控制系统里测的是送风温度PT100 安装在风管中距离控制器约 3 米屏蔽双绞线进线。用一台经过校准的 0.1°C 精度温度表在现场做比对连续记录两小时系统读数波动范围在 ±0.15°C 以内和标准表最大偏差 0.08°C。对风管温度控制来说这个精度已经超出要求。另一个工业场景是测空压机冷却水回水温度量程 0~100°C同样用 PT100 三线制走线距离超过 15 米。这里遇到了比较明显的干扰最初读数在设定值附近有 0.3°C 的周期波动后来把线缆屏蔽层从两端接地改成控制器端单端接地又加了 1kΩ/10nF 的一阶 RC 滤波波动压到 0.1°C 以内。数据记录如下测试点标准表读数系统读数偏差风管送风温度24.98°C24.94°C-0.04°C风管回风温度21.02°C21.06°C0.04°C冷却水回水58.00°C57.92°C-0.08°C冷却水供水62.50°C62.40°C-0.10°C这个偏差量级对于大部分 HVAC 和工业过程监控都足够但如果要做贸易结算或者严谨的工艺控制还得在系统里做两点校准把 ADC 和传感器链路的一起补偿掉。4.2 我在调试中踩过的四个坑第一个坑是 PIC 内部振荡器导致的 UART 乱码。PIC18F4680 能用内部振荡器跑省一颗晶振但内部 RC 振荡器随温度变化会有几个百分点的偏差。第一次做样机时省了晶振常温下通信正常设备放到室外机柜里温度一高就开始偶发乱码。后来老老实实加了 20MHz 外部晶振再没出现过通信丢帧。第二个坑是电源耦合。最初为了省事把 ADC 和继电器驱动共用一个 5V 线性电源继电器动作瞬间读数会跳 0.2°C。原因是继电器线圈电流突变在电源上产生了毛刺直接干扰了 ADC 基准电压。改成 ADC 单独用一颗低噪声 LDO 供电并在电源输出端加磁珠隔离后问题消失。第三个坑是断线检测阈值设得太紧。工程上想了很久正常工作时因为干扰偶尔会出现一两帧接近阈值的“假断线”数据导致系统误报。后来把断线判断改成连续两帧都超阈值才算断线误报完全消除。这个思路后来我也用在超温报警上先连续判断再采取措施比单帧触发可靠得多。第四个坑是长线通信电平问题。ADS122U04 和 PIC 都是 3.3V 或 5V 的电平板内连接没问题但如果现场需要走 5 米以上的线CMOS 电平极容易受干扰。我在一个项目里直接用裸 UART 走线到操作面板一直不稳定最后加了 RS485 收发器把信号转成差分传输问题才彻底解决。4.3 快速排查速查表现象可能原因处理方案读数乱跳电源纹波大 / 输入滤波不够加 LDO、π型滤波、RC 滤波读数偏高且稳定IDAC 自热 / 引线电阻未补偿降低激励电流、改用3线制UART 偶发乱码波特率偏差改用外部晶振、校准 SPBRG长线通信失败CMOS 电平衰减换成 RS485 / 降低波特率断线误报阈值太紧连续两帧判断 / 放宽阈值上电无数据ADC 未退出复位 / 配置未生效检查复位引脚、回读校验寄存器5. 如果继续往后做系统集成的几点经验5.1 扩展4-20mA模拟量输出很多工业仪表要求 4-20mA 模拟量输出PIC18F4680 没有内置 DAC但可以用 PWM 加两阶 RC 滤波生成 0~2.5V 线性电压再用运放或者专用芯片转换成电流环。我常用的做法是 PWM 频率设高一点滤波后纹波控制在几个毫伏然后通过 0~100°C 对应 4~20mA 的比例关系做软件标定。这个方法成本低、灵活批量生产时每个通道在产线校准一下精度能做到满量程的 0.2% 以上。5.2 多测点组网与RS485如果系统里要挂多路温度测点每个节点做成一个小板PIC 的 UART 接 RS485 收发器连到总线上统一轮询。这样每块板有独立地址主机发读取命令从板收到后去读 ADS122U04再把温度值打包返回。HVAC 楼宇自控系统里这种拓扑很常见。现场布线用屏蔽双绞线波特率 9600 或者 19200距离几百米没问题终端电阻按距离选配。5.3 从样机到量产的小建议最后聊一点量产的体会。第一PCB 上一定要留 ICSP 调试接口和几个关键测试点样机阶段能救命的第二传感器端子用可插拔防呆设计安装工人不容易接错线第三校准参数要单独存 EEPROM量产出厂时每个通道写入偏移和增益补偿不要把所有参数烧死在 Flash 里否则返修换芯片后还要重刷固件第四如果现场湿度高板子做三防漆处理防潮防腐蚀长期可靠性会好很多。我自己做过几套温度采集板最大的体会是这套方案的难点从来不在芯片选型而在模拟前端的地怎么处理、UART 波特率准不准、断线判断够不够稳。ADS122U04 和 PIC18F4680 这对组合胜在稳定和容易调非常适合不想在温度测量上耗费太多精力、又对精度和可靠性有要求的项目。做 HVAC 控制器也好做工业采集设备也好从一颗 PT100 开始搭几天就能跑通后续扩展成多通道、模拟量输出、RS485 组网也都顺理成章。