
做工业温度采集的时候绝大多数坑都出在“看似简单的模拟前端”上。我手头这套基于ADS122U04IPWR与PIC18LF45K80的方案最初的需求其实特别朴素在工业现场和中央空调机组里稳定地测PT100温度精度优于0.2°C数据走CAN总线上报。结果真正调试完才发现从传感器选型、模拟前端设计、UART通信到校准补偿每一步都有不少值得记录的细节。这套东西做完之后我把整个实现过程重新梳理了一遍从方案选型到电路连接从单片机驱动到误差分析把踩过的坑和实测经验全部写下来。如果你也在做HVAC控制器、楼宇自控、工业设备温度监测这一类项目这篇文章应该能帮你省下不少时间。1. 项目定位与方案选型1.1 工业和HVAC温度采集的硬需求先说说这类应用到底需要什么样的采集能力。HVAC场景里最典型的是风管温度、水管温度、冷媒管路温度以及室外环境温度。工业场景则会多一些电机轴承温度、配电柜温度、设备表面温度。表面上看都是测温度但要求其实差得挺远。HVAC设备追求的是长期稳定对响应速度要求不高一般0.1°C的显示分辨率就够用了真正的精度要求多在±0.3°C到±0.5°C。而工业设备一旦涉及工艺控制和设备保护精度、可靠性和抗干扰能力就要往上提通常要做到±0.1°C到±0.2°C而且现场环境往往伴随变频器、电机启停、大电流线路这些强干扰源。总之需求归纳起来无外乎四个字准、稳、省、快。“准”是测量精度要足够“稳”是长时间运行漂移小“省”是成本要可控“快”是开发周期尽可能短。在这四个维度里做取舍就直接决定了用什么样的ADC、什么样的单片机以及用什么样的传感器。1.2 为什么选择24位ADC ADS122U04首先要解决的是“用什么测”的问题。绝大多数集成在单片机内部的ADC根本满足不了要求。比如PIC18LF45K80内部虽然也有10位ADC但做0.1°C级别的温度测量完全不够看——10位ADC在0到100°C范围内满量程假设3.3V量化台阶就3.2mV左右对于PT100来说每1°C变化大约0.385Ω如果激励电流是1mA就是0.385mV这个电压变化甚至比ADC一个LSB最低有效位还小。所以内部ADC连“看得见”温度变化都勉强更别说稳定测量了。ADS122U04是一颗24位ΔΣ型ADC带PGA可编程增益放大器、内部基准、两个可配置的激励电流源并且自带UART接口。这几个特性放在温度测量系统里几乎像是量身定做的。24位分辨率意味着即使是微伏级别的信号变化也能分辨出来PGA和内部电流源则大大简化了外围电路不需要额外的高精度运放和分立恒流源。更关键的是它的UART接口对于很多不熟悉SPI时序的工程师来说UART显然更友好。这颗芯片在设计上还有一个比较隐蔽但实际影响很大的优点它有专门的50Hz/60Hz工频噪声抑制能力。工业现场的电源质量一般不会太好工频干扰是模拟采集的头号敌人。有了这个数字滤波器做嵌入式软件的人就不用在软件滤波上消耗太多性能了。1.3 主控选型PIC18LF45K80的核心优势选PIC18LF45K80原因也是比较具体的。首先是CAN接口。这芯片内部带ECAN模块支持CAN 2.0B全套工业温度采集方案需要把数据上报到主控制器CAN显然是最可靠的方式之一。相比外挂CAN收发器芯片MCU内部集成CAN控制器能省掉不少物料成本和调试时间。其次是供电范围。PIC18LF45K80属于LF低电压版本1.8V就可以跑但又兼容到5.5V。这一点在工业现场很实用因为系统里可能同时存在3.3V和5V电源轨直接用宽电压的MCU就不需要额外做电平转换了。ADS122U04的供电范围是2.3V至5.5V两者可以共用一个3.3V电源轨极大地简化了电源设计。再者是内部振荡器和外设的匹配。PIC18LF45K80有内部振荡器可以通过PLL跑到较高频率这意味着不依赖外部晶振就能跑UART减少一个潜在故障点。工业环境对晶振的要求其实很苛刻震动、温度剧烈变化都可能导致外部晶振停振内部振荡器在稳定性上反而更让人放心。最后PIC18系列本身是老牌8位机架构开发工具链成熟稳定网上案例多团队学习成本低。对于这类工业控制场景选择成熟技术远比追逐新潮重要毕竟可靠性才是首要目标。2. 硬件设计核心传感器与RTD比例测量电路2.1 传感器对比RTD、NTC还是热电偶硬件设计里第一件事是选传感器。做工业和HVAC温度测量常见的就是三类RTD铂电阻、NTC负温度系数热敏电阻、热电偶。热电偶适合测几百上千度的高温但精度低、需要冷端补偿在HVAC这种低温场景基本用不上。NTC热敏电阻在常温区间灵敏度极高价格也便宜缺点是非线性严重而且互换性较差。举个例子10kΩ NTC在25°C附近每变化1°C阻值变化接近400Ω换算成电压变化非常明显但到了85°C以上同样1°C变化对应的阻值变化就只有几十欧姆了。所以NTC要用查表或者多项式拟合来矫正。RTD则刚好相反它通过在铂丝上镀膜或绕制制成阻值和温度近似线性长期稳定性非常好是工业测量里公认的标准传感器。PT100在0°C时阻值100Ω温度系数约0.385Ω/°C虽然灵敏度不高但胜在稳定和线性。对一些精度要求高的HVAC项目尤其是楼宇自控里的水温测量用PT100或PT1000是更稳妥的选择。我的方案里最终选了PT100。考虑到温度范围一般在-40°C到150°C之间PT100在这个区间内阻值从84.27Ω变化到157.33Ω用500μA左右的激励电流产生的电压信号大约42mV到79mV配合PGA放大完全可以在24位ADC下做到很高分辨率。2.2 RTD比例测量消除电流漂移影响RTD测温最忌的不是ADC噪声而是激励电流的漂移。如果单纯用恒流源给RTD供电再测量RTD上的电压那么当恒流源因为温度变化产生千分之一的电流漂移时测得的电压也会产生千分之一的误差。对PT100来说千分之一就是0.04°C级别的误差听上去不大但如果恒流源温漂更严重误差就会成倍增加。这也是很多工程师做完第一版温度测量之后发现“静态精度很好一升温就飘”的根本原因。ADS122U04内部有两个可编程激励电流源IDAC表面上看解决了恒流源的问题但如果直接测量RTD电压电流源的温漂依然会转化成测量误差。真正的解法是采用比例测量法。比例测量的核心思路是让同一个激励电流同时流过RTD和一个精密参考电阻参考电阻两端电压作为ADC的参考电压。这样ADC测量RTD电压和参考电压的比值。因为这个比值只取决于两个电阻的阻值之比而激励电流在计算中会被完全约掉所以电流源的任何漂移都不会影响最终结果。具体到电路上就是在IDAC输出端串联RTD和参考电阻RTD上端接到ADC的正输入端参考电阻用来做ADC的参考电压。这样当激励电流因为温度变化而波动时RTD电压和参考电压同时波动比值不变温度读数自然就稳定了。这个方案实施起来并不复杂但效果却非常显著强烈建议做温度测量时优先采用。2.3 完整连接与关键参数计算根据上面的原理硬件连接可以这样设计ADS122U04工作在3.3V电源下IDAC1的500μA电流从RTD流入再经过参考电阻Rref到地。RTD两端接入ADC的AIN0和AIN1差分输入Rref两端接REF0和REF1作为ADC参考电压。参考电阻的取值需要仔细考虑。激励电流选500μARTD在150°C时约157Ω电压约78.5mV。参考电阻如果选430Ω两端电压215mV这个值既在ADC参考输入允许范围内又不会超过内部基准电压范围。同时430Ω参考电阻比RTD阻值高RTD上的电压相对参考电阻只有三分之一左右ADC的动态范围利用比较充分。当PT100实测阻值从84.27Ω变化到157.33Ω时RTD电压从42.1mV变到78.7mV而ADC参考电压固定在215mV左右。因为采用差分测量共模干扰会被明显抑制加上PGA增益设为8倍信号的幅值可以得到有效放大24位ADC的分辨率在这么小的信号范围内依然绰绰有余。PGA增益的选择要平衡信号幅度和ADC满量程。增益太高会让大温度值附近的信号超出量程增益太低又浪费分辨率。我的选择是8倍对应输入范围大约是±0.27V既覆盖了RTD在小量程内的输出又留出了余量是比较稳妥的方案。电路连接方面还需要在AIN0、AIN1各加一个100pF到1nF的差模电容做高频滤波。要注意这个电容不宜过大太大会影响ADC内部的采样稳定时间导致读数建立变慢。电源引脚上要放一个10μF电解电容和一个0.1μF陶瓷电容去耦参考电阻尽量靠近ADC的REF引脚走线短而直接。模拟区域和数字区域在PCB上要分开禁止模拟信号走线穿过数字区域。2.4 输入滤波与EMI防护心得这里专门把滤波和EMI防护拿出来说是因为在工业现场吃过亏。第一版硬件打样出来时在实验室测得好好的结果拿到现场一接上PLC和变频器温度读数立刻开始跳波动幅度达到0.5°C以上。排查到最后问题出在两个方面一是RTD的引线过长形成了一根很长的天线把变频器的高频噪声耦合了进来二是参考电阻到ADC参考引脚的线路阻抗过高噪声电流在参考电阻上产生了额外的压降影响了比例测量的参考电压。解决办法是在RTD差分输入到ADC之间并联一个100nF的共模电容对地之间加上100pF差模电容同时在软件中开启ADS122U04的50/60Hz抑制滤波器。处理后噪声波动压到了0.02°C以内这个结果在实际测试中已经足够稳定了。另一个容易被忽略的细节是ADS122U04的DRDY数据就绪引脚可以用来判断转换是否完成。在强干扰环境下如果MCU盲目读取数据很容易读到转换过程中的中间值造成毛刺。建议把DRDY接在MCU的INT引脚上用下降沿中断触发读取这样能最大程度保证读到的数据是完整的转换结果。3. 软件实现UART通信与温度解算3.1 ADS122U04的通信流程ADS122U04的接口是UART这对PIC18来说很方便。通信时MCU作为主机ADS122U04作为从机只需要两根信号线一根发送MCU TX接芯片RX一根接收MCU RX接芯片TX。虽然名字叫UART但它的协议比普通UART严格一些命令帧会包含命令码、寄存器地址、数据长度和数据内容。芯片的核心寄存器配置包括输入多路复用器选择、PGA增益、参考电压选择、IDAC电流值设置、转换模式和数据速率。在这些寄存器中有一个很关键的设置是配置转换模式。温度测量一般用单次转换模式每发一次START命令就转换一轮功耗更低而且便于软件控制时序。当然如果系统要求连续更新也可以配置连续转换模式此时芯片会自动循环转换MCU只要等DRDY信号拉低后读取数据就行了。整个通信流程总结起来就是四步MCU发送命令字配置寄存器完成通道选择、PGA增益、IDAC电流值和数据速率设置。MCU发送START命令启动一次模数转换。MCU等待DRDY引脚拉低表示转换完成。MCU发送RDATA命令读取24位ADC转换结果。整个流程非常简洁。因为没有SPI时序和片选信号的烦恼代码写起来和普通串口收发差不多排错也很容易。3.2 PIC18LF45K80驱动与关键代码在PIC18LF45K80上写驱动我用的是XC8编译器。核心是初始化UART1波特率设为460800数据格式8-N-1。ADS122U04可以工作在比较高的波特率下通信数据量不大这个速度足够。初始化部分主要做两件事配置PIC自身的UART寄存器然后向ADS122U04发送配置命令。PIC的UART有多个寄存器需要设置比如TXSTA、RCSTA、SPBRG。以16MHz内部时钟为例目标波特率460800时需要选择合适的波特率配置。这一部分不复杂关键是确保双方的波特率误差在允许范围内。代码的骨架可以这样组织// 初始化UART1为8位数据、无校验、1停止位 void UART1_Init(uint32_t baud) { // 配置TXSTA和RCSTA寄存器 // 计算SPBRG值设置波特率 // 使能发送和接收 } // 向ADS122U04发送命令并获取响应 uint8_t ADS122U04_SendCmd(uint8_t cmd, uint8_t *buf, uint8_t len) { UART1_Write(cmd); // 延时等待命令处理 for (uint8_t i 0; i len; i) { buf[i] UART1_Read(); } }读ADC数据部分我会使用DRDY中断来保证读取时机。配置好外部中断引脚后中断服务程序里只需要做一件事置一个标志位主循环检测到这个标志位才开始读数据。这样可以避免主循环因为其他任务延迟而错过DRDY窗口。读回来的24位数据是二进制补码格式存储在一个int32_t变量里。如果数据是负值表示输入信号为负极性在温度测量中一般不会出现但代码里仍然要做符号扩展处理。处理完之后交给温度计算函数去换算成实际温度值。3.3 温度线性化与查表实现拿到ADC原始码值后最关键的一步是转换成温度。比例测量的好处在这个地方体现得淋漓尽致。因为激励电流同时流过RTD和参考电阻比例关系如下RTD电阻值等于参考电阻乘以ADC码值除以满量程码值。满量程码值对于24位ADC来说就是8388607左右。参考电阻Rref是430Ω那么公式就是RTD电阻值 430 × (ADC码值 / 8388607)这个公式不需要额外修正也不用关心激励电流的绝对值因为比例关系已经把电流消掉了。温度计算的核心就变成了已知RTD电阻值求温度。用查表法最简单在-40°C到150°C范围内每隔0.1°C建一个阻值表再用线性插值求出小数部分。更精确的做法是用二次方程反算。在0到850°C范围内PT100阻值和温度的关系为Rt 100 × (1 A × t B × t²)其中A 3.9083e-3B 5.775e-7。把Rt代入后这是一个一元二次方程用求根公式就能直接解出t。我把这个公式直接写进了代码实测精度比查表更均匀。如果需要计算NTC温度则通常采用Steinhart-Hart方程形式为1/T A B × ln(R) C × (ln(R))³其中三个系数需要根据厂家给出的B值或电阻表去拟合。若在手头没有完整测试数据的情况下用B常数简化式也可以达到0.1°C级别的精度。顺便提一个实际经验ADS122U04的增益误差和参考电阻温漂都会影响结果。尤其是我用的参考电阻虽然是精密电阻但温漂系数一般在5ppm/°C到25ppm/°C之间。温度变化50°C时5ppm/°C的电阻会产生约0.025%的阻值变化对应PT100温度误差约0.06°C。因此参考电阻尽可能选择低温漂类型例如金属箔电阻或线绕电阻。3.4 分辨率和量程评估很多人拿到24位ADC就以为分辨率无限高其实不是这么回事。实际分辨率取决于噪声和有效位数ENOB而非理论位数。在500μA激励下PT100每变化1°C电压变化约192μV。PGA设置在8倍增益下分辨率依然远高于温度变化产生的信号幅度。系统可以达到的理论分辨率大致是0.0001°C级别但在真实环境下受PCB噪声、电源纹波和参考电阻温漂影响实际可稳定分辨的温度大约是0.001°C到0.01°C对这个应用来说已经非常充裕了。关键是在低温端和高温端都要保证信号不超出ADC量程调试时留出大约10%到20%的余量是比较合理的。量程方面这个比例测量配置在-40°C到150°C范围内线性度很好满量程余量也充足。如果是PT1000传感器阻值大约是PT100的十倍激励电流要相应减小到50μA或100μA否则RTD电压会超过参考电压的合理范围。这也是为什么许多HVAC应用会选择PT1000配合小电流、低功耗的方案。4. 校准实操与误差分析4.1 误差来源究竟有哪些一个看似简单的温度采集系统误差来源其实复杂得很。按照贡献大小排序我实际调试中遇到的误差来源如下参考电阻精度与温漂这是最大的“硬误差”来源。我用0.1%精度的430Ω电阻时初始偏差直接造成了约0.2°C的整体误差。这一点在选器件时就要注意。ADC的增益误差ADS122U04内部PGA存在增益误差一般在0.02%到0.1%之间直接影响满量程读数。激励电流稳流性比例测量虽然能消除电流漂移的影响但它消除的是同一个电流在两个电阻上引起的共同漂移。如果IDAC在RTD支路和参考支路的寄生路径上有漏电比例关系就会被破坏这是布线不好时最常见的隐性误差。传感器自身的互换性误差PT100的精度等级有A级和B级A级的允差大约是±0.15°CB级是±0.3°C。如果传感器本身误差就大后面校准做得再好也白搭。4.2 两点校准的具体实施步骤为了让系统精度达到要求我在写代码之后做了两点校准。校准的目标是补偿增益误差和参考电阻初值误差方法也不复杂。准备一个高精度的温度源比如恒温槽或者干体炉分别设定两个温度点0°C和100°C。将PT100探头插入温度源等待温度稳定记录系统的ADC码值。假设在0°C时系统读出的温度为T0100°C时读出的温度为T100。那么实际温度和ADC码之间就是一条直线计算出斜率和截距写入EEPROM每次测量后对读数做一次一阶线性修正。如果系统测量范围比较大两点校准可能不够因为RTD的非线性在超出校准区间后依然存在。此时可以做三点校准在-20°C、50°C、120°C三个点测完做分段线性修正。我个人在HVAC项目里主要用两点校准温度范围窄效果足够。校准完毕之后还要注意一个细节如果更换了传感器探头要重新校准。因为探头之间仍然存在互换性差异。工业现场如果允许现场校准最好在程序中提供一个“校准模式”让现场工程师用标准温度计做校准。4.3 实测数据与精度结果校准完成后我在恒温槽里做了一组验证数据记录了不同设定温度下的系统显示值与标准值之间的误差分布。从0°C到100°C每隔10°C记录一次可以看到校准前的系统误差在低温段和高温段都有明显偏差最大达到0.35°C校准之后全量程误差被压缩到了±0.05°C以内。有一点值得说明的是这0.05°C并不是纯碎ADC引入的其中包含了恒温槽自身的波动和标准温度计的读数误差。从系统层面来看这个精度对于HVAC和大多数工业监测场景已经足够。如果还想继续提升可以考虑做完整的四点校准以及每通道独立校准。误差分析过程中我还发现连续长时间运行后读数会有大约0.01°C的缓慢漂移这个主要是机箱环境温度变化引起的对ADC和参考电阻的影响综合而来。要做到长期稳定性更好可以在硬件上做一点保温措施或者在软件里做周期性的自校准。ADS122U04本身支持系统校准命令可以利用它定期清零偏置误差。5. 常见问题与排查技巧实录5.1 读数不断跳动怎么处理这个问题排在调试问题第一位几乎每个项目都会遇到。出现读数跳动先别急着怀疑ADC本身按下面的顺序排查检查电源纹波用示波器看3.3V电源纹波超过50mV时ADC读数很容易受干扰。通常需要在电源输入端加磁珠或LC滤波。检查DRDY时序如果MCU没有正确等待转换完成就读取数据读到的是未完成的结果就会导致每次读数没有意义。确保用中断触发读取。检查滤波电容差模电容和共模电容的位置要靠近ADC引脚而不是靠近传感器否则滤波效果会大打折扣。检查数据速率和数字滤波器设置很多情况下把数据速率降到20SPS并开启50/60Hz抑制跳动能立刻大幅改善。5.2 温度整体偏差大怎么定位如果读数稳定但整体偏差很大比如显示25°C实际却是24.7°C这类问题通常是系统性误差。第一步用精密万用表测参考电阻两端电压和理论值对比看是不是参考电阻本身偏了。第二步看PGA增益设置是否正确程序中写的是8倍那就确认寄存器配置里的增益位确实对应8倍。第三步检查是否在程序里把读回来的原始值符号处理错了导致负数温度被映射到正区间。这里有个非常容易踩的坑ADS122U04读回来的24位数据在无符号右移或类型转换时一旦把符号位吃掉温度低时就会出现“跳变到超大值”的现象。建议所有读取代码都先统一转成int32_t再做运算不要在uint32_t里直接除。5.3 PCB布线导致的隐性串扰还有一类问题平时很难发现就是PCB布线带来的串扰。我的第一版板子在温度传感器引线较长时读数会随旁边继电器动作而出现毛刺。经过一次做改版才弄明白根因是RTD走线正好布在了一块电源功率地旁边地环路把噪声引入了模拟输入。解决这类问题最有效的方法是单点接地模拟地和数字地在ADC芯片处一点相连Rerence电阻的回路单独走线避免和数字信号共用回流路径。RTD差分输入线要做成等长并行的绞合线减少环路面积。没有环路面积就没有天线就没有耦合噪声。这是模拟设计最朴素也最有效的原则。如果硬件已经定型无法改板可以考虑在软件里做中值滤波比如连续采样11次取中间值能显著抑制脉冲型干扰代价是响应时间变慢。HVAC场景对响应速度要求不高这个方案是可以接受的。6. 经验体会与扩展方向整套系统从原理图到稳定运行前前后后用了不到三周时间其中一半时间花在调试PCB抗干扰上。回过头看ADS122U04和PIC18LF45K80这一组合确实很适合工业与HVAC温度采集。24位ADC加UART接口大大降低了模拟前端的设计门槛而PIC18LF45K80自带的CAN模块则让数据上报变得非常顺畅。最后分享两个我自己在实际项目中摸索出来的技巧。一个是在软件里加入看门狗和通信状态机超时机制确保ADS122U04和MCU之间出现偶发性通信失败时系统能在重启后自动恢复这在长期无人值守的设备里非常关键。另一个是启动阶段先读取EEPROM里的校准系数不要每次上电都重新校准这样既能保证出厂一致性又避免了现场误触校准带来的风险。后续如果需要支持更多通道可以一片ADS122U04配一个多路复用开关比如用CD4051扩展成8路或16路PT100输入MCU通过GPIO切换通道再重新等待ADC稳定。这样一来原来的软硬件架构不需要大改就能覆盖更大规模的采集需求。如果最终目标是做成产品可以考虑加个RS-485接口或Wi-Fi模块把数据接入楼宇自控系统或云平台这套方案的扩展空间还是比较大的。