1. 项目背景与核心需求拆解温度监测这件事看起来简单真要做到“本地看得见、远程收得到、长期跑得稳”里面门道不少。我这次做的项目核心就是用PJ85718DM这颗温度传感芯片搭配STM32F405RG主控搭建一套同时覆盖本地显示与远程上报的温度监测系统目标场景是嵌入式设备机箱内部和 HVAC暖通空调风管/回风口的温度采集。先说为什么选这个组合。STM32F405RG 是 ST 家 F4 系列里比较经典的一颗Cortex-M4 内核带 FPU主频 168MHz192KB SRAM、1MB Flash外设资源丰富3 个 I2C、3 个 USART、2 个 CAN、USB OTG 都有。做温度监测这种“多传感器 本地交互 远程通信”的活儿它的算力和接口数量都绰绰有余而且生态成熟HAL 库、LL 库资料齐全调试起来不折腾。PJ85718DM 则是一颗数字温度传感器I2C 接口测温范围覆盖 -40℃ 到 125℃分辨率可配置典型精度在常温区间能到 ±0.5℃ 左右封装小、功耗低适合分布式布点。这个项目解决的核心问题有三个第一本地实时性——设备现场要能直接看到当前温度不能什么都依赖上位机第二远程可观测——运维人员不在现场时要能通过通信链路拿到温度数据做趋势判断和告警第三多点一致性——HVAC 场景往往要同时监测送风、回风、盘管等多个位置传感器要能挂同一条总线地址不冲突采样时序可控。适合谁来参考这份内容我觉得三类人比较对口一是做嵌入式产品开发、需要快速把温度采集跑通的工程师二是做 HVAC 控制板、楼宇自控设备的开发者需要本地 远程双通道方案三是刚接触 STM32 和 I2C 传感器、想找一个完整小项目练手的朋友。下面我会把整体设计思路、硬件连接、软件实现、参数计算、踩坑经验全部摊开讲尽量做到你照着就能复现。2. 整体方案设计与选型逻辑2.1 为什么是“本地 远程”双通道架构很多温度监测项目只做远程上报本地不留任何显示结果现场调试时特别难受——传感器有没有读到数、读数对不对全靠猜。我一开始也想过省掉本地显示直接用串口打印代替但实际装机后发现问题设备装在机柜里串口线拉出来不方便而且 HVAC 现场经常是工人师傅在调风阀他们需要抬头就能看到当前温度而不是拿笔记本连上去看。所以最终架构定成双通道本地通道STM32F405RG 通过 I2C 轮询 PJ85718DM把温度值处理后驱动本地显示可以是 OLED、段码屏或者简单的数码管同时留一个按键做阈值设置。远程通道通过 USART 转 RS485或者直接用以太网/无线模块把温度数据按固定协议上报给上位机或云平台。这样设计的好处是职责清晰本地通道保证“随时可见”远程通道保证“远程可查”两者共用同一份采样数据不会出现本地和远程读数打架的情况。2.2 PJ85718DM 的接口与地址配置考量PJ85718DM 走 I2C7 位地址通常由芯片的 ADDR 引脚电平决定常见可选地址有两档。HVAC 场景经常要挂多颗传感器比如送风、回风、盘管各一颗这时候地址就不能冲突。我的做法是每颗传感器的 ADDR 引脚单独拉到 VCC 或 GND分配不同地址在 STM32 侧维护一张“地址—位置”映射表代码里用枚举区分上电时先做一次总线扫描确认每颗传感器都在线再进入正常采样循环。这里有个细节I2C 总线上拉电阻不能省也不能随便选。PJ85718DM 在标准模式 100kHz 下上拉电阻一般取 4.7kΩ如果跑 400kHz 快速模式建议降到 2.2kΩ 左右。我实测在 400kHz、总线电容约 150pF 的情况下2.2kΩ 上拉波形干净上升沿约 300ns能满足时序要求。如果上拉太大波形会变“圆”高速下容易丢数据。2.3 STM32F405RG 的资源分配思路STM32F405RG 外设多但分配不好也会打架。我的分配方案是外设用途说明I2C1连接 PJ85718DM400kHzPB6/PB7USART2远程通信115200PA2/PA3TIM3采样定时1Hz 触发采样GPIO本地按键/显示独立分配避免复用冲突SWD调试PA13/PA14保留采样定时用 TIM3 而不是软件延时原因是软件延时在加入显示刷新和通信后会被拉长导致采样周期不稳。用硬件定时器触发采样节奏由硬件保证主循环只负责处理数据实时性好很多。3. 硬件连接与关键参数计算3.1 传感器与主控的接线细节PJ85718DM 到 STM32F405RG 的接线不复杂但有几个点必须注意VCC接 3.3V不要接 5V除非确认模块自带电平转换GND和主控共地这是最基本也最容易忘的SCL/SDA分别接 PB6/PB7同时各挂一个上拉电阻到 3.3VADDR按地址规划接 VCC 或 GND不要悬空。我见过有人把 ADDR 悬空结果地址随机漂读出来的数据时有时无排查了半天才发现是地址脚没处理。这个坑一定要避开。3.2 上拉电阻与总线电容的估算I2C 总线的上升时间公式是t_r ≈ 0.847 × R_pullup × C_bus标准模式要求 t_r ≤ 1000ns快速模式要求 t_r ≤ 300ns。假设总线电容 C_bus 150pF标准模式R_pullup ≤ 1000ns / (0.847 × 150pF) ≈ 7.8kΩ取 4.7kΩ 很安全快速模式R_pullup ≤ 300ns / (0.847 × 150pF) ≈ 2.36kΩ取 2.2kΩ 合适。如果总线上挂的传感器多电容会累加这时候要么降低速率要么减小上拉电阻但上拉太小会增加功耗需要权衡。我的经验是挂 3 颗以内、线长 30cm 以内2.2kΩ 400kHz 没问题超过 5 颗或者线长超过 50cm建议降到 100kHz上拉用 4.7kΩ。3.3 温度数据的换算与校准PJ85718DM 输出的是数字量需要按数据手册的公式换算成摄氏度。常见格式是 16 位高 12 位有效分辨率 0.0625℃。换算代码大概是这样float pj85718dm_to_celsius(uint16_t raw) { int16_t temp (int16_t)raw; return temp * 0.0625f; }但实际用的时候我发现裸换算出来的值在常温下和参考温度计差 0.3℃ 左右。这个偏差主要来自芯片自身精度和板级热耦合。我的做法是加一个单点校准在已知温度环境比如 25℃ 恒温箱下读一组值算平均偏差写进代码做补偿。校准后常温误差能压到 ±0.2℃ 以内对 HVAC 场景足够用了。4. 软件实现与核心代码拆解4.1 I2C 初始化与传感器扫描STM32F405RG 的 I2C1 初始化用 CubeMX 生成比较快但要注意时钟配置。I2C 时钟源来自 APB1168MHz 主频下 APB1 通常是 42MHz分频后要保证 I2C 时钟在 400kHz 附近。我一般用 CubeMX 直接配生成后检查一下I2C1-CR2的 FREQ 字段和CCR寄存器值。初始化完成后先做总线扫描void i2c_scan(void) { for (uint8_t addr 1; addr 128; addr) { if (HAL_I2C_IsDeviceReady(hi2c1, addr 1, 2, 10) HAL_OK) { printf(Found device at 0x%02X\n, addr); } } }这一步能快速确认传感器地址对不对、接线通不通。我习惯在正式采样前跑一次把结果打印出来心里有底。4.2 定时采样与数据滤波采样用 TIM3 触发1Hz 一次。中断里只置一个标志位实际读取放在主循环避免在中断里做 I2C 操作I2C 可能阻塞放中断里容易出问题。读回来的原始数据不能直接用要做滤波。我用的是滑动平均 限幅滑动平均窗口取 8 个点平滑随机噪声限幅判断如果新值和上一次值差超过 5℃认为是异常跳变丢弃这次数据。#define FILTER_WIN 8 static float temp_buf[FILTER_WIN]; static uint8_t buf_idx 0; float filter_temp(float new_temp) { static float last_valid 25.0f; if (fabsf(new_temp - last_valid) 5.0f) { return last_valid; // 丢弃异常值 } temp_buf[buf_idx] new_temp; buf_idx (buf_idx 1) % FILTER_WIN; float sum 0; for (int i 0; i FILTER_WIN; i) sum temp_buf[i]; last_valid sum / FILTER_WIN; return last_valid; }这套滤波在 HVAC 场景很实用因为风阀动作时温度会有短时波动限幅能避免误告警。4.3 本地显示与远程上报的协同本地显示我用的是一块 0.96 寸 OLEDI2C 接口和传感器共用 I2C1 但地址不同。显示刷新频率不用太高2Hz 足够避免占用太多总线时间。远程上报走 USART2协议我自定义了一个简单帧格式字节内容0帧头 0xAA1传感器编号2-3温度值大端0.1℃ 单位4校验和5帧尾 0x55这种格式简单、易解析上位机用 Python 或 C# 都能快速对接。上报周期我设成 5 秒一次比采样慢减少通信压力。5. 常见问题与排查技巧实录5.1 I2C 读不到数据的排查顺序这是最常见的问题我的排查顺序是先量电压VCC 是不是 3.3VGND 是不是共地再量上拉SCL/SDA 空闲时是不是高电平如果不是上拉没接好跑扫描看能不能扫到地址扫不到就查 ADDR 引脚看波形有示波器的话抓一下 SCL/SDA看时序对不对换速率400kHz 不行就降到 100kHz排除时序问题。我遇到过一回扫描能扫到地址但读数据全是 0xFF最后发现是传感器供电不足换了个 LDO 就好了。所以电源质量也要查。5.2 温度读数跳变的处理读数跳变一般三个原因电源噪声、总线干扰、滤波不够。我的处理办法电源加 100nF 10uF 去耦靠近传感器放置I2C 走线尽量短远离 PWM 或电机线软件加滑动平均和限幅。如果跳变还是大可以在传感器和主控之间加一个 I2C 缓冲器或者改用差分通信的传感器方案。5.3 远程通信丢包的应对USART 转 RS485 时丢包多半是方向控制没做好。RS485 收发切换需要 DE/RE 引脚发送前拉高发送完拉低中间要等最后一个字节发完。我一般用发送完成中断来切换而不是发完就立刻切否则最后一个字节可能被截断。另外协议里加校验和是必须的收到校验错的帧直接丢弃不要试图用错数据。6. 实操心得与扩展思路这个项目我从打样到跑稳大概花了两周其中一半时间在调 I2C 和滤波。几个心得先跑通单点再扩多点不要一上来就挂三颗传感器先一颗跑通再加第二颗问题好定位采样和通信解耦采样归采样通信归通信中间用缓冲区传递避免相互阻塞留调试口SWD 一定要留串口打印也留着现场排查全靠它们。后续扩展的话可以加 SD 卡做本地历史记录或者加无线模块做云端上报。HVAC 场景还可以把温度数据和风机状态联动做简单的闭环控制。这些都是在现有框架上叠加核心的采样和通信逻辑不用大改。我个人在实际操作中的体会是温度监测这种项目硬件是基础软件是保障但真正决定好不好用的是细节处理——上拉电阻选对、滤波参数调好、通信协议留校验这些看起来不起眼的地方往往就是稳定运行的关键。