ADS122U04与PIC18F4680组合:高精度多路温度采集方案解析

发布时间:2026/11/5 6:29:00
ADS122U04与PIC18F4680组合:高精度多路温度采集方案解析

这次项目里拿到一个实际需求:给工业现场和HVAC空调机组做温度采集,要求多路、精度高、抗干扰,主控那边又不愿意换太新的平台。最终方案落到了ADS122U04IPWR和PIC18F4680这个组合上。前者是TI的24位Δ-Σ ADC,带UART接口;后者是Microchip的8位经典MCU。这套组合做出来的东西,放在工业管道表面测温和HVAC风管/水系统测温场景里,稳定性和精度都够用。

这篇内容我会从选型思路、硬件设计、固件实现,再到调试踩坑一条线展开。适合正在做高精度温度采集、多通道模拟量输入、或者想把“老单片机”和“新ADC”搭配起来用的朋友参考。

1. 方案选型:为什么是“串口ADC + 8位MCU”的组合

1.1 独立ADC解决了PIC18F4680自带ADC的根本短板

PIC18F4680本身带了一个10位ADC,通道数也不少,日常采集个0-5V的电位器、NTC粗略分压,完全没问题。但拿到工业温度和HVAC控制这个场景里,10位分辨率就不够看了。

粗略算一下:如果测温范围是0℃到100℃,用10位ADC去量化,每LSB对应的温度大约是0.1℃。看起来还行?但这是理想情况。实际PIC内部ADC的失调、增益误差、参考电压波动,再加上布线噪声,整体误差很容易超过0.5℃甚至1℃。而HVAC系统里面,温差控制精度直接关系到能耗,工业现场更不用说,温度误差大了,工艺参数就偏了。

这时候把模拟前端从MCU里面“拆”出来,交给ADS122U04这种独立24位ADC,是更务实的做法。ADS122U04的ENOB(有效位数)在低数据速率下能做到接近20位,比MCU内部10位ADC高了好几个数量级。

打个比方:MCU自带ADC像是一个厨房秤,称个面粉能凑合;独立ADC像是分析天平,你要精确到毫克级,就得换工具。温度信号本身是慢变化、低带宽的模拟量,用高分辨率ADC去“慢慢读”,效率虽然不高,但精度和稳定性是MCU自带ADC没法比的。

1.2 选UART接口的ADS122U04,而不是SPI/I2C版本

ADS122U04这个型号带的是UART接口,这点要和常见的SPI接口ADS1220系列区分开。ADS122U04的“U”就是UART的意思。

为什么在工业/HVAC场景里,UART接口反而比SPI更好用?三个原因:

一是线少。SPI至少要SCLK、MISO、MOSI三根线,I2C要SCL、SDA两根,UART只要TX和RX两根,再加上ADC的DRDY(数据准备好)引脚,一共三根线就能完成通讯。在控制柜里走线或者做长距离传输时,线越少越省事。

二是远距离传输友好。UART是异步串行,本身就适合跨越一定距离的连接,很多现场仪表和控制器之间也习惯用UART/RS232/RS485这一套协议体系。相比之下,SPI在长线、高噪声环境下更容易出时序问题。

三是PIC18F4680本身自带增强型USART模块,不需要软件模拟协议,CPU开销很小。配置好波特率之后,读写ADC就像操作一个串口外设一样简单,这对老工程师来说非常顺手,对新手来说也容易理解。

1.3 PIC18F4680在这个项目里的角色定位

说实话,PIC18F4680不是一颗多先进的芯片,但它在这个项目里依然是核心:负责初始化ADC、通过UART读取转换结果、做温度换算、驱动显示或对外通讯(比如RS485透传)、执行控制逻辑。

这颗MCU有40引脚封装,带有增强型USART、I2C/SPI、多个定时器,还集成了CAN控制器。用在HVAC控制器里,一个UART口接ADC,一个UART口或RS485接上位机,还能留出CAN接口做楼宇自控,资源刚刚好。

