
1. 项目背景与核心需求拆解温度监测这件事看起来简单真要做到工业级可靠、本地远程双通道、还要兼顾成本与精度里面的门道比想象中多得多。我最近刚完成一个嵌入式温度采集项目用的方案是 PJ85718DM 红外温度传感器搭配 STM32F303VE 主控目标场景是 HVAC暖通空调系统的本地与远程温度监测。这套组合在业内不算新鲜但真正把它跑通、跑稳并且把本地与远程两条数据链路都做扎实还是踩了不少坑。先说清楚这个项目到底要解决什么问题。HVAC 系统里温度监测通常分两个层面一个是本地温度也就是设备自身或者紧邻区域的温度比如出风口温度、回风温度、管道表面温度另一个是远程温度指的是通过有线或无线链路把远端传感器的数据汇聚到主控或者上位机。传统做法是用 NTC 热敏电阻或者数字温度芯片比如 DS18B20做本地采集远程则靠 RS485 或者无线模块回传。但这类方案在 HVAC 场景下有几个硬伤响应速度慢、易受电磁干扰、远距离布线成本高、多点组网麻烦。PJ85718DM 是一颗红外测温传感器支持非接触式测量I2C 接口测温范围覆盖 -40°C 到 125°C具体视配置而定精度在常温段可以做到 ±0.5°C 以内。它的优势在于不需要物理接触被测物体适合测量运动部件、带电设备或者难以贴装传感器的位置。STM32F303VE 则是 ST 家的 Cortex-M4 内核 MCU带 FPU主频 72MHz片上资源丰富有多路 I2C、SPI、USART、CAN正好适合做多传感器汇聚和远程通信的主控。这个项目适合谁参考如果你是做嵌入式硬件开发的正在找一套靠谱的温度监测方案或者你是 HVAC 行业的工程师想了解怎么把红外测温和远程数据回传整合到一起再或者你只是单纯想玩 STM32 加传感器这套组合的复杂度适中资料也相对好找。不管你是哪种下面的内容都会从选型逻辑、硬件设计、软件实现到问题排查一步步拆开讲。2. 方案选型与整体设计思路2.1 为什么选 PJ85718DM 而不是普通数字温度芯片普通数字温度芯片比如常见的 I2C 温度传感器优点是便宜、接口简单、精度也不错。但它们有一个共同限制必须接触被测物体。在 HVAC 场景里很多测点根本没法贴传感器。比如你想测风机轴承的温度传感器贴上去会影响动平衡想测管道内壁温度开孔安装又破坏密封。红外测温这时候就是刚需。PJ85718DM 的核心优势有三个。第一是非接触安装位置灵活不会干扰被测对象。第二是响应快红外测温的响应时间通常在毫秒级比 NTC 的热惯性快一个数量级适合做动态温度跟踪。第三是集成度高芯片内部集成了红外热电堆、信号调理、ADC 和 I2C 接口外围只需要少量去耦电容和光学窗口硬件设计压力小。当然它也有代价。红外测温的精度受发射率影响很大不同材料表面的发射率不一样测出来的温度会有偏差。另外如果测量距离和视场角不匹配读数也会飘。这些在后面实操部分会详细讲怎么处理。2.2 STM32F303VE 作为主控的合理性选 STM32F303VE 主要看中三点。第一是浮点运算能力红外测温原始数据需要做发射率补偿、环境温度补偿、线性化处理这些计算用 FPU 跑起来很轻松不用像 M0 那样费劲做定点优化。第二是外设资源F303VE 有 3 路 I2C、3 路 USART、2 路 SPI、1 路 CAN本地可以挂多颗 PJ85718DM远程可以走 RS485 或者 CAN 总线扩展性很好。第三是封装和引脚VE 是 100 引脚 LQFPGPIO 够多方便接显示屏、按键、报警输出这些外围。有人可能会问为什么不用 F103 或者 F407F103 没有 FPU做浮点补偿运算会吃力F407 性能过剩成本也高。F303 正好卡在中间性价比合适。而且 F303 的 ADC 是 12 位 5Msps如果以后想加模拟传感器也留了余地。2.3 本地与远程双通道的架构设计整个系统的架构可以分成三层。感知层是 PJ85718DM 红外传感器负责采集本地温度。控制层是 STM32F303VE负责数据汇聚、补偿计算、逻辑判断和通信调度。传输层负责把数据送到远程端可以用 RS485 有线方式也可以用无线模块。本地监测和远程监测的区别在于本地数据直接进 MCU实时性高采样率可以做到 10Hz 以上远程数据需要经过传输链路会有延迟而且要考虑链路可靠性和数据完整性。我的做法是本地数据走 I2C 直连远程数据通过 USART 转 RS485 差分传输波特率 115200加上 CRC 校验和重传机制保证在工业环境下的稳定性。注意RS485 总线在 HVAC 场景里很常见但布线时一定要用双绞线并且终端要加 120 欧姆匹配电阻否则长距离传输会出现反射和误码。3. 硬件设计与关键参数计算3.1 PJ85718DM 的外围电路设计要点PJ85718DM 的硬件设计不算复杂但有几个细节必须注意。电源方面芯片典型工作电压是 3.3V和 STM32 一致可以直接共用电源轨。去耦电容要靠近芯片的 VDD 引脚放置推荐 100nF 加 10uF 组合滤掉高频和低频噪声。I2C 总线上拉电阻一般取 4.7k如果总线电容较大或者走线较长可以降到 2.2k但要注意功耗。光学窗口是容易被忽略的地方。红外传感器前面需要有一个透红外的窗口普通玻璃会阻挡大部分红外辐射导致读数严重偏低。正确做法是用硅片或者专用红外透射材料做窗口如果只是做原型验证也可以直接开孔让传感器裸露但要注意防尘和防潮。芯片的视场角FOV决定了测量区域的大小。假设 FOV 是 35 度测量距离是 10cm那么测量光斑直径大约是 2 × 10 × tan(17.5°) ≈ 6.3cm。这意味着如果你要测一个小目标距离就不能太远否则光斑会覆盖到背景读数会被平均掉。实际选型时要根据被测物体的尺寸和安装距离反推需要的 FOV。3.2 STM32F303VE 最小系统与接口分配STM32F303VE 的最小系统包括晶振、复位电路、启动模式配置和调试接口。晶振用 8MHz 无源晶振配合内部 PLL 倍频到 72MHz。复位电路用 10k 上拉加 100nF 电容简单可靠。启动模式默认从 Flash 启动BOOT0 下拉到地。调试接口用 SWD只需要 SWCLK 和 SWDIO 两根线省引脚。接口分配上我用了 I2C1 挂 PJ85718DMPB6 和 PB7 做 SCL 和 SDA。USART1 做调试输出PA9 和 PA10。USART2 转 RS485PA2 和 PA3方向控制引脚用 PA1。另外留了 I2C2 给以后的扩展传感器SPI1 给显示屏预留。功能外设引脚备注红外传感器I2C1PB6/PB7400kHz 快速模式调试串口USART1PA9/PA10115200 波特率RS485 通信USART2PA2/PA3方向控制 PA1扩展传感器I2C2PB10/PB11预留显示屏SPI1PA5/PA6/PA7预留3.3 RS485 远程链路的参数计算RS485 链路的可靠性取决于几个参数。波特率和线缆长度是矛盾的波特率越高可靠传输距离越短。115200 波特率下用标准双绞线可靠距离大约在 100 到 200 米。如果距离更远要么降波特率到 9600要么加中继器。终端电阻的取值要匹配线缆特性阻抗通常双绞线是 120 欧姆。只在总线两端各加一个 120 欧姆电阻中间节点不加。如果加了多个终端电阻总线负载会过重信号幅度下降。共模电压范围也要注意。RS485 收发器的共模范围通常是 -7V 到 12V如果两端设备地电位差太大会超出范围导致通信失败。解决办法是用隔离型 RS485 收发器或者确保两端共地。4. 软件实现与核心代码解析4.1 I2C 驱动与 PJ85718DM 初始化流程PJ85718DM 的 I2C 地址通常是 0x3A 或者 0x3B具体看型号后缀。初始化流程分几步先复位芯片然后配置测量模式、发射率、环境温度补偿参数最后启动连续测量。#include stm32f3xx_hal.h #define PJ85718DM_ADDR 0x3A 1 I2C_HandleTypeDef hi2c1; uint8_t pj_init_sequence[] { 0x00, 0x01, // 复位 0x01, 0x0A, // 配置测量模式 0x02, 0x64, // 发射率设为 0.64 0x03, 0x19 // 环境温度补偿 }; void PJ85718DM_Init(void) { HAL_I2C_Master_Transmit(hi2c1, PJ85718DM_ADDR, pj_init_sequence, sizeof(pj_init_sequence), 100); HAL_Delay(10); } float PJ85718DM_ReadTemp(void) { uint8_t raw_data[2]; HAL_I2C_Master_Receive(hi2c1, PJ85718DM_ADDR, raw_data, 2, 100); int16_t raw (raw_data[0] 8) | raw_data[1]; return raw * 0.02f; // 假设分辨率 0.02°C/LSB }这段代码是简化版实际使用时要根据数据手册确认寄存器地址和分辨率。发射率设置很关键不同材料的发射率差别很大比如金属表面发射率可能只有 0.1 到 0.3而塑料和橡胶可以到 0.9 以上。如果发射率设错温度读数会偏差几十度。4.2 温度补偿算法与浮点运算优化红外测温的原始读数需要做补偿才能得到准确温度。补偿包括两部分环境温度补偿和发射率补偿。环境温度补偿是因为传感器自身的温度会影响读数芯片内部有环境温度传感器可以用它做参考。发射率补偿是把测到的辐射能量换算成真实温度。float compensate_temperature(float raw_temp, float env_temp, float emissivity) { // 简化补偿模型 float compensated raw_temp (env_temp - 25.0f) * 0.05f; compensated compensated / emissivity; return compensated; }实际补偿公式比这复杂通常要用多项式拟合或者查表法。STM32F303 有 FPU跑这些计算毫无压力单次补偿耗时不到 1 微秒。如果换成没有 FPU 的 MCU就要考虑用定点数或者查表来优化。4.3 RS485 远程通信协议设计远程通信协议我设计了一个简单的帧结构帧头2 字节 地址1 字节 命令1 字节 数据长度1 字节 数据N 字节 CRC162 字节。帧头用 0xAA 0x55方便接收端同步。地址用来区分不同节点最多支持 255 个节点。CRC16 用标准多项式 0x1021保证数据完整性。typedef struct { uint16_t header; uint8_t addr; uint8_t cmd; uint8_t len; uint8_t data[32]; uint16_t crc; } RS485_Frame; uint16_t crc16(uint8_t *data, uint16_t len) { uint16_t crc 0xFFFF; for (uint16_t i 0; i len; i) { crc ^ (uint16_t)data[i] 8; for (uint8_t j 0; j 8; j) { if (crc 0x8000) crc (crc 1) ^ 0x1021; else crc 1; } } return crc; }发送时先拉高 RS485 方向控制引脚延时一小段时间让收发器切换然后发送数据发完再拉低。接收时用中断或者 DMA收到完整帧后校验 CRC通过则处理不通过则丢弃。提示RS485 方向切换后要加延时通常 10 到 100 微秒具体看收发器的切换时间。延时不够会导致第一个字节丢失。5. 实操过程与调试记录5.1 硬件焊接与上电检查PCB 打样回来后先目视检查有没有短路或者虚焊。重点看电源部分用万用表测 3.3V 和地之间的电阻正常应该在几百欧姆以上如果接近零就是短路了。上电前先把电源限流设到 100mA防止意外烧板。上电后先测电压3.3V 应该在 ±5% 以内。然后用示波器看晶振有没有起振8MHz 正弦波幅度大约 1V 峰峰值。如果晶振不起振检查负载电容是否匹配通常 8MHz 晶振配 20pF 电容。5.2 I2C 通信调试与常见问题I2C 调试最容易遇到的问题是从机不应答。先用逻辑分析仪抓波形看 SCL 和 SDA 有没有信号。如果 SCL 有信号但 SDA 一直高说明从机没响应可能是地址错了或者芯片没上电。如果 SDA 被拉低不放说明总线死锁了需要手动发送 9 个时钟脉冲解锁。PJ85718DM 的 I2C 地址要确认清楚有些型号是 0x3A有些是 0x3B差一位就通不了。另外上拉电阻不能省我见过有人直接接 MCU 内部上拉结果总线电容一大就通信失败。5.3 红外测温精度校准方法红外测温的精度校准分两步。先用黑体炉或者已知温度的标准源做参考把发射率设成 1.0测一组数据算出偏差。然后根据被测物体的实际发射率调整参数再测一组验证偏差是否在可接受范围内。如果没有黑体炉也可以用冰水混合物0°C和沸水100°C注意海拔影响做粗略校准。把传感器对准目标距离固定记录读数然后调整补偿系数。校准后精度通常能做到 ±1°C 以内好的话可以到 ±0.5°C。校准点标准温度实测温度偏差调整后偏差冰水0°C1.2°C1.2°C0.3°C沸水100°C98.5°C-1.5°C-0.4°C室温25°C25.3°C0.3°C0.1°C5.4 远程链路联调与抗干扰测试RS485 联调时先用短距离1 米测试确认通信正常。然后逐步加长线缆观察误码率。我在 50 米双绞线上跑 115200 波特率误码率几乎为零到 150 米时开始出现偶发误码降到 57600 后恢复正常。抗干扰测试用变频器做干扰源把线缆靠近变频器输出线。结果发现不加屏蔽层时误码率明显上升加屏蔽层并单端接地后误码率降到可接受范围。注意屏蔽层只能一端接地两端接地会形成地环路反而引入干扰。6. 常见问题与排查技巧实录6.1 温度读数跳动大怎么办读数跳动通常有三个原因。电源噪声是最常见的用示波器看 3.3V 电源纹波如果超过 50mV就要加滤波电容或者换 LDO。I2C 通信误码也会导致读数异常可以在软件里加多次采样取中值或者加 CRC 校验。被测物体发射率不稳定比如表面有油污或者氧化层会导致读数漂移这种情况只能清洁表面或者换测量位置。6.2 RS485 通信时好时坏怎么排查先确认波特率是否匹配两端必须一致。然后检查终端电阻用万用表测 A 和 B 之间的电阻应该是 60 欧姆左右两个 120 欧姆并联。如果偏差太大说明终端电阻有问题。再检查共模电压用万用表测 A 对地和 B 对地的电压应该在 0 到 5V 之间超出范围就要加隔离或者共地。6.3 红外传感器读数偏低或偏高读数系统性偏低通常是发射率设高了。比如金属表面实际发射率是 0.2你设成 0.9读数就会偏低很多。反过来发射率设低了读数会偏高。解决办法是查材料发射率表或者用接触式温度计做对比校准。读数随机偏高可能是视场内有热源干扰。比如传感器旁边有个发热的电源模块它的红外辐射会被传感器接收到。解决办法是加遮光罩或者调整安装角度。6.4 常见问题速查表现象可能原因排查方法解决措施I2C 无应答地址错误/未上电逻辑分析仪抓波形确认地址和电源温度跳动大电源噪声/通信误码示波器测纹波加滤波/多次采样RS485 误码波特率不匹配/终端电阻测电阻和波形统一波特率/加终端电阻读数偏低发射率设高对比接触式温度计调整发射率参数读数偏高视场有热源遮挡测试加遮光罩/调整角度实操心得调试红外测温时先用一个已知温度的物体做参考把发射率调准再去测实际目标。不要一上来就测复杂表面否则会陷入反复调参的泥潭。7. 系统优化与扩展思路7.1 低功耗设计考虑如果设备是电池供电低功耗就很重要。STM32F303 支持多种低功耗模式待机模式下电流可以降到微安级。PJ85718DM 也有休眠模式不测量时电流只有几微安。我的做法是让 MCU 定时唤醒采集一次温度然后通过 RS485 发送发完立刻进入待机。这样平均功耗可以做到毫安级用一节 18650 电池能撑几个月。7.2 多点组网与地址分配RS485 总线支持多点组网最多可以挂 32 个标准负载或者 128 个低负载节点。每个节点需要一个唯一地址可以用拨码开关设置也可以在软件里动态分配。动态分配的好处是免去手动设置但需要一个分配协议复杂度高一些。小规模组网用拨码开关就够了。7.3 数据上云与远程监控如果需要把数据传到云端可以在 RS485 总线的一端接一个网关网关把数据转成 MQTT 或者 HTTP 协议再通过以太网或者无线模块上传。网关可以用树莓派或者 ESP32 做成本低开发快。数据上云后可以做趋势分析、报警推送、远程配置适合大型 HVAC 系统的集中监控。7.4 固件升级与维护固件升级可以通过 RS485 做 IAP在应用编程不需要拆机。STM32F303 的 Flash 支持自编程可以划分一个 Bootloader 区和一个应用区。Bootloader 负责接收新固件并写入应用区应用区负责正常运行。升级时先发命令让设备进入 Bootloader然后分块传输固件每块校验 CRC全部收完后跳转到新固件。这套方案我在实际项目中跑了大半年稳定性没问题。温度监测的精度和响应速度都满足 HVAC 系统的要求远程通信在 100 米以内的双绞线上误码率极低。如果你也在做类似的项目建议先把 I2C 和 RS485 的底层驱动调通再往上叠业务逻辑这样排查问题会容易很多。另外红外测温的发射率校准一定要认真做这一步偷懒后面数据全是错的。