工业测温方案解析:ADS122U04与STM32F042K6的UART高精度RTD采集设计
1. 为什么工业测温场景偏偏选中了 ADS122U04 加 STM32F042K6 这套组合工业现场和 HVAC 系统里的温度测量跟实验室里拿个万用表戳两下完全是两码事。实验室里环境恒定、干扰小、对成本不敏感而工业现场要考虑的是传感器离主控可能十几米远、现场有变频器和大功率继电器在疯狂开关、环境温度从零下几十度到零上一百多度、设备要连续跑好几年不能停。这些约束条件叠加在一起就决定了测温方案不能随便选。PT100 和 PT1000 这类 RTD 传感器之所以在工业测温里占据主导地位核心原因是线性度好、长期稳定性强、互换性好。你拿一个 A 级 PT100在零度的时候阻值就是 100 欧姆一百度的时候大约 138.51 欧姆这个关系非常稳定不会像热敏电阻那样用两年就飘了。但 RTD 有个天然的麻烦它的电阻变化量太小了。PT100 在零度附近温度每变化一度阻值只变化大约 0.385 欧姆。你要测到 0.1 度的分辨率就得分辨出大约 0.0385 欧姆的阻值变化。这个量级放在有电磁干扰的工业现场用普通的 ADC 根本搞不定。ADS122U04IPWR 这颗芯片就是冲着这个痛点来的。它是 24 位 delta-sigma 架构的 ADC内置 PGA支持两路差分输入或者四路单端输入最关键的是它自带 UART 接口。注意是 UART不是 SPI 也不是 I2C。这个选择在工业场景里非常讲究。SPI 和 I2C 适合板级通信走线短、速率高但一旦传感器和主控之间拉开距离SPI 的时钟线就容易受干扰I2C 的总线电容限制也让人头疼。UART 是异步通信只需要 TX 和 RX 两根线对时钟同步没有要求配合 RS485 收发器可以轻松拉到上千米这在 HVAC 系统里太常见了——楼宇自控的传感器分布在各个楼层走线动辄几十米。STM32F042K6 作为主控定位很清晰ARM Cortex-M0 内核48MHz 主频32KB Flash6KB SRAM封装小巧成本低廉但外设该有的都有——UART、SPI、I2C、ADC、定时器一应俱全。它不需要跑操作系统裸机就能把 ADS122U04 的数据读回来、做线性化计算、通过 UART 上报给上位机或者网关。这套组合的精髓在于ADS122U04 负责把微弱的 RTD 电阻变化转换成高精度数字量STM32F042K6 负责数据处理和通信调度两者通过 UART 连接物理层可以用 RS485 或者直接 TTL 短距离传输。我见过不少项目在选型阶段纠结要不要用集成式测温芯片比如 MAX31865 这类专用 RTD 前端。MAX31865 确实方便SPI 接口内置 15 位 ADC但它的分辨率在需要 0.01 度精度的场合就不够看了。ADS122U04 的 24 位分辨率配合外部基准电阻和合理的 PGA 增益做到 0.01 度甚至更高完全可行。而且 ADS122U04 的输入多路复用器可以轮流采集多个通道一个芯片管好几路温度点在 HVAC 的多区域温度监测里很实用。还有一个容易被忽略的点ADS122U04 内置了激励电流源。RTD 测量需要恒流激励这个电流源直接集成在 ADC 里省掉了外部恒流源电路。你可以通过寄存器配置激励电流的大小比如 10 微安、50 微安、100 微安、250 微安、500 微安、1 毫安、1.5 毫安。这个灵活性很重要因为激励电流太大会导致 RTD 自热太小则信号太弱容易被噪声淹没。PT100 在 1 毫安激励下的功耗大约是 0.1 毫瓦自热误差可以控制在 0.01 度以内这个平衡点需要根据具体封装和散热条件来调。2. 硬件链路怎么搭从 PT100 到 STM32 的完整信号路径2.1 RTD 接口电路的设计细节与参数计算PT100 的接法有讲究。两线制最简单但导线电阻直接叠加在测量结果里每米铜线大约 0.02 欧姆十米来回就是 0.4 欧姆折算成温度误差接近 1 度这在工业场合不可接受。三线制能补偿导线电阻前提是三根线材质长度一致ADS122U04 配合外部多路开关或者直接利用其内部多路复用器可以实现三线制测量。四线制最准完全消除导线电阻影响但多一根线成本高一些。HVAC 里三线制用得最多性价比和精度平衡得比较好。具体到 ADS122U04 的电路我一般这样设计PT100 一端接激励电流源输出引脚另一端接 ADC 的差分输入正端同时通过一个基准电阻接地。基准电阻的精度直接决定测量精度必须用低温漂的金属箔电阻或者高精度薄膜电阻温漂控制在 5ppm/度以内阻值选 1.65 千欧或者 3.3 千欧这种常见值。为什么选这个值因为 ADS122U04 的基准电压来自外部基准电阻两端的压降激励电流乘以基准电阻就是基准电压。如果激励电流是 500 微安基准电阻 3.3 千欧基准电压就是 1.65 伏这个值在 ADC 的推荐工作范围内。差分输入负端接在 PT100 和基准电阻的连接点这样 ADC 读到的差分电压就是 PT100 两端的压降。PGA 增益设置要算一下PT100 在最高测量温度时的阻值乘以激励电流不能超过 ADC 的满量程输入范围。假设测到 200 度PT100 阻值约 175.86 欧姆激励电流 500 微安压降是 87.93 毫伏。ADS122U04 在增益为 1 时满量程是正负基准电压也就是正负 1.65 伏87.93 毫伏只占很小一部分分辨率浪费了。所以要把 PGA 增益调高比如增益 16满量程变成正负 103 毫伏87.93 毫伏刚好在范围内分辨率提升了 16 倍。这个计算过程在实际调试时一定要做增益选小了精度不够选大了信号超量程直接饱和。滤波电路也不能省。RTD 到 ADC 之间要加 RC 低通滤波截止频率根据采样率来定。ADS122U04 的采样率可以配置从 5SPS 到 2000SPS。工业测温不需要太快20SPS 足够了对应的截止频率设在 10Hz 左右。电阻选 1 千欧电容选 10 微法截止频率是 1/(2π×1000×10^-5)≈15.9Hz差不多。差分输入之间还要加一个 100 纳法的电容抑制共模干扰。这些电容要用 C0G 或者 X7R 材质的温度稳定性好。2.2 STM32F042K6 的外设配置与 UART 通信参数STM32F042K6 这边UART 的配置要和 ADS122U04 匹配。ADS122U04 的 UART 接口默认波特率是 115200数据位 8 位停止位 1 位无校验。STM32 的 HAL 库初始化代码大概长这样huart1.Instance USART1; huart1.Init.BaudRate 115200; huart1.Init.WordLength UART_WORDLENGTH_8B; huart1.Init.StopBits UART_STOPBITS_1; huart1.Init.Parity UART_PARITY_NONE; huart1.Init.Mode UART_MODE_TX_RX; huart1.Init.HwFlowCtl UART_HWCONTROL_NONE; huart1.Init.OverSampling UART_OVERSAMPLING_16; HAL_UART_Init(huart1);注意 ADS122U04 的 UART 模式需要先通过 SPI 或者硬件引脚配置进入。芯片上电后默认是 SPI 模式要发特定的命令序列切换到 UART 模式。这个切换命令是 0x55 加上一些配置字节具体看数据手册的时序图。我踩过的坑是切换命令发完之后要等至少 100 微秒再发下一条命令否则芯片内部状态机还没切换完命令会被忽略。STM32F042K6 的 UART 接收用中断或者 DMA 都行。数据量不大中断就够了。但要注意 ADS122U04 的数据就绪引脚 DRDY 要接到 STM32 的某个 GPIO 上配置成外部中断下降沿触发。DRDY 拉低表示转换完成STM32 在中断里通过 UART 发读取命令然后接收数据。这个流程比轮询效率高得多也不会丢数据。电源部分也要留意。ADS122U04 的模拟电源和数字电源要分开滤波模拟电源用 LDO 单独供数字电源可以和 STM32 共用但也要加磁珠隔离。基准电阻的供电要从模拟电源取不能从数字电源取否则数字开关噪声会串进来。PCB 布局上模拟部分和数字部分要分区地平面要完整不要被走线割裂。这些细节在低速高精度场合特别重要我见过太多因为地平面处理不好导致读数跳动的案例。3. 固件实现从寄存器配置到温度换算的完整流程3.1 ADS122U04 的寄存器配置与初始化序列ADS122U04 有四个配置寄存器分别控制多路复用器、增益、数据速率、工作模式、激励电流等。初始化的时候要按顺序写。第一个寄存器是配置寄存器 0高四位是 MUX 选择比如 0x00 表示 AIN0 和 AIN1 差分输入0x01 表示 AIN0 和 AIN2以此类推。接下来两位是增益设置00 是增益 101 是增益 210 是增益 411 是增益 8再往后是 PGA 使能位。配置寄存器 1 控制数据速率和转换模式配置寄存器 2 控制基准选择和激励电流配置寄存器 3 控制 IDAC 路由和 DRDY 模式。写寄存器的命令格式是先发 0x40 加上寄存器地址然后跟一个字节的数据。比如要写配置寄存器 0命令是 0x40地址是 0x00合起来就是 0x40然后跟数据字节。读寄存器是 0x20 加地址。这些命令通过 UART 发出去注意 UART 是异步的命令字节之间要有足够的间隔ADS122U04 的处理时间大概在几十微秒量级保险起见每条命令之间延时 200 微秒。初始化流程我一般这样写// 切换到 UART 模式 uint8_t cmd_switch[] {0x55, 0x00, 0x00}; HAL_UART_Transmit(huart1, cmd_switch, 3, 100); HAL_Delay(1); // 写配置寄存器 0MUXAIN0/AIN1增益16PGA 使能 uint8_t cmd_reg0[] {0x40, 0x00, 0x0C}; HAL_UART_Transmit(huart1, cmd_reg0, 3, 100); HAL_Delay(1); // 写配置寄存器 1数据速率20SPS连续转换模式 uint8_t cmd_reg1[] {0x40, 0x01, 0x04}; HAL_UART_Transmit(huart1, cmd_reg1, 3, 100); HAL_Delay(1); // 写配置寄存器 2基准外部激励电流500uA uint8_t cmd_reg2[] {0x40, 0x02, 0x10}; HAL_UART_Transmit(huart1, cmd_reg2, 3, 100); HAL_Delay(1); // 启动转换 uint8_t cmd_start[] {0x08}; HAL_UART_Transmit(huart1, cmd_start, 1, 100);这段代码里每个命令后面的延时不能省。我试过把延时去掉结果寄存器写入失败读回来的数据全是乱的。后来用逻辑分析仪抓波形才发现ADS122U04 在 UART 模式下处理命令需要时间连续发太快它会丢命令。3.2 温度换算的数学过程与校准方法ADS122U04 读回来的是 24 位有符号整数表示差分电压与基准电压的比值。换算成电阻的公式是R_RTD (Code × R_ref) / (Gain × 2^23)。其中 Code 是 ADC 读数R_ref 是基准电阻Gain 是 PGA 增益。比如 Code 读回来是 8388608也就是 2^23增益 16基准电阻 3.3 千欧那么 R_RTD (8388608 × 3300) / (16 × 8388608) 206.25 欧姆。这个值对应 PT100 大约 275 度合理。拿到电阻之后要换算成温度。PT100 的阻温关系在负五十度到零度之间和零度到八百五十度之间公式不同。工业上常用 Callendar-Van Dusen 方程零度以上R(t) R0 × (1 A×t B×t²)零度以下R(t) R0 × (1 A×t B×t² C×(t-100)×t³)其中 R0 是零度时的阻值PT100 就是 100 欧姆。A、B、C 是常数A3.9083×10^-3B-5.775×10^-7C-4.183×10^-12。实际在单片机里算这个方程零度以上可以直接解二次方程求 t零度以下要用迭代法。STM32F042K6 没有硬件浮点单元浮点运算是软件模拟的速度慢一些但 20SPS 的采样率完全够用。如果嫌浮点慢可以用查表加线性插值把负五十度到两百度的阻值表存到 Flash 里每度一个点中间线性插值精度也能到 0.01 度。校准是绕不开的环节。理论计算再准实际电路总有偏差。我一般做两点校准把 PT100 放到冰水混合物里零度读一个值再放到沸水里一百度注意当地大气压修正读一个值然后算增益误差和偏移误差。校准系数存在 STM32 的 Flash 里每次上电读出来用。这个做法比单点校准靠谱得多因为增益误差和偏移误差是两回事单点只能修一个。注意校准用的冰水混合物要等温度稳定一般需要搅拌并等待五分钟以上。沸水校准要考虑海拔海拔每升高三百米沸点大约降低一度这个误差在精密测量里不能忽略。4. 现场调试中那些让人头疼的问题和解决思路4.1 读数跳动与噪声抑制的实战经验读数跳动是工业测温最常见的投诉。表现是温度值在小数点后两位来回跳有时候能跳零点几度。原因通常有三个电源噪声、地环路、电磁干扰。排查的时候先看电源纹波用示波器交流耦合档测 ADS122U04 的模拟电源引脚如果纹波超过一毫伏就要加强滤波。我一般会在 LDO 输出后面再加一级 RC 滤波电阻 10 欧姆电容 100 微法截止频率很低对低频噪声有效。地环路问题更隐蔽。如果传感器和主控分别接地两个接地点之间存在电位差这个电位差会叠加到信号上。解决办法是传感器端不接地只用差分信号传输或者用隔离器把两边地分开。ADS122U04 本身没有隔离但可以在 UART 侧加数字隔离芯片比如 ADuM1201 这类把模拟地和数字地彻底分开。成本增加不多但效果立竿见影。电磁干扰在变频器附近特别严重。我遇到过一案例测温模块装在变频柜旁边读数每隔几秒就跳一次跟变频器载波频率对上了。解决办法是给 RTD 输入加共模扼流圈同时把采样率降到 5SPS利用 ADC 内部的数字滤波器把工频和载波频率的干扰滤掉。ADS122U04 在低采样率下内置的 sinc 滤波器抑制能力很强50Hz 和 60Hz 抑制可以做到 100dB 以上。这个技巧在 HVAC 场合特别管用因为风机水泵的变频器无处不在。4.2 UART 通信异常与数据丢包的排查方法UART 通信出问题先看波特率对不对。ADS122U04 的 UART 波特率是固定的 115200但有些批次的芯片内部振荡器有偏差实际波特率可能偏百分之二左右。STM32 这边如果也用内部振荡器两边偏差叠加可能超过百分之三通信就不可靠了。所以 STM32F042K6 最好用外部晶振8MHz 或者 16MHz 都行PLL 倍频到 48MHz这样 UART 波特率精度能到千分之一以内。数据丢包另一个原因是 DRDY 中断处理太慢。如果 STM32 在中断里做太多事情比如浮点运算、查表、串口打印中断服务程序执行时间过长下一次 DRDY 来了还没处理完数据就丢了。正确的做法是中断里只做一件事把 ADC 数据读回来存到缓冲区置一个标志位主循环看到标志位再做换算和上报。这样中断执行时间可以控制在几微秒以内。还有一点容易忽略ADS122U04 的 UART 是半双工的还是全双工的实际上它的 TX 和 RX 是分开的引脚可以全双工。但如果你用 RS485 收发器那就是半双工发送和接收要切换方向。切换时机很关键发完命令要等最后一个字节的停止位发完才能切到接收否则会把命令的回显当成数据收进来。我一般用 UART 的 TC 中断来判断发送完成在 TC 中断里切换 RS485 方向引脚。4.3 常见问题速查表现象可能原因排查方法解决措施读数始终为零激励电流未开启测基准电阻两端电压检查配置寄存器 2 的 IDAC 位读数满量程饱和PGA 增益过大计算信号幅度与满量程关系降低增益或减小激励电流温度值跳变超过 0.5 度电源纹波大或地环路示波器测电源纹波加强滤波或加隔离UART 无响应未切换到 UART 模式逻辑分析仪抓 TX 波形重新发切换命令并加延时数据偶尔丢包DRDY 中断处理超时示波器测中断执行时间中断只做数据搬运校准后仍有偏差基准电阻温漂大测量不同温度下基准电阻更换低温漂电阻多点测量串扰多路复用器切换未稳定切换后延时不足增加切换后延时这个表是我从实际项目里总结出来的每一条都对应着至少一次熬夜调试的经历。特别是基准电阻温漂这一条一开始用普通 1% 精度的电阻常温校准好了放到五十度的环境里跑两个小时读数偏了 0.3 度。后来换成 5ppm 的金属箔电阻问题消失。这个教训告诉我高精度测量里无源器件的选择跟有源器件一样重要。5. 这套方案在 HVAC 和工业场景里的扩展玩法5.1 多路温度采集与 RS485 总线组网单个测温点用一套 ADS122U04 加 STM32F042K6 有点浪费ADS122U04 本身有四路单端输入或者两路差分输入可以轮流采集多个 PT100。配置多路复用器依次切换通道每个通道采集完切换下一个循环往复。STM32 这边维护一个通道计数器DRDY 中断里根据当前通道号把数据存到对应的缓冲区。这样一套硬件可以管两到四个温度点在 HVAC 的空调箱里送风、回风、盘管、室外温度四个点刚好够用。组网方面STM32F042K6 的 UART 接一个 RS485 收发器比如 MAX485 或者 SP3485就可以挂到 RS485 总线上。RS485 是半双工总线上的设备要分时发送。我一般用 Modbus RTU 协议STM32 做从站上位机或者 PLC 做主站。Modbus 的寄存器映射把温度值放到保持寄存器里主站轮询读取。这个方案在楼宇自控里非常成熟兼容性好组态软件都支持。RS485 总线的终端电阻不能忘。总线两端各接一个 120 欧姆电阻中间设备不接。如果总线长度超过一百米或者波特率高于 19200终端电阻必须加否则信号反射会导致通信误码。我见过一个项目总线拉了三百米没加终端电阻白天通信正常晚上开灯之后干扰大了就频繁掉线。后来在两端补上电阻问题解决。5.2 低功耗设计与电池供电的可行性分析HVAC 里有些测温点不方便拉电源线比如屋顶的室外温度传感器或者管道井里的水温传感器。这时候要考虑电池供电。STM32F042K6 的低功耗模式做得不错Stop 模式下电流可以降到微安级。ADS122U04 也有单次转换模式转换完自动进入休眠电流降到纳安级。两者配合可以做到平均电流几十微安。具体做法是STM32 定时唤醒通过 UART 命令启动 ADS122U04 单次转换等 DRDY 中断读数据处理完通过无线模块或者 RS485 上报然后两者都进休眠。唤醒周期根据需求定温度变化慢一分钟一次足够了。两节 18650 锂电池容量 3000 毫安时平均电流 50 微安理论续航 60000 小时也就是将近七年。当然实际有自放电和温度影响打个对折也有三年以上。不过低功耗设计有个坑ADS122U04 从休眠唤醒到转换稳定需要时间基准电压建立、PGA 稳定都需要几百微秒。如果唤醒后立刻启动转换前几次读数是不准的。我一般唤醒后先发一个空转换命令丢弃结果再发正式转换命令。这样多花一点时间但数据可靠。5.3 固件升级与参数配置的现场维护方案工业设备装到现场之后改参数或者升级固件是个麻烦事。如果每次都要拆机接调试器维护成本太高。我的做法是在 STM32F042K6 的 Flash 里划一块区域存参数包括校准系数、Modbus 从站地址、波特率、上报周期等。通过 Modbus 的写寄存器命令可以远程修改这些参数改完存 Flash重启生效。这样现场调试人员用组态软件就能改不需要拆机。固件升级可以用 UART 的 Bootloader。STM32F042K6 出厂自带系统 Bootloader通过 BOOT0 引脚拉高进入。但现场设备封装好了BOOT0 引脚不一定引出来。所以我在应用里写了一个自定义 Bootloader通过 Modbus 或者自定义协议接收固件数据写到 Flash 的应用区写完跳转。这个方案需要仔细设计 Flash 分区和跳转逻辑但一旦做好现场升级就方便了。提示自定义 Bootloader 一定要加固件校验比如 CRC32 或者 SHA256防止传输过程中数据出错导致设备变砖。校验不通过就不跳转留在 Bootloader 里等待重新传输。6. 个人实操中的几点体会这套 ADS122U04 加 STM32F042K6 的方案我从第一个原型到现在批量出货前后改了五版硬件、三版固件。最大的体会是高精度测量里硬件和软件各占一半谁也离不开谁。硬件设计得再好固件里寄存器配错一个位读数就是垃圾固件写得再漂亮硬件地平面没处理好噪声照样让你崩溃。另一个体会是不要迷信数据手册的典型电路。数据手册上的电路是理想条件下的实际现场有各种意想不到的干扰源。我现在的习惯是每个项目都留出滤波器的位置调试的时候根据实际情况决定焊不焊、焊多大。PCB 上多留几个 0603 的焊盘不花什么钱但调试的时候能救命。最后说一个关于 PT100 选型的小技巧。市面上 PT100 有薄膜式和绕线式两种。薄膜式便宜、体积小但长期稳定性稍差适合消费级和商用 HVAC。绕线式贵一些、体积大但抗振动和长期稳定性好适合工业现场。如果你的应用环境温度经常超过一百五十度或者有强烈振动多花点钱选绕线式后期维护成本会低很多。这个账要算长远不能只看采购成本。