更重要的是,它的生态成熟。MPLAB X IDE、XC8编译器、PICkit调试器,资料多、例程多,买芯片也容易。很多老工程师手里就囤着这类8位MCU,方案能不能落地,很大程度取决于团队对工具链的熟悉程度。

2. 硬件设计核心细节:从供电、基准到输入前端

2.1 模拟电源与数字电源处理

ADS122U04的工作电压范围是2.3V到5.5V,我这次直接给AVDD和DVDD都接了3.3V。需要注意:它虽然允许AVDD和DVDD分开供电,但实际项目中为了省一个LDO,我测试过把两个引脚直接并在一起供电,模拟性能和分开供电时差异不大。前提是3.3V电源质量要过关,纹波尽可能低。

电源去耦一定要到位。ADS122U04的每个电源引脚旁边都放了一个0.1μF陶瓷电容,另外在靠近AVDD引脚的位置加了一个10μF钽电容做低频去耦。之前遇到过ADC读数跳动的问题,排查到最后就是电源去耦电容离引脚太远,高频噪声通过电源走线耦合进了模拟部分。

还有个容易被忽略的点:PIC18F4680的数字电源和ADS122U04的模拟电源,最好从同一路电源的根部做星形分配,不要串成一条长链。数字电路工作时的瞬态电流会让公共走线上产生压降,这个压降会直接反映在ADC供电上,造成测量误差。

2.2 参考电压与RTD比例式测量

ADS122U04内部有2.048V参考电压,精度在±0.2%左右。对于一般HVAC应用来说,内部基准够用了。但做工业级温度测量时,我更推荐用比例式测量法,也就是让激励电流同时流过传感器和精密参考电阻,ADC的参考电压也取自这颗参考电阻。

这个思路的原理很简单:激励电流I是波动的,但是传感器上的电压Vrtd = I × Rrtd,参考电阻上的电压Vref = I × Rref,两个电压相除之后,电流I被约掉了。只要Rref足够精密(比如0.1%温漂的金属膜电阻),测量结果就和激励电流的稳定性无关了。

这一点非常关键。如果不用比例式,而是用内部2.048V基准+独立恒流源,那么激励电流每变化0.1%,测温就会对应产生约0.26℃的误差(PT100在0℃附近灵敏度约0.385Ω/℃)。比例式直接把这个误差源去掉了。

ADS122U04自带两个IDAC恒流源,正好用来做这个事。我配置的是1mA激励电流,流过PT100再加一个250Ω的参考电阻,参考电压就是0.25V,对应的ADC满量程很小,所以PGA增益设置在8倍左右。

2.3 输入前端:RTD与热电偶两套接法

如果测的是PT100铂电阻,用三线制或四线制接法会比两线制准确得多。两线制的导线电阻直接叠加在传感器阻值上,PT100零度时是100Ω,导线电阻如果有0.4Ω,就相当于产生约1℃的误差。三线制可以用IDAC1和IDAC2分别驱动线缆的两条引线,同时利用差分测量把公共线上的压降抵消掉。四线制更彻底,测量回路和激励回路完全分开,导线电阻基本可以忽略。

如果测的是热电偶,情况不一样。K型热电偶输出的是毫伏级电压,典型灵敏度约41μV/℃,0℃到100℃也只有约4mV。这就必须把PGA增益拉高,我通常设到16倍或32倍,再配合数字滤波器使用。热电偶本身没有激励电流,IDAC这时候就可以关掉。另外,热电偶测量必须做冷端补偿:热电偶输出的是热端和冷端的相对温差电压,冷端如果放在PCB上,就需要用NTC或者板上温度传感器测出冷端的实际温度,在软件里把这部分电压加上去。

这里有一个比较隐蔽的问题:PGA增益大了以后,ADS122U04的输入共模范围会变窄。热电偶信号的地和ADC地如果不一致,很容易超出共模范围,导致输出信号削波或者非线性。所以热电偶的接入点要尽量靠近ADC输入引脚,并在信号线上并联一个小电容做共模滤波。

