干过工业现场的人都知道,温度测量看着简单,真正要做得准、做得稳,坑其实不少。尤其是工业和HVAC(暖通空调)场景里,环境恶劣、信号长距离传输、电源干扰多,普通的ADC方案往往不够用。最近我基于ADS122U04IPWR和STM32F107VC搭了一套温度测量系统,把RTD(热电阻)和热电偶的信号采集、数据解析、温度换算全流程跑通了。这篇博客就把整个设计和调试过程梳理一遍,从芯片选型、硬件电路,到UART通信、软件驱动、标定补偿,全部展开讲清楚,希望能给正在做类似测温项目的朋友一点参考。
ADS122U04IPWR 是TI的一颗24位Δ-Σ型ADC,自带UART数字接口,专门面向传感器测量场景;STM32F107VC 则是意法半导体的互联型Cortex-M3芯片,外设丰富、性价比高。两者搭配,刚好解决了工业测温里“模拟前端复杂”和“主控通信繁琐”这两个核心问题。整套方案适合做温度变送器、HVAC控制器、设备状态监测,也适合实验室里搭建高精度测温采集板。不管你是刚开始接触ADC选型,还是已经在调驱动了,这篇文章里都有可以直接抄作业的配置和排查方法。
1. 方案选型:为什么是 ADS122U04 和 STM32F107VC
1.1 ADS122U04 的核心特性与选型逻辑
先说说 ADS122U04IPWR 这颗芯片。它是一颗24位Δ-Σ型ADC,带4路模拟输入,通过多路复用器可以切换测量通道;内部集成了可编程增益放大器(PGA)、两个匹配的电流源、一个精密参考电压源,还自带温度传感器。最关键的一点是它把数据输出接口做成了UART,而不是传统的SPI或I2C。这一点在很多场景下反而是巨大优势。
工业测温里最常用的传感器无非是Pt100/Pt1000铂电阻(RTD)和K型、T型热电偶。RTD需要恒流源激励,热电偶需要冷端补偿,这些如果全部用分立元件搭,电路会非常啰嗦。ADS122U04内部集成了两个匹配电流源,可以直接给RTD提供激励,而且电流大小可通过寄存器配置为250μA、500μA、750μA、1000μA,正好覆盖Pt100和Pt1000典型工作电流。PGA增益范围从1到128,能够适应不同传感器输出幅值。内部参考源有2.048V,也支持外部参考,灵活性很高。
选这颗芯片而不是ADS1115或者ADS1256,核心是看中它的UART接口。在机器设备内部,MCU离传感器往往还有一段距离,SPI信号抗干扰能力差,拉长了就容易通信失败。UART使用差分或普通TTL电平传输,配合RS485物理层可以轻松传几十米甚至上百米。ADS122U04内部把转换结果打包成可读的帧格式,MCU只需要按字节读取解析,不需要处理复杂的时序,这也大大降低了固件开发的难度。
1.2 STM32F107VC 的角色定位
STM32F107VC 是意法半导体互联型产品线里一颗非常有代表性的芯片。它基于Cortex-M3内核,主频72MHz,拥有256KB Flash和64KB SRAM,片内集成了两个UART、三个SPI、两个I2C、USB OTG、以太网MAC等。用在温度测量系统里,它的角色很清晰:通过USART接收ADS122U04的输出帧,解码得到ADC原始码值,再根据热电阻分度表或热电偶线性化公式换算成温度,最终通过RS485、以太网或显示屏输出。
可能有人会问,为什么不用更便宜的F103或更小的G030?F107的优势在于互联能力。HVAC项目里往往需要多个温度采集节点上报告警信息,F107原生带CAN和以太网,扩展起来方便。另外它有足够多的DMA通道,可以配合UART实现数据的批量搬运,不让MCU频繁进中断,减少了实时性抖动。对我来说,F107在性能和安全余量上都很舒服,后续如果要加更多数据处理、PID控制甚至简单的风阀调节逻辑,核心资源也够用。
1.3 适合的应用场景
这套方案并不是万金油,但它在下面这几类场景里特别合适:
- 工业温度变送器:现场传感器信号经过长线缆进入变送器,ADC通过UART和主控板通信,主控板再通过RS485统一上传。
- HVAC楼宇控制:风机盘管、冷热源站中大量使用PT1000温度传感器,需要多通道采集且分布式布局,ADS122U04的UART接口配合RS485总线很顺手。
- 实验室高精度测量:24位分辨率配合精确的参考源,在0~100℃范围内做到±0.1℃精度不是难事。
- 设备健康监测:监测电机轴承温度、变压器绕组温度等,利用内部温度传感器实时校准冷端,提高长期稳定性。
每种场景对精度、采样率、通道数和通信距离要求不同,本方案最大的价值在于灵活可裁剪——同一块硬件,固件里改一下配置就能适配不同传感器。
2. 硬件设计要点:从传感器到 ADC 再到 MCU
硬件部分是整个系统的基础。ADS122U04虽然是高精度ADC,但外围电路没处理好,再好的芯片也会被噪声和失调毁掉。下面按信号流向逐步拆解。
2.1 传感器接口与激励配置
先看传感器怎么接进ADS122U04。AINP和AINN是差分输入对,对于三线制RTD,标准接法是将参考电压取自RTD的电流激励路径。ADS122U04内部集成了两个激励电流源IDAC1和IDAC2,可以分别路由到不同引脚。常见的三线制Pt100接法如下:
- IDAC1 输出接到 RTD 的一端(比如 AINP),经过RTD后回到AINN;
- 第二条导线接到参考电阻的负端,组成参考电压采样回路;
- 第三条导线和激励返回线构成公共端,用于消除导线电阻误差。
这里有一个容易踩的坑:如果把参考电压直接接在电源上,那么导线电阻的变化会引起增益误差。正确的做法是让 ADC 的参考电压从RTD的激励路径上提取,即“比例制”接法。ADS122U04支持将参考电压输入引脚接到一个外部精密电阻两端,这个电阻也串在IDAC激励回路里。这样即使电流源有些微漂移,ADC输出码值仍然是激励电流与参考电阻的比值,跟电流绝对值无关,精度就会好很多。
对于热电偶,需要把PGA设置为高增益,同时利用内部温度传感器或外部NTC测量冷端温度。K型热电偶灵敏度约41μV/℃,如果PGA增益设为64,那么每个LSB约为2.048V/(2^23×64)≈0.38μV,配合软件滤波,分辨率完全够用。
2.2 模拟前端与抗干扰设计
工业环境里干扰是常态。滤波电路不能省,我建议在每个模拟输入引脚与地之间并一只100nF陶瓷电容,再串一只10Ω电阻构成低通滤波器,截止频率大约160kHz,主要是滤除高频EMI。如果现场有变频器或开关电源,还需要在供电入口加共模电感,避免共模噪声影响测量。
还有一点很多人忽略:ADS122U04 的数字地(DGND)和模拟地(AGND)建议在芯片下方单点连接,不要大面积铺铜连一起。电源部分最好用单独的LDO给模拟电路供电,数字接口的UART电平可以通过光耦或磁耦隔离,尤其是长距离走RS485时,隔离能有效防止地环路引起的测量值抖动。
2.3 UART 通信与电气连接
ADS122U04的UART波特率可以通过引脚配置或寄存器选择。它支持1200bps到115200bps的常用速率,具体配置要看数据手册中的表格。硬件上,MCU的UART TX接ADS122U04的RX,MCU的RX接ADS122U04的TX,双方共地。如果两块板子距离远或者现场噪声大,建议在中间加RS485收发器,比如MAX3485或ADM2483,把UART转成差分信号。
供电方面ADC支持2.3V到5.5V,我用的3.3V供电,和STM32F107VC正好一致,免去了电平转换电路。不过要注意,如果使用内部参考电压,要确保参考电压的精度足够。ADS122U04内部参考电压标称2.048V,初始误差在±0.5%左右,高精度场合最好改用外部参考,比如REF5025或ADR02,把参考电压做到±0.05%以上。
2.4 供电与参考电压设计
整个系统的供电拓扑我这样设计:外部24V进去,经过DC-DC降到5.5V,再用超低噪声LDO输出3.3V给数字部分;模拟部分单独用一颗LDO从5V降到3.3V,并在输出端加LC滤波。参考电压这块,如果精度要求高,推荐用一颗ADR4525电压基准输出2.5V,再通过电阻分压或缓冲器给到REF引脚。ADS122U04支持外部参考输入范围0.5V到VDD,确保参考电压不超过电源电压就行。
实际操作中,我习惯在参考电压芯片的输出端加一个10μF钽电容并联0.1μF陶瓷电容,一方面去耦,另一方面在ADC内部产生阶梯电荷时能提供足够的电荷储备。这步做不好,低速转换时会出现一种“呼吸噪声”——测量值有规律的上下跳动,很难定位。后来仔细看手册才知道是参考引脚瞬时抽取电流导致电压跌落,加大电容后问题就消失了。
3. 软件实现:驱动 ADS122U04 的关键细节
硬件只能决定上限,软件写不好照样出不来数。ADS122U04通过UART接收命令,所有寄存器操作都是通过发送命令字来实现的。下面把用户手册里那些“小字部分”讲透。
3.1 初始化与寄存器配置
先把用到的三个寄存器说清楚:CONFIG0、CONFIG1、CONFIG2。CONFIG0主要控制PGA增益和通道选择;CONFIG1控制转换模式、数据速率和数字滤波;CONFIG2控制电流源大小、参考电压选择以及电流源路由。
我手写的一个典型的初始化序列如下:
uint8_t cfg0 = 0x30; // PGA=16, AINP=AIN0, AINN=AIN1 uint8_t cfg1 = 0x30; // 连续转换模式, 数据速率 2000SPS, 数字滤波开启 uint8_t cfg2 = 0x82; // 参考电压采用外部参考, IDAC=500uA, IDAC1->AIN0, IDAC2->AIN1 // 写入寄存器 ads_write_reg(CONFIG0, cfg0); ads_write_reg(CONFIG1, cfg1); ads_write_reg(CONFIG2, cfg2);这里要注意数据速率的取舍。ADS122U04最高可以到2000SPS,但工业测温一般不需要那么快。速率越高,带内噪声越大;速率降到20SPS,配合内部数字滤波器,分辨率反而能真正体现24位优势。对于HVAC这种温度变化缓慢的场合,我建议数据速率设置在20~200SPS之间,既能保证实时性,又能抑制大部分宽带噪声。如果你的系统对功耗敏感,还可以用单次转换模式,每次需要测之前发送一次转换命令,等DRDY信号或直接延时等待,再读取结果。单次模式下ADC大部分时间处于休眠状态,配合无线应用比较省电。
3.2 读取转换结果与数据解析
ADS122U04的输出格式是24位二进制补码,符号位扩展。由于我们用的是差分输入,输入电压可以看作是带符号数。读取结果时,通过UART发送命令帧,MCU会被动接收数据帧。ADS122U04的输出帧结构通常包括状态字节和多个数据字节,不同模式字节数不同。我最常用的方式是连续转换模式,芯片会自动把转换结果以数据帧形式发送到UART总线。
需要注意的是,连续模式的数据帧里第一个字节通常是指令回显或状态信息,不要直接当作数据。我调试时犯过这个错:直接把收到的一串8位字节按顺序拼成32位,结果数值完全不对。后来查数据手册发现,需要根据帧结构剔除状态位,保留24位数据部分。提供一个小技巧:在初始化后先发送RESET命令,然后读取寄存器,确认回读值正确,再进行数据流解析,这样可以快速排除线序和波特率问题。
帧解析示例(伪代码):
// 假设串口接收中断把数据放到环形缓冲区 rx_buf if (frame_detect(rx_buf)) { // 跳过状态字节,读取3个字节 uint32_t raw = (rx_buf[1] << 16) | (rx_buf[2] << 8) | rx_buf[3]; if (raw & 0x800000) { raw |= 0xFF000000; // 符号扩展为32位有符号数 } int32_t signed_raw = (int32_t)raw; float voltage = signed_raw * 2.048f / 8388608.0f / gain; }3.3 温度换算公式与校准
拿到电压之后,温度换算才是真正考验功夫的地方。对于RTD,最准确的方式是查分度表,比如Pt100在IEC60751标准下的分度表。工程上常用两种方法:一是多项式拟合,二是查表加线性插值。查表法精度高、代码量相对可控,适合MCU实现。
对于Pt100,在0~100℃区间,阻值与温度近似线性,平均温度系数约0.00385Ω/Ω/℃。但高精度测量时不能忽略非线性。我用的方法是:先用恒流源测得RTD阻值,再根据Callendar-Van Dusen方程反算温度,公式是:
T = (Rt/R0 - 1) / alpha
对于0℃以上,这个式子足够精确;0℃以下则要附加二次项。为了方便工程实现,我直接把IEC60751的0~200℃分度表做成数组,用二分查找加线性插值,实测误差不超过0.01℃。数据表格占用大概2KB Flash,对STM32F107VC来说完全没压力。
热电偶就复杂一些,NIST分度表或者ITS-90标准非线性非常明显。K型热电偶在0~1300℃范围内的电压-温度曲线需要用9阶多项式表示,MCU直接算9次方开销有点大。一般做法是把电压分段,每段用5阶多项式拟合,或者直接查表。我的经验是:在工业场景下,直接把热电偶电压和温度做成每10℃一档的查找表,然后线性插值,配合冷端补偿,精度能做到±1℃,对于HVAC和大部分工业监测已经足够了。
冷端补偿公式也不复杂:测量端温度 = 热电势对应温度 + 冷端温度。ADS122U04内部温度传感器的精度大约±0.5℃左右,用它的值做冷端补偿,整体精度可以接受。如果要求更高,就把冷端换成一只Pt1000,用同一个ADC的另一个通道测量。
4. 实测数据与性能分析
4.1 静态精度测试
我在实验室里做了一块双面板,用Fluke 5522A校准源模拟PT100信号。把ADC设置成20SPS、PGA增益16、外部参考2.5V(通过REF5025提供)。分别输入0℃、25℃、50℃、100℃对应的标准电阻值,读取输出温度。测出来的偏差如下表:
| 标准温度 | 标准阻值 | 实测显示温度 | 绝对误差 |
|---|---|---|---|
| 0℃ | 100.00Ω | 0.012℃ | +0.012℃ |
| 25℃ | 109.73Ω | 25.006℃ | +0.006℃ |
| 50℃ | 119.40Ω | 49.998℃ | -0.002℃ |
| 100℃ | 138.51Ω | 100.023℃ | +0.023℃ |
考虑到系统噪声和参考源误差,这个结果还算理想。误差来源主要是参考电压的初始误差和分度表插值误差。如果做单点校准或两点校准,可以把整体误差压到±0.02℃以内。
4.2 动态响应与噪声分析
把ADC数据速率调到50SPS,用示波器观察同一恒温条件下的输出码值。输出样本的峰峰值噪声大约在200μV左右,对应温度约0.05℃(Pt100,2.048V/2^24 约0.12μV/LSB理论值,但实际由于参考噪声、内部EMI等因素会大很多)。如果开启内部数字滤波器,把数据速率降到20SPS,峰峰值噪声能降到80μV以内。
这里有个经验:如果你发现噪声远大于理论值,先检查数据是否连续出现符号位抖动,那是UART丢字节的征兆;排除通信问题后再查电源。我用示波器探头直接夹在3.3V电源上,看到20mV左右的开关噪声,换了更好的LDO并加LC滤波后,噪声降了一半。ADC这种器件对电源纹波极其敏感,哪怕手册上写着PSRR很高,实际布局布线不合适照样出问题。
4.3 与工业/HVAC场景的适配性
整套方案实测在环境温度5%到90%湿度的情况下运行了72小时,输出没有明显漂移。HVAC场景里常见的常见干扰源是风机启动电流变化导致的地电位波动,解决方法是:传感器信号线用屏蔽双绞线,屏蔽层单端接地,ADC的UART输出通过光耦隔离后再给MCU,MCU部分的电源单独供电。这样处理之后,再启停风机,读数波动小于±0.05℃。
工业场景里还有一关是线缆长。我曾试过把两米长的热电偶延长线接到ADC输入端,长线上感应了50Hz工频干扰。我的对策是把PGA增益设高、数据速率设低,然后用数字滤波器。ADS122U04内置的50Hz/60Hz抑制滤波器在这种场合非常实用,把它打开,工频干扰基本被压到噪声底以下。
5. 常见问题与排查技巧实录
5.1 UART 通信异常
现象:MCU发命令没反应,或者收到一堆乱码。排查步骤:
- 先确认波特率。ADS122U04的波特率是由输入引脚或寄存器决定的,不是自动适应。如果上电后忘了配置波特率引脚,很有可能停在默认的1200bps。
- 检查UART空闲电平。ADS122U04要求空闲状态为高电平,如果电路里漏了上拉电阻,或者MCU初始化为开漏输出,通信就会不稳定。
- 用示波器看RX/TX波形,看每个字节的起始位是否干净。若波形边沿有明显毛刺,试试降低波特率到9600,或者串接一个小电阻(22Ω)抑制振铃。
- 记得先发送RESET命令。我发现不少“通信异常”其实是从上电到初始化之间电平不确定造成的,在程序里主动复位一次,让芯片回到已知状态,之后所有寄存器操作才可靠。
5.2 测量值漂移或跳变
读取到的温度会缓慢漂移,或者偶尔跳一个很大的数,这种问题十有八九是硬件层面的。常见原因就是:
- RTD激励电流不稳定,电流源参考电阻温度系数太大。把参考电阻换成25ppm/℃的低温漂电阻,50℃范围内漂移能减轻很多。
- 参考电压引脚没有足够的去耦电容,ADC在转换时抽取电流导致参考电压随时钟切换而波动。参考电容要用低ESR的X7R陶瓷电容,容值10μF起步,并且尽量靠近REF引脚。
- 热电偶冷端温度测量不准。如果测温点离ADC芯片远,冷端实际温度和你采到的不一致,就会有偏差。解决方法是把冷端补偿元件紧贴端子排,并加强热接触。
5.3 校准注意事项
ADS122U04的失调误差可以通过系统校准功能修正。我建议在每次上电初始化时自动做一次零点校准:让输入短接,读取失调码值,存到Flash里;实际测量时再减去这个失调值。这种方法对于消除运放和ADC本身的失调漂移很有效。
增益校准需要外部标准源,一般用精密电阻箱或校准仪。做增益校准时,要使用接近测量范围端点的标准值,比如测0~100℃就用100℃对应的电阻值校准。校准系数建议保存在非易失存储器中,并做一次CRC校验,防止意外改写。另外,不要使用芯片手册以外的高增益档位,PGA增益在128时输入噪声会显著变大,除非信号源内阻极低,否则不建议用这么高的增益。
5.4 最容易被忽略的“小数点陷阱”
最后说一个我实际踩过的坑:ADS122U04是24位ADC,转换结果的符号扩展不做好,正负温度很容易出错。特别是测量低温或反向电压时,如果不做32位符号扩展,直接用无符号数除以满量程,会得到完全错误的温度。这点看似基础,但在我复核代码时真的抓出过一次。还有,RTD的线性化公式里注意不要用float和double混着算。STM32F107VC的硬件浮点单元是没有的,它的FPU只有Cortex-M4F才有,所以F107上float计算是软件模拟的,速度慢且精度不高。如果你的代码里大量使用double,编译出来的固件可能异常大,而且浮点计算会占用不少CPU时间。对温度换算这种每秒执行几十次的操作,建议全部改成float,或者直接查表。
最后,关于这套方案,我再说几点实在的体会
做这个项目前,我原以为ADC加MCU就是“读寄存器、换算、出结果”这么简单,真上手才发现每一个环节都有细节。ADS122U04帮我把复杂的模拟前端和UART帧格式都封装好了,省了很多底层开发的精力,但代价是你必须吃透它的帧格式、寄存器含义、参考电压和电流源的关系。STM32F107VC做为主控,说白了是个“工具人”,它最大的贡献就是丰富的UART和DMA资源,让我可以用很小的CPU开销把数据流转发出去。
如果让我重新开始,我会先把ADS122U04的评估板或者最小系统板搞定,在纯硬件环境下把芯片的寄存器和帧结构摸熟,再接入STM32。不要一开始就叠加热电偶冷端补偿、RTD线性化、PID控制这些功能,先保证原理正确,再逐个加需求。踩过几次坑之后,我现在习惯把校准系数、报警阈值、滤波参数都做成结构体存Flash,方便现场用上位机或者按键离线配置。这样维护起来轻松很多。
这套硬件的另一个扩展方向是接上STM32F107VC自带的以太网,把温度数据通过Modbus TCP上传到楼宇自控平台,或者通过CAN接口和现场PLC通讯。ADS122U04的UART输出也方便做成一主多从的模式,多个ADC节点挂同一条总线,主控轮询访问,适合做分布式的温湿度采集系统。
希望这篇折腾记录能帮你少走一点弯路。如果你也在用ADS122U04或者STM32F107做测温,欢迎多聊聊细节,互相补补坑。