干这行久了你就会发现,温度测量是工业现场最容易被低估的环节。很多设备看起来是逻辑控制问题,最后排查下来其实是温度采样的底子没打好。之前做一套控制器改造,磁珠、热电阻、热电偶信号混在一起,用MCU内置ADC根本没法看,噪声能盖掉好几度。后来换了ADS122U04IPWR + STM32F303RE这套组合,把K型热电偶和PT1000采样一起做掉,才算是把数据稳定下来。ADS122U04IPWR是TI的24位ΔΣ ADC,自带可编程增益放大器(PGA)、内部基准源和激励电流源,非常适合直接接热电偶和RTD;STM32F303RE有FPU、有多个SPI和UART,处理浮点滤波和通信都得心应手。这篇文章就把从硬件接法到软件驱动、再到现场调试的完整过程捋一遍,给正在搭温度采集系统的工程师一个直接能参考的方案。
1. 整体设计与选型思路
1.1 这个组合到底解决什么问题
工业和HVAC里的温度测量,难的不是电路原理,而是信号幅度小、共模干扰大、通道需求杂。
以K型热电偶为例,它的灵敏度大约是41μV/℃。常温附近测温,0.1℃的分辨率对应的是4.1μV的电压变化。MCU内置12位ADC的LSB,在3.3V参考下大约是806μV,根本不够用。就算把信号放大到运放能处理的范围,运放的输入失调和温漂也会在长时间运行中慢慢吃掉精度,而且每一路信号都要配一颗精密运放,板子上的器件多、成本高,调试点也多。
ADS122U04IPWR 这类24位ΔΣ ADC 就是为了这个场景设计的。它把可编程增益放大器、24位采样内核、内部基准源、激励电流源都集成在一颗芯片里。热电偶毫伏级信号进来,内部PGA直接放大,省掉外围运放;PT1000这类阻性传感器,内部IDAC电流源提供激励,接上电阻就能测,不用单独做恒流源。四路差分输入,能同时接两路热电偶加一路RTD,或者按需求自由分配成多路单端输入,灵活性比常见的单通道ADC高出一截。
STM32F303RE在这套方案里做控制和数据汇聚,主频72MHz,带单精度FPU,算24位原始数据的线性化、冷端补偿和滤波,效率很够。它自带多个SPI接口,其中一个和ADS122U04IPWR对接,剩下的还能挂显示屏、按键或者通信芯片。F303系列内部还带了模拟外设,虽然这块用不到,但如果你后续想在主控端顺便做电流采样或者电压比较,这个型号留了余地。
1.2 器件选型对比
做温度采集方案,市面上的高精度ADC并不少,我拿几颗常用芯片做个对比:
| 芯片 | 位数 | 通道数 | 内部PGA | 内部基准 | 激励电流源 | 接口 | 适合场景 |
|---|---|---|---|---|---|---|---|
| ADS122U04 | 24 | 4(差分/单端) | 1~128 | 有 | 有 | SPI/UART | 热电偶、RTD多通道采集 |
| ADS124S08 | 24 | 8 | 1~128 | 有 | 有 | SPI | 通道数要求更高的系统 |
| ADS1256 | 24 | 8 | 1~64 | 无(需外部基准) | 无 | SPI | 通用高精度采集,需外配基准和激励 |
| MCP3561 | 24 | 2 | 1~64 | 有 | 无 | SPI | 成本敏感的两通道测量 |
选ADS122U04IPWR而不是ADS124S08,主要是因为四通道够用,价格更低,封装更小。和ADS1256相比,最大优势是内部基准和恒流源都集成在片内,省掉外围电路。ADS1256精度确实不错,但做RTD测量时还要自己加外部基准源和恒流源电路,PCB面积和BOM成本都上去了,工业现场器件越多,故障率越高。
F303RE的选择逻辑也很简单:项目需要同时驱动一个OLED、一路RS485通信和温度采集,F303系列有多个UART和SPI,不需要抢资源。芯片带FPU对浮点算温度多项式是实打实的加速,虽然主频不高,但算起来不卡。如果你手头只有F103或者国产GD32F103系列,也能跑这套软件,只是滤波处理和浮点换算会慢一些,实测下来还是推荐带FPU的型号。
2. 硬件设计——接口、电源与传感器接入
2.1 SPI通信接口怎么接
ADS122U04IPWR的SPI接口时序很标准,连接方式不复杂,但有几个细节需要注意。
芯片的SPI信号线是SCLK、DIN(对应主机的MOSI)、DOUT(对应主机的MISO)、CS。DRDY引脚必须接MCU的外部中断输入,不要为了省引脚把它悬空或接固定电平。数据转换完成时,DRDY会拉低,MCU收到下降沿再启动SPI读取,这样保证读到的都是稳定的最新转换结果。如果靠轮询寄存器里的状态位,代码可能会在数据更新瞬间读到高低字节的混合状态,出现偶发的大跳变。
我用SPI1对接,接线表如下:
| ADS122U04IPWR引脚 | STM32F303RE引脚 | 说明 |
|---|---|---|
| SCLK | PA5(SPI1_SCK) | 时钟信号,速率建议2MHz左右 |
| DIN | PA7(SPI1_MOSI) | 主机输出,从机输入 |
| DOUT | PA6(SPI1_MISO) | 从机输出,主机输入 |
| CS/SS | PA4(GPIO输出) | 片选,低有效 |
| DRDY | PB0(EXTI输入) | 转换完成信号,下降沿触发中断 |
CS用普通GPIO控制,不用硬件NSS,这样更灵活,也方便和多个SPI器件共用总线时分时操作。SPI模式必须与ADC的时序要求匹配,标准配置是CPOL=0、CPHA=1(模式1)。如果你用CubeMX初始化,把这两个参数对好,别的按常规来。
2.2 电源和基准电压处理
ADS122U04IPWR的模拟电源AVDD和数字电源DVDD建议分开供电。我在板上用了一个低噪声LDO给AVDD供电,型号是LP5907这类,输出3.3V,纹波噪声在几十μV级别。DVDD可以和MCU共用一路3.3V,但中间串一颗磁珠,减少MCU开关噪声窜入模拟电路的风险。AVDD和DVDD之间,数据手册通常建议同一个来源加上磁珠隔离即可,不需要两个独立电源树。
内部基准电压可以选2.048V或4.096V,由寄存器配置。选哪个看你的信号范围。热电偶信号经过PGA放大后通常在参考电压的一半以内,用2.048V配合PGA=64足够;如果是测RTD,信号幅度稍大,用4.096V更合适,能留出更大的余量。
精度要求高的时候,建议外部基准。内部基准的温漂大约是几个ppm/℃,对于0.5℃精度的系统没问题。但现场环境在-20℃到70℃之间波动时,内部基准的温漂会直接反映在测量结果里。我做的那套控制器,要求高温段误差不超过±0.3℃,就直接加了REF5025外部基准芯片,基准漂移控制在3ppm/℃,效果比软件校准省心。
2.3 传感器接线方式
热电偶信号是毫伏级的,接法上要特别注意线材和滤波。K型热电偶的引线如果比较长,现场容易感应工频干扰,所以从端子上到ADC输入端之间,建议加一个RC低通。我用的是差分输入各串联10Ω电阻,然后两条线之间并联一个1nF电容,构成差分滤波。这个RC截止频率大约是几十kHz,已经能压掉大部分高频噪声。注意电容不要选太大的,如果RC过低,会拖慢ADC内部采样电容的建立时间,反而引入增益误差。
冷端温度补偿是热电偶测量里的关键环节。热电偶测的是热端与冷端的温差电动势,想要得到绝对温度,必须测出冷端(也就是接线端子处)的温度,然后补偿回去。我直接用板上的一颗热敏电阻或者二极管放在接线端子附近,连接到ADC的一组输入通道,用IDAC电流源激励测温,芯片内部有专门针对冷端补偿的配置项。这样硬件上不需要额外电路,软件里查表加多项式即可。
RTD接法分两线制和四线制。两线制简单,但导线电阻会直接叠加到测量结果里,我后面会详细讲到误差抵消的办法。四线制用四根线连接传感器,激励电流走两根,电压测量走另外两根,完全消除线阻影响,适合对精度要求高的PT100测点。
3. 软件驱动——从寄存器到底层数据解析
3.1 SPI初始化与底层读写
基于STM32的HAL库,SPI初始化代码很直接。但有一点需要注意,每次读转换数据时,片选信号要完整地拉低→写命令→读数据→拉高,不要图省事一直把CS拉低。ADS122U04IPWR在CS持续低电平时也能工作,但这样如果中间有一次通信时序被打乱(比如被高优先级中断插了一脚),整个通信状态就乱了,而且不好恢复。所以每次访问ADC都重新拉低CS,操作完立即拉高,可靠性最好。
底层读写函数我一般写成这样:
uint8_t ads122u04_read_write(uint8_t byte) { uint8_t rx = 0; HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(&hspi1, &byte, &rx, 1, 100); HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); return rx; }虽然看起来简单,但整个通信时序的基础就是它。底层函数里我没有在每次操作之间加延时,实际通信时钟用的是2MHz,写寄存器、读数据都很快,不需要额外等待。个别批次芯片对por上电时间有要求,上电后最好等100ms再开始配置寄存器,不然后端读取的第一个寄存器值可能是默认值,容易出现“配置写进去了但没生效”的假象。
3.2 寄存器配置要点
ADS122U04IPWR的寄存器配置直接决定了测量模式和精度,我是按下面的顺序来设置的:
- Config Reg0:PGA增益和输入模式选择。热电偶K型接差分输入,PGA设置为64倍。如果是PT1000直接测电压,PGA可以设成4或8倍,避免小信号被噪声淹没。
- Config Reg1:数据速率和通道选择。常用20SPS,这个速率下50Hz工频干扰有不错的抑制效果(积分周期正好与工频周期对齐),同时分辨率也够高。通道选择成AIN0-AIN1作为差分热电偶输入,AIN2-AIN3用作板温冷端补偿输入。
- Config Reg2:基准源选择。用外部REF5025时选外部基准输入,用内部基准则选内部基准。同时配置IDAC电流源输出引脚和电流大小。PT1000的激励电流一般设250μA,功耗小,自热效应可以忽略。
- Config Reg3:IDAC方向和电流源设置。此寄存器还包含热电偶开路检测的配置,如果检测到传感器断线,可以把报警结果发给MCU,方便现场运维人员排查。
写入寄存器后,强烈建议读回校验一遍。我用的是“写配置寄存器后读同一寄存器,比对结果一致才继续进行后续操作”的方式。虽然会多花几十微秒,但能有效避免因为时序问题导致的“哑配置”。
3.3 数据读取与补码解析
ADS122U04IPWR是24位ΔΣ ADC,输出数据是二进制补码格式。读取过程是:CS拉低,发送读取命令,连续读取3个字节(MSB在前),CS拉高。
拿到这3个字节之后,最重要的坑就是符号扩展。如果直接把这3个字节拼成uint32_t,最高位是符号位,不处理的话,负温度会变成巨大的正数。我见过好几份项目代码死在这一步,排查半天发现是因为忘了补码转有符号数值。
补码转真实电压的完整处理:
int32_t raw = (buf[0] << 16) | (buf[1] << 8) | buf[2]; if (raw & 0x800000) { raw -= 0x1000000; // 符号扩展 } float lsb = 2.048f / (1 << 23) / 64.0f; // 参考电压2.048V,PGA=64 float voltage = raw * lsb;其中LSB的计算要记住,参考电压是2.048V时,24位ADC的满量程对应±2.048V/PGA。所以每个LSB代表的电压就是 2×参考电压/(2^24)/PGA,代码里按2.048/(1<<23)/64计算,就是单边满量程2^23个码对应的值。这个公式看着绕,但一定要自己推一遍,不然数据出来偏一个固定倍数都不知道问题在哪。
3.4 冷端补偿与软件滤波
冷端补偿是热电偶测量里最容易被忽略的部分。简单说,热电偶测到的电压是热端和冷端的温差对应的电动势,冷端温度变化会直接造成相同幅度的误差。很多新手把热电偶接上就测,发现读数反复漂移,其实就是忽略了冷端温度。
我的做法是在PCB接线端子旁放一颗高精度NTC热敏电阻,用另一路ADC输入测它,得到冷端温度。软件流程是这样的:
- 读取NTC的ADC值,换算成冷端温度Tc。
- 查NIST热电偶分度表(或者用多项式近似),算出在Tc温度下K型热电偶对应的毫伏电压E_c。
- 用这个E_c加上从ADC读到的热端毫伏电压E_meas,得到补偿后的总电动势E_total。
- 再用E_total反查分度表,得到真实热端温度。
这个过程听起来麻烦,但代码实现后运行起来非常稳定。查表时可以预先用程序把分度表存成数组,MCU里做线性插值,1kHz的采样率下随便跑。分段多项式拟合也是一种做法,但我不推荐很多人直接用的三阶多项式全局拟合,温度范围宽的时候,拟合误差会到几度。老老实实分段查表,最稳妥。
滤波方面,我用的是“滑动平均+一阶IIR”的组合。原始数据20SPS,滑动平均窗口取4个点,相当于每秒输出5个有效值,然后又加了一个系数为0.2的一阶低通,进一步平滑。实测下来,原本读数会有±0.2℃左右的跳动,叠加滤波后能稳定在±0.05℃以内。真要响应速度,可以等稳定后把窗口调小,或者搞自适应滤波,按现场需求取舍。
4. 实测场景——工业现场与HVAC应用
4.1 工业现场:变频器附近的K型热电偶测温
工业现场最常见的干扰源就是变频器,它输出的PWM波形会在空间产生强烈的电磁辐射。我测试的工况里,控制柜内同时装了一台4kW变频器和温度采集板,距离不到20cm。初始测试时,热电偶屏蔽层两端都接地,空载时读数稳定,变频器一启动,读数直接跳了1.5℃。
问题出在屏蔽层的接地方式上。热电偶屏蔽层如果两端都接地,会形成地环路,变频器通过地线注入的共模电流在屏蔽层上产生压降,又被热电偶差分输入检测到一部分。
后来改成屏蔽层靠近ADC板一端单端接地,另一端悬空,跳变幅度立刻降到0.3℃以内。再配合软件滤波,现场结果稳定在±0.1℃内。这个现象很典型,很多工程师只关注ADC芯片选型,忽略了现场接地策略,结果精度怎么也上不去。
4.2 HVAC系统:风管温度和AHU回水温度采集
HVAC场景的特点是距离远、线缆长、测点分散。风管内的温度传感器通常是PT1000,采用两线制接法时,导线电阻引起的误差不可忽视。比如一栋楼里的风管温度测点,从控制柜到传感器可能有30米,铜导线0.5mm²的电阻大约是36Ω/km,来回线阻接近2Ω。PT1000在0℃时标称电阻1000Ω,温度系数大约是0.385Ω/℃,所以2Ω线阻带来的误差大概是5.2℃。
两线制解决不了线阻问题,就只能设法补偿。ADS122U04IPWR的IDAC激励电流有一个好处,可以给激励电流配一个校准电阻路径:让IDAC电流同时流过已知精度的基准电阻和PT1000,通过分别测量两者电压的比例关系,把导线电阻的影响用软件消除。
实际项目里,我在AHU回水温度测点用了四线制PT1000,回来细线四根直接接ADC板,精度测试下来,全量程范围内误差不超过±0.15℃。风管温度测点因为原先管线已布好,只有两线,用上面说的比例补偿法把线阻误差从5℃拉回到0.2℃左右。这个补偿方法要是没有内部IDAC,做起来要外接恒流源,麻烦得多。
4.3 精度验证与系统校准
不管硬件多好,出厂前都建议做一次系统校准。我在实验室里用FLUKE的校准仪直接注入毫伏信号来模拟热电偶,从0到20mV按1mV步进测了一遍。
校准方法很简单:
- 校准仪不出信号,记录ADC输出的零点漂移值。
- 逐步注入标准毫伏源,记录每个点的ADC输出码值。
- 用最小二乘法拟合实际增益和偏置,得到两组修正系数。
- 把修正系数写进固件里,每次读数先乘增益修正系数,再加偏置修正系数。
做完校准之后,实测下来的数据是:温度点误差在0℃附近约±0.05℃,在300℃附近约±0.15℃,在600℃附近约±0.25℃。误差随温度变大的主要原因有两个,一是热电偶的非线性度,二是冷端补偿的温度测量误差。如果想要全程±0.2℃以内,需要在上位机做多点标定,做成分段修正表,那就要花更多工夫了。
5. 常见问题与排查技巧实录
这部分是我在实际开发中踩过的坑,整理成一张速查表,适合遇到问题的时候按图索骥。
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| SPI读数据全是0xFFFFFF | 通道配置没生效,或者输入悬空导致输出饱和 | 检查寄存器回读值,PGA增益调低,把输入引脚接固定电压 |
| 读数波动大,跳变好几度 | 接地环路或屏蔽层两端接地 | 屏蔽层单端接地,AVDD和DVDD间加磁珠隔离 |
| 负温度显示成巨大正数 | 补码没做符号扩展 | 检查代码里的raw &= 0x800000判断逻辑 |
| 写入寄存器后行为不变 | 通信时序有问题,上电后未等待就配置 | 上电延时100ms再初始化,CS操作完整 |
| 偶尔出现一个大的离群点 | DRDY读取时机不对,数据更新瞬间读了半个新旧数据 | 换成DRDY下降沿中断后再读,不用轮询方式 |
| PT1000测出来的温度偏高 | 两线制线阻未补偿 | 增加校准电阻比例测量,或者改四线制 |
| 冷端温度不准导致整体偏移 | 冷端传感器离接线端子太远 | 冷端传感器贴到端子,用硅胶固定保证热耦合 |
还有一个很实用的技巧,ADC输入端虽然没有损坏风险很大,但工业现场长线上会有静电和浪涌,最好在ADC前面加一级ESD/TVS保护管,再串电阻限流。仪表在柜内测试时啥事没有,安装到现场连续打雷就坏了一个通道输入,排查下来就是接口处没做防护。加了TVS之后到现在没再出过问题。
写在最后
ADS122U04IPWR和STM32F303RE这套组合,最让我满意的其实是它的“省心”——硬件上外围器件少,软件上寄存器逻辑清晰,不需要为了采样精度去逐级调运放的零点和偏置。真正花时间的地方都在数据解析和补偿算法上,而这些恰恰是可以沉淀成通用代码模块的。如果你也正在做温度采集相关的产品,我的建议是先别急着堆硬件,先把传感器型号、接线方式、隔离策略和补偿方案想清楚,再动手画板写驱动。这几个环节要是都理顺了,后面就是水到渠成的事。