2.4 PIC18F4680的连接与波特率计算

PIC18F4680和ADS122U04之间只接三根线:TX(MCU发送)接ADC的RX,RX(MCU接收)接ADC的TX,另外ADC的DRDY引脚接MCU的一个外部中断引脚(我这里用的RB0/INT0)。DRDY是ADC的转换完成标志,下降沿表示新数据就绪,用中断方式读数据比轮询省心很多。

PIC18F4680我用的是8MHz外部晶振,再通过内部PLL倍频到32MHz作为系统时钟。UART波特率设置为9600,计算SPBRG寄存器:

波特率 = Fosc / (16 × (SPBRG + 1))

9600 = 32,000,000 / (16 × (SPBRG + 1))

SPBRG + 1 = 208.33,取SPBRG = 207,实际波特率误差约0.16%,完全可以接受。

注意:如果用的是内部RC振荡器,UART波特率误差会明显变大,长期来看不可靠。尤其是9600波特率时虽然容错空间还行,但一旦环境温度变化大,内部振荡器漂移几十个百分点不足为奇。做工业测温,外部晶振是底线。

3. 固件驱动与温度算法实现

3.1 ADS122U04初始化流程

ADS122U04的寄存器配置通过UART命令完成。初始化顺序一般是:先发送复位命令让ADC回到默认状态,再写入配置寄存器,最后发送启动转换命令。

我这边配置的要点:

  • 寄存器0(MUX):选通AIN0和AIN1作为差分输入,对应RTD测量通道;
  • 寄存器1(PGA):增益设为8,适用于PT100满量程约250mV的场景;
  • 寄存器2(DR):数据速率设为20SPS,滤波器选sinc3模式;
  • 寄存器3(RMUX):转换模式设为连续转换,DRDY引脚在每次转换完成后输出低脉冲;
  • 寄存器4(IDAC):开启IDAC1,电流设为1mA,接到AIN0引脚上作为RTD激励。

需要注意,不同批次和型号在寄存器位的定义上可能有细微差别,具体配置值建议对着数据手册逐位核对。上面说的是我项目中的配置思路,不代表所有场景通用。

初始化完成后,发送START命令启动第一次转换。之后ADC会按照设定的数据速率持续转换,DRDY引脚每个周期拉低一次,MCU在中断里通过RDATA(读数据命令)取走结果。

3.2 数据读取与符号处理

ADS122U04的输出是24位有符号数,格式是二进制补码。读取时连续收3个字节,拼成一个32位有符号整数,然后右移8位(因为24位数据左对齐在寄存器里)或者直接按24位处理。

这里有个容易踩的坑:如果读取速度跟不上ADC的转换速度,DRDY引脚会保持低电平,MCU可能重复读取同一个数据,或者读到新旧数据交替。我一开始把数据速率设到1000SPS,MCU端串口中断处理不过来,数据就乱了。后来把速率降到20SPS,同时用DRDY中断加标志位判断,每读完一帧数据才允许下一次读取,问题就解决了。

3.3 RTD温度换算

RTD比例式测量的核心关系式是:

比值 = 原始ADC读数 / 满量程ADC读数 = Rrtd / Rref

已知参考电阻Rref(我用的250Ω,0.1%精度),就能算出Rrtd。接下来把阻值转成温度。

PT100在0℃以上的阻值特性可以用Callendar-Van Dusen方程简化表达:

Rt = R0 × (1 + A × t + B × t²)

其中R0 = 100Ω,A = 3.9083×10⁻³,B = -5.775×10⁻⁷

代入Rt后,解一元二次方程得到温度t:

t = [-A + √(A² - 4B×(1 - Rt/R0))] / (2B)

这个公式在0℃到850℃范围内误差很小,做HVAC和工业测温足够了。如果想偷懒,也可以直接用PT100分度表做线性插值,查表法占用Flash,但逻辑更直观。

