STM32与PJ85718DM温度监测系统实战:I2C本地采集+RS485远程汇聚

📅 发布时间:2026/10/22 6:42:17
STM32与PJ85718DM温度监测系统实战:I2C本地采集+RS485远程汇聚
搞嵌入式或者暖通控制的朋友都清楚温度监测看起来是最不起眼的功能但真正要把“温度”测准、传稳、在本地和远程都可靠往往比想象中多花两三倍时间。这个项目里我用了 PJ85718DM 温度传感器搭配 STM32F415ZG 主控完成了一套覆盖本地直连和远程汇聚的温度监测系统用在嵌入式设备与 HVAC暖通空调的现场调试中。文里会直接讲硬件架构、驱动编写、滤波处理、远程通信和现场排障以工程向的内容为主适合正在做温控类产品或楼宇自控项目的同行参考。整套系统的核心就一句话本地用 I2C 直连读 PJ85718DM远程通过 RS485 总线把多个温度节点汇聚回来由 STM32F415ZG 统一处理、校准、上抛。就这么一个看起来简单的架构实际调起来踩了不少坑。下面我把完整的方案和细节拆开讲所有经验都来自真实调试记录可以直接抄作业。1. 项目需求拆解与总体方案1.1 本地温度与远程温度的本质差别很多人把“本地温度”和“远程温度”混为一谈觉得都是读个传感器没什么区别。实际从工程设计角度这是两套完全不同的链路难点也完全不同。本地温度指的是传感器就在主控附近比如板载温度、机箱内温度、控制器附近的回风温度。这类温度传感的特点是走线短、信号完整性好、电气噪声相对较小主要挑战在传感器本身的精度和自热控制上。远程温度则指传感器部署在几十米甚至上百米之外比如空调机组的送风管道、楼宇各楼层的风管末端、冷却水管表面等这时候主要挑战变成了通信距离、总线负载、抗干扰和节点供电。HVAC 场景里的远程温度还有一个特点它不是单点测量而是多点、分散、需要统一汇聚的。所以方案必须考虑“多节点组网”的问题不是简单拉一根线到一个传感器就完事。我在设计时把本地通道和远程通道分开处理本地直接挂 I2C远程用 RS485 网关汇聚这样两边都能做到最优。1.2 为什么是 PJ85718DM STM32F415ZG先说传感器。PJ85718DM 是一颗 I2C 接口的数字温度传感器量程覆盖 -55℃ 到 125℃在 -10℃ 到 85℃ 范围内的典型精度能做到 ±0.5℃12 位分辨率下最小温度分辨率是 0.0625℃。这个精度和量程放在 HVAC 的现场监测里完全够用不管是回风温度、送风温度还是水管表面温度都能覆盖到。相比模拟热敏电阻方案数字传感器最大的优势是信号链短。热敏电阻方案从分压电路到运放再到 ADC 样样都要排查任何一个环节的基准漂移都会反映到温度值上。PJ85718DM 直接输出数字量MCU 通过 I2C 读寄存器就行抗干扰和一致性都好了很多。主控选 STM32F415ZG 是因为这颗料在资源上非常宽裕。Cortex-M4 内核带 FPU主频能到 168MHzFlash 1MBSRAM 192KB。这么多资源用在温度采集上看起来有点“杀鸡用牛刀”但实际做 HVAC 控制器时主控往往还要同时跑风机控制、阀门 PID、人机交互、通信协议栈和报警逻辑。温度采集只是其中一个模块选一颗性能充足的主控后面扩展功能时不会捉襟见肘。而且 F4 系列的多路 I2C、多路 USART、硬件 CRC 模块对这次方案里 I2C 采集和 RS485 轮询正好都用得上。1.3 整体架构直连与总线网关并存这套系统的架构分三层。第一层是本地温度采集STM32F415ZG 直接通过 I2C1 接口读取一颗或者多颗 PJ85718DM用于监测主控板附近的温度比如进风温度、控制柜内温度。第二层是远程温度汇聚每个远程测温点由一颗小节点板完成节点板上也是 PJ85718DM但前端多了一片 RS485 收发器多个节点用一条双绞线串联到主控板的 RS485 接口。第三层是数据处理与上传STM32F415ZG 把本地、远程所有温度统一校准之后再通过以太网、RS485 或者 CAN 转发给上层 BA 系统或者触摸屏。这样的分层的核心原因是通信距离匹配。I2C 在板级通信非常好用但抗干扰能力弱、走线长了波形就变形所以在远程场景坚决不用 I2C 硬拉几十米而是就近把温度值转成 RS485 信号传回。每个节点板实际上是一个小网关把传感器数据远程化。如果后面现场需要增加测温点也只需要在总线上再挂一个节点主控侧软件改一下节点数量参数就行扩展性很好。2. 硬件连接的几个关键点2.1 PJ85718DM 的接口与时序基础PJ85718DM 的引脚不多典型接法是四线VDD、GND、SDA、SCL供电范围通常在 2.7V 到 5.5V所以 3.3V 和 5V 系统都能直接用。我在这套系统里统一用 3.3V 供电因为 STM32F415ZG 的 GPIO 也是 3.3V省去电平转换电路直连更省事。上电之后传感器默认是待机模式需要往配置寄存器写命令让它开始转换再等待转换完成之后读温度寄存器。转换时间取决于分辨率配置如果用 12 位分辨率典型转换时间在 300ms 到 750ms 之间分辨率越高转换越慢。温度寄存器是 16 位带符号数低 4 位用于扩展分辨率读取之后右移 4 位再乘以 0.0625就是实际的摄氏温度。这个公式我用了一年多没有遇到过数值跳变的问题很稳定。提示PJ85718DM 的器件地址和寄存器地址可以通过数据手册确认不同批次可能支持不同的地址配置引脚。硬件设计时最好留出地址电阻的焊盘方便现场扩展多个传感器时修改地址。2.2 本地 I2C 设计的电阻与保护本地 I2C 虽然简单但几个细节处理不好照样出问题。首先是上拉电阻3.3V 供电、单板布局情况下用 4.7kΩ 上拉电阻通常没问题。但如果 I2C 线上并联的传感器多了或者走线稍微长一点就需要把上拉电阻改小到 2.2kΩ 甚至 1kΩ否则信号上升沿太慢I2C 通信会出现随机失败。我在设计本地板卡时把 I2C1 总线上挂了两颗 PJ85718DM走线长度控制在 20cm 以内用 4.7kΩ 上拉实测波形很干净。但如果总线长度超过 30cm 或者线上挂到四颗以上建议直接用 1kΩ 上拉并且把 I2C 速率从 400kHz 降到 100kHz。工程师通常喜欢追求高速率在温度采集这种场景里完全没必要100kHz 足够满足采样需求换来的是更好的兼容性和稳定性。ESD 保护也不能省。SDA 和 SCL 线上各加一颗 TVS 管到地型号选结电容小的避免影响信号完整性。这块板子在实验室里怎么测都行一上现场传感器线缆被维护人员反复插拔静电打进来就是一颗芯片报废加了 TVS 之后再没出过这类问题。2.3 远程节点怎么接才稳远程节点板的硬件设计和本地板有几点不同。第一是必须加 RS485 收发器我用的是一颗常规的半双工 RS485 芯片A/B 线上各串一个 10Ω 电阻再并一个 120Ω 终端匹配电阻。终端电阻的位置应该在总线最远端的那个节点上不是每个节点都加否则总线负载太重通信距离反而缩短。第二是供电问题。远程节点如果直接从主控板拉 12V 或 24V 供电现场经常出现地电位差的问题。两个节点之间只要地电位差超过收发器的共模范围通信就会异常。我处理的方式是远程节点板内部用隔离 DC-DC 给传感器和 RS485 收发器供电RS485 收发器的 A/B 侧再加 TVS 管。这套组合应付 50 米左右的双绞线走线实测没有出现过因电位差导致的通信失败。还有一点是 RS485 的方向控制。半双工通信中MCU 的 DE/RE 引脚要一起控制发送时置高接收时置低。这个控制时序如果切换太快最后一个字符还没发完就切到接收帧就被截断了。我在软件里做了发送完成中断延时发送完最后一个字节后再等一个字符时间然后才拉低 DE这个细节后面在固件部分还会细说。3. 固件实现与数据处理3.1 驱动初始化与温度读取固件这块我建议直接用 STM32 的标准外设库或者 HAL 库把 I2C1 初始化成 100kHz 主机模式。初始化代码不复杂但要注意开启 I2C 的时钟超时功能。实际调试中 I2C 总线被 SDA 拉低导致死锁的情况很常见如果不做超时保护程序会一直卡在等待事件完成整个系统跟着停摆这对 HVAC 控制器来说是不可接受的。驱动层我封装了一个读寄存器函数传入寄存器地址和长度底层通过 HAL 库的 I2C 读接口完成。核心代码大概长这样#define PJ85718DM_ADDR (0x48 1) static uint8_t pj85718dm_read_reg(uint8_t reg, uint8_t *buf, uint8_t len) { if (HAL_I2C_Mem_Read(hi2c1, PJ85718DM_ADDR, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 100) ! HAL_OK) { return 0; } return 1; }读取温度时连续读两个寄存器组合成 16 位数据然后转成浮点温度static float pj85718dm_read_temp(void) { uint8_t buf[2]; int16_t raw; if (!pj85718dm_read_reg(0x00, buf, 2)) { return TEMP_INVALID; } raw (int16_t)((buf[0] 8) | buf[1]); return (float)raw * 0.0625f; }这里有个细节温度寄存器的高字节在前还是低字节在前一定要看数据手册。不同厂商的习惯不一样搞反了读出来的温度会完全不对。比如实际 25℃翻转字节顺序后可能变成 -40℃ 甚至更离谱排查一整天可能就错在这一行代码上。3.2 温度数值与滤波算法读回原始温度之后不能直接用。在实际现场电磁干扰、传感器自身噪声、继电器吸合瞬间的电压跌落都会反映到温度值上。我见过最典型的情况是传感器读出来的温度在 20℃ 到 25℃ 之间疯狂跳动就是没做滤波。对于 HVAC 这种温度变化缓慢的场景一阶低通滤波已经足够。公式很简单filtered filtered alpha * (new_temp - filtered);alpha 决定了滤波的平滑程度取值范围 0 到 1alpha 越大响应越快、滤波越弱。在 HVAC 里我一般取 0.3 到 0.5对应 1 到 2 秒的采样周期能比较有效地抑制噪声同时温度控制的响应速度也不会太慢。除了低通滤波我还要做一个异常值剔除。温度是物理量正常情况下不可能在 100ms 内跳变 10℃。所以代码里保留上一次的有效值如果新读到的温度与上一次的差值超过 3℃就判定为异常数据直接丢弃不参与滤波。这样处理之后即使现场偶尔有强干扰导致读错也不会把错误的温度值送进控制逻辑里。注意异常值剔除的阈值要结合具体场景设置差得太小会把正常快速升温丢掉差得太大又起不到剔除作用。以 HVAC 来说3℃ 是比较合理的折中值。3.3 多点校准与误差补偿PJ85718DM 这类传感器出厂的时候精度已经标定过但在高精度要求的 HVAC 应用里我强烈建议做一次系统级校准。因为传感器误差和 MCU 的电压基准、PCB 布局热阻都有关系出厂精度只能保证传感器本身无法保证最终整个测温链路的系统精度。校准方法很简单用恒温槽或者冰水混合物作为基准把传感器探头放进去稳定之后记录读到的温度值。单点校准可以校正偏移误差公式为calibrated_temp raw_temp - offset;其中 offset 就是实测温度与标准温度之间的差值。如果现场要求更高可以做两点校准在低温和高温两个点各记录一次偏差然后用线性插值修正中间区间的误差calibrated_temp raw_temp * k b;两点校准能同时修正增益误差和零偏误差效果比单点好很多。实际项目中我把四路远程节点的温度误差控制在 ±0.2℃ 以内这个精度在楼宇自控领域已经很够用了。3.4 远程节点轮询状态机设计远程 RS485 总线的温度读取不能裸奔我写了一个简单的状态机让主控按地址逐个轮询。状态机包含几个状态空闲、发送查询帧、等待响应、超时重发、错误处理。每个节点分配一个地址从 1 开始编号地址通过节点板上的拨码开关设置。轮询周期看现场要求一般 2 秒轮询一圈 16 个节点足够温度变化没那么快。如果某个节点连续 3 个周期都没有响应就标记该节点离线同时保留最近一次的有效温度值避免上层系统拿到无效数据。这时候我看后台日志能直接从轮询状态码判断是哪个节点出了故障不用拿万用表到现场一个个量。4. 远程通信设计方案4.1 为什么远程不建议直接拉 I2C很多初学者会把远程传感器直接通过长导线接到 STM32 的 I2C 引脚上一开始距离短时没问题等到线拉到十几米以上问题就全出来了。I2C 的开漏结构决定了它依靠上拉电阻驱动总线总线电容越大信号上升沿越慢最后波形变成梯形数据传输直接乱套。我见过一次现场把 I2C 拉到 15 米结果传感器时不时读不到数据用示波器一看SCL 上升沿慢得像爬坡I2C 协议对时序有明确要求这种波形能稳定工作才奇怪。所以我后来定了硬性规矩I2C 只板内使用传感器引脚到 MCU 引脚最多不超过 30cm远程一律走 RS485。RS485 是差分信号两条线互为参考抗共模干扰能力比单端信号强得多。双绞线传输 50 米、甚至 100 米都没有压力而且在 HVAC 现场RS485 是楼宇自控的老熟人后期接入 BA 系统也非常顺理成章。4.2 通信帧格式与会话过程远程节点上报的帧格式要自己定清楚保证可靠性和可扩展性。我用的帧结构是typedef struct { uint8_t head0; // 0xAA uint8_t head1; // 0x55 uint8_t addr; // 节点地址 uint8_t cmd; // 命令字 uint8_t len; // 数据长度 uint8_t data[8]; // 数据区 uint16_t crc16; // CRC16 校验 } temp_frame_t;帧头固定为 0xAA 0x55接收方只在收到这两个字节后才开始解析一帧数据避免总线上的杂波导致数据错位。CRC16 校验覆盖从地址到数据区的所有字节任何一个比特错误都能被发现并丢弃整帧这是 RS485 通信最基础的可靠性保障。查询流程是主控发查询帧命令字为 0x01数据区为空地址为远程节点地址。远程节点收到查询后把当前温度值填入数据区回复一帧。温度值用 int16 表示单位是 0.01℃这样 25.5℃ 就编码为 2550既保精度又省空间。发送完查询帧后主控启动一个 200ms 超时定时器。如果超时未收到响应重发一次连续重发三次仍无响应标记该节点离线。这个流程简单但实用现场排障时我能清晰地确定是链路问题、节点供电问题还是节点程序问题。4.3 RS485 方向切换与发送时序RS485 半双工通信的方向切换是一个高频踩坑点。发送数据时需要把 DE 引脚拉高发送完成后不能再立即切换回接收状态必须等最后一个停止位完全从总线上发出去。如果切早了帧尾被截断对端收不到完整帧通信成功率直接下降一个数量级。我处理的方法是发送最后一个字节之后再延时一个字节的发送时间然后才把 DE 拉低。比如波特率 9600一个字节大约是 1.04ms我延时 1.5ms 再切换留足余量。在代码里这样实现DE_RE_High(); HAL_UART_Transmit(huart2, (uint8_t *)tx_frame, sizeof(tx_frame), 100); delay_us(1500); DE_RE_Low();如果用的是 HAL_UART_Transmit 阻塞模式函数返回时 DMA 或者外设可能还没把移位寄存器里的最后一位发完。我建议直接用发送完成中断或者在发送结束后延时等待两三百微秒到 1.5 毫秒都可以关键是确保总线完全空闲之后再改变方向。5. HVAC 现场的特殊问题5.1 传感器装在哪决定了读数是 0 分还是 100 分硬件和固件都可靠了传感器安装位置就成了决定系统成败的最后一块拼图。HVAC 里不同温度测量点的安装要求完全不同。回风温度传感器应该装在回风口内、过滤网之后要避开回风死角不然测到的温度不具代表性。送风温度传感器通常装在送风管内准确的位置应该在气流混合充分、管道直管段足够长的地方避免装在弯头、阀门等涡流区域。管道温度传感器要保证感温部分与管壁有良好的热接触我通常会在安装时涂一层导热硅脂再在外面包保温棉防止环境温度干扰读数。室外温度传感器要注意防雨防晒但不能放在阳光直射处否则测的是太阳辐射温度而不仅仅是空气温度。我还遇到过传感器离变频器太近导致读数持续偏高的情况那是传感器被周围发热器件影响不是传感器本身的问题。这种问题软件补不了只有改安装位置或者加隔热片才能解决。5.2 干扰、结露与线缆布局HVAC 现场是电磁干扰的重灾区。风机电机、变频器、接触器、电磁阀每一个动作都可能产生强烈的电磁噪声。传感器线缆和 RS485 总线必须远离动力电缆最少保持 30cm 以上的距离而且一定要用屏蔽双绞线屏蔽层单端接地。线缆一旦与动力电缆平行走线哪怕只有 1 米长共走线槽干扰都可能让人头疼。我遇到过 RS485 通信在风机启动时瞬间失败的情况排查了两天才发现是节点线缆和风机动力线绑在同一个线槽里。把线缆重新走了一个独立的线槽之后问题彻底消失。结露的问题是 HVAC 特有的冷表面上的传感器可能结露水汽可能导致测量偏差甚至短路。室内盘管温度传感器在夏季接近 7℃ 供水温度如果现场湿度大传感器探头上会凝结水滴。解决方案是选用带防潮涂层的传感器或者给探头加个密封护套探头与管壁之间涂导热硅脂但护套要保持密闭。这个细节看起来小处理不好一整个夏天系统都在误报。5.3 采样周期与系统响应速度的权衡HVAC 系统的热惯性决定了温度变化不会很快。送风温度调整后风管末端的温度可能要几秒甚至几十秒才会发生变化。所以采样周期没必要设得很短1 秒已经算快的常见的是 2 到 5 秒采一次。但采样周期也不是越慢越好。如果和上层 PID 控制配合采样周期太长会让控制器产生滞后温度震荡起来很难看。我的经验是正常温度监测用 2 秒周期参与控制回路的温度点用 1 秒周期并且滤波参数要匹配这个周期。比如周期从 2 秒改成 1 秒后alpha 要相应调大一点否则滤波后的温度响应会过于迟钝。6. 常见问题排查速查表现场调试和后期运维中我把遇到过的典型问题和排查方法整理成一个表遇到问题先按表排查效率会高很多。故障现象可能原因排查方法本地读不到温度I2C 地址错误、SDA/SCL 接反用扫描程序确认总线上所有地址温度值跳动剧烈未做低通滤波或滤波参数过小增加一阶低通滤波适当调大 alpha温度读数固定为 0寄存器读取失败、未启动转换检查初始化时序、转换等待时间远程节点无响应地址冲突、波特率不匹配、RS485 方向切换异常逐项检查节点地址、统一波特率、示波器看 A/B 波形RS485 通信偶发失败无终端电阻或终端电阻过多确认最远端节点有一个 120Ω 终端电阻现场风机启动后温度异常线缆与动力电缆近距离并行走线重新走线屏蔽层单端接地传感器读数整体偏高传感器自热、离发热元件太近检查安装位置必要时加隔热片管道温度波动滞后严重探头与管壁接触不良、缺少导热膏重涂导热硅脂确认探头固定牢靠远程节点离线但恢复后数值跳变通信异常期间保留旧值失真离线恢复后先连续采 5 次并取中值这里最容易被忽视的是 RS485 的终端电阻和屏蔽层接地。很多人只在实验室里测试距离短、干扰小终端电阻不接也能通一到现场就原形毕露。我的建议是现场布线时直接按标准做省下后期排查的精力。还有一个排查技巧用示波器看 RS485 的 A/B 线波形。静止状态下的差分电压应该在 ±2V 以上如果幅度差、波形歪线缆问题或者终端电阻问题基本就实锤了。波形干净但通信还是失败的再去查帧格式和波特率误差。7. 最终调试中的实战经验7.1 一次完整的现场温度校准流程项目联调阶段做一次完整的温度校准非常必要。我把四路远程温度节点和两路本地温度放在同一个恒温槽里槽内温度设定在 25℃稳定后记录每一路读数。然后改变恒温槽温度为 45℃再次记录读数。两次记录下来的偏差都不一样说明每一路都有各自的偏移和增益误差。我用两点校准公式给每一路单独计算 k 和 b烧录到 STM32F415ZG 的 Flash 参数区里。净室复测时六路温度读数与恒温槽标准温度的偏差都控制在 ±0.2℃ 以内这个精度在 HVAC 控制里非常舒服了。要注意校准参数区不能和程序代码放同一个扇区最好单独划出一块 Flash 区域用于存储每路校准值方便后续现场.读改写。而且写 Flash 时要先擦后写注意掉电保护不然中途掉电整块参数区就变成 0xFF 或者 0x00现场恢复很麻烦。7.2 固件升级与现场维护的细节STM32F415ZG 的 1MB Flash 跑这个项目绰绰有余我用 IAP 方式做了远程升级功能。Bootloader 放在 Flash 起始地址应用程序从偏移地址启动。远程节点升级和主控升级分开处理这样现场维护时不用爬到吊顶里去拆传感器节点。升级的稳定性是重点。我用固件分块 CRC32 校验的方式先接收完整个固件镜像到外部存储校验通过后再写入 Flash。万一传输过程中断也不会破坏原有的固件重启还能回到旧版本继续运行。这套方案在 HVAC 项目里非常重要因为现场设备往往分布在楼层各个角落一次远程升级失败如果不影响旧程序运行后期维护成本能省一大截。7.3 几次调试跑下来的一些个人体会做这套系统前后有半年多最大的体会是温度监测项目的问题往往不在温度传感器本身而是在通信链路和安装工艺上。传感器读温度很少有技术含量特别高的难点最怕的是线缆布局、供电隔离、RS485 方向切换那种不起眼的问题它们平时不烧程序一爆发就让整个系统看起来像“彻底坏了”排查起来极其消耗精力。另外一点是软件上务必留好日志记录。我在主控里记录每一路温度的原始值、滤波值、校准参数和 RS485 轮询状态上位机可以直接拉到日志文件。后期做故障分析时这些历史数据能帮人从时间维度看温度的变化轨迹往往能直接定位到干扰事件发生的具体时刻排查效率完全不一样。最后再分享一个小技巧HVAC 现场温度监测传感器探头别买太便宜的安装工艺比传感器品牌更重要。探头装配到位、导热膏抹好、线缆走线规范哪怕一颗中等精度的传感器也能稳定工作很多年安装敷衍的话再贵的传感器也会被现场环境“教做人”。做完这套系统之后再用同型号器件做别的场景我每次都会把布线和安装规范放在和硬件设计同等重要的位置。这也是这套方案能保持稳定运行最核心的经验。