3.4 热电偶测量与冷端补偿

热电偶通道的处理比RTD多一步。读取ADC原始电压后,先把它转换成毫伏值,再从热电偶分度表里查出对应的温度——但这里的温度是“相对冷端的温度”,必须加上冷端温度才是真实的被测温度。

冷端温度我用的板上NTC测量。NTC阻值和温度关系是近似的指数曲线,我用的10kΩ NTC在25℃时标称10k,B值3435。软件里用Steinhart-Hart方程换算更准确:

1/T = A + B×ln(R) + C×(ln(R))³

换算出的冷端温度单位是开尔文,需要转成摄氏度,再和热电偶分度表查出的温度相加。这里有个细节:冷端补偿不是简单把两个温度值相加就完了。严格做法是先在毫伏域做补偿:把冷端温度对应的热电偶毫伏值算出来,加到ADC读到的毫伏值上,再用总和反查温度。如果直接用温度相加,在非线性区会产生额外的误差,热电偶测量范围越宽,这个误差越明显。

3.5 数字滤波与响应速度的取舍

ADS122U04本身的sinc3数字滤波器已经滤掉了不少工频和带外噪声,但数据读回来以后,我还会再做一次滑窗平均。比如20SPS下取8次平均,等效输出速率降到2.5SPS,噪声进一步被压制。

这里要考虑响应时间的取舍。HVAC管道温度变化本来就慢,2.5SPS的反应速度完全够。但工业管道如果要求快速报警,滑窗长度就不能设太长,否则温度突变会像是被“钝化”了。我建议根据实际控制环路的延迟要求来设:一般温度环路过冲容忍度高的场合,32次平均也没问题;需要快速响应的,取4次平均就可以。

4. 调试实录:实际踩过的坑与排查方法

4.1 现象:ADC输出噪声跳动,跳动幅度超过±10个LSB

第一次上电测试时,通道读数在恒定温度下依然有明显跳动。排查步骤:

  • 先用示波器看ADS122U04的电源纹波,发现AVDD上有幅度大约20mV的毛刺,频率和LED指示灯切换频率一致;
  • 把LED驱动回路和ADC供电物理隔离,在电源入口加LC滤波,毛刺降到5mV以内;
  • 同时检查了DRDY引脚附近有没有高频开关信号,把DRDY走线稍微拉远了一些。

这个问题的根源就是数字噪声耦合进模拟电源。模拟前端和数字电路之间的电源隔离,必须从布局阶段开始考虑,而不是等出了问题再补。PCB上模拟部分和数字部分的地用单点连接,电源走线尽量粗,是既简单又有效的做法。

4.2 现象:UART通信偶发失败,ADC寄存器写不进去

调试中发现,ADC偶尔配置无响应,读回来的数据是0xFF。通过逻辑分析仪抓时序,发现MCU发送的波特率偶尔会偏差几十个百分点。查下来是PIC18F4680的时钟配置有问题:我一开始图省事用了内部RC振荡器,温度一变,波特率就漂了。

换外部8MHz晶振后,通讯异常基本消失。这个教训也验证了前面说的:工业/长期运行环境下,UART通信必须依托稳定的外部时钟源。

另外还发现一个细节:当ADC的TX和MCU的RX没有共地时,通讯偶发失败且无规律。后来在ADC附近加了一个0Ω电阻把模拟地和数字地单点相连,才彻底解决。UART的“地”是信号参考,参考不干净,数据就不可靠。

4.3 现象:RTD通道读数溢出(输出全为1)

排查思路三步走:

  • 第一步看输入是否超出量程。用万用表量AIN0和AIN1之间的电压,发现是接近0V的——正常PT100在1mA激励下应该有100多毫伏;
  • 第二步查IDAC是否正常工作。用万用表量AIN0引脚对地电压,发现没有电压,说明IDAC没有输出电流;
  • 第三步查寄存器配置,发现IDAC的使能位因为初始化时序问题被后续配置覆盖掉了。

修复方法:按照数据手册要求,在每次寄存器写入之后,再单独确认一次IDAC寄存器内容;如果写IDAC寄存器,要确保命令地址和数据字节之间的间隔满足时序要求。ADS122U04的寄存器写入不是“写一次就永久有效”的,复位之后必须重新完整配置一遍,这个初始化序列务必要做成一个独立模块。

4.4 现象:热电偶测量整体偏差约+2℃

这个偏差很典型。检查后发现冷端补偿用的NTC安装位置靠近一个发热的LDO稳压器,NTC感知的温度比实际冷端高了约2℃。把NTC移到PCB角落、远离发热器件之后,偏差降到0.3℃以内。

冷端补偿的物理位置比补偿算法更重要。算法再准,如果传感器感受的温度不是真实的冷端温度,算出来的结果也会带系统偏差。这也是为什么很多高精度热电偶采集卡会把冷端传感器贴在接线端子旁边,就是为了让传感器和热电偶冷端处于同温。

4.5 常见问题速查表

问题现象优先排查方向常见根因
读数跳动大电源纹波、DRDY边沿干扰模拟电源去耦不足、布局不当
偶发全0xFF时钟源精度、地连接内部振荡器漂移、未共地
RTD溢出IDAC电流、输入范围IDAC寄存器被覆盖、接线断开
热电偶整体偏差NTC位置、PGA设置冷端传感器被局部热源加热
数据乱码波特率误差、中断处理晶振不准、读取速度过快

5. 校准与系统验证

5.1 两点校准法

ADC和传感器的综合误差,最终还是要通过校准来消除。我的做法是最常用的两点校准:

  • 第一点:把PT100探头放进冰水混合物中(0℃),记录ADC原始读数和计算温度;
  • 第二点:用精密恒温槽或者沸水(100℃附近)作为第二点,记录第二个数据。

利用这两组数据,软件里做一次线性修正:误差 = k × 测量值 + b,把k和b存到EEPROM或者Flash中,每次测量后自动修正。

这里有一个细节:校准要针对“整条链路”进行,而不是只校准ADC或只校准传感器。因为电阻偏差、参考电阻温漂、PGA增益误差、MCU换算误差是混在一起存在的,分头校准既麻烦又难以彻底,整链路校准一次就能把系统误差打包消掉。

5.2 长时间稳定性验证

温度采集设备最怕的是“开机准,越跑越漂”。我做了72小时连续运行测试,每隔1小时记录一次温度读数。实测下来,在恒温环境下整机漂移小于0.1℃,主要残余漂移来自于参考电阻的温度系数。

如果对长期稳定性有更高要求,建议把参考电阻从普通贴片电阻换成低温漂的精密电阻,或者直接使用外部精密基准芯片给ADC提供参考电压。这样又多一层成本,但对工业应用来说值得。

6. 写在最后的一点经验

ADS122U04和PIC18F4680这个组合,看起来不算“新潮”,但胜在分工明确、稳定可靠。ADC负责把最难的模拟信号处理掉,MCU只做自己擅长的事务逻辑,这种架构在工程现场反而是最不容易出问题的。

我自己的体会是,这类项目里最花时间的往往不是原理图,而是布局、地线处理和固件细节。模拟电路的精度不是“选出来的”,是“布出来的”和“调出来的”。同一个芯片,布局讲究一些,噪声能少一个数量级;配置时序稍微马虎一点,数据就莫名奇妙地出错。

如果你也在做类似的温度采集方案,建议先把传感器类型、精度目标、响应速度三项定清楚,再回头看芯片选型。ADS122U04的UART接口特性、24位分辨率加上PIC18F4680的稳定外设,正好卡在“精度够用、成本可控、开发周期短”这三者的交汇点上。希望这篇内容能帮你少走一些弯路,把这套方案快速落地。