基于PJ85718DM与STM32F405RG的嵌入式温度监测系统设计与实现

📅 发布时间:2026/10/10 11:13:56
基于PJ85718DM与STM32F405RG的嵌入式温度监测系统设计与实现
1. 项目缘起与整体设计思路嵌入式温度监测这个方向看起来简单实际上坑特别多。我最早接触这类需求是在一个 HVAC 控制器的改造项目里当时客户的要求很朴素本地要能看到实时温度远程也要能拿到数据精度要够成本要低还得稳定跑个三五年不出毛病。听起来不难对吧但真正动手之后你会发现从传感器选型到信号链设计从本地显示到远程通信每一个环节都有取舍。这个项目用的是 PJ85718DM 搭配 STM32F405RG 的组合。先说说为什么选这两个核心器件。PJ85718DM 是一颗带 I2C 接口的数字温度传感器封装小巧典型精度在 ±0.5°C 以内工作电压范围宽非常适合嵌入式场景。STM32F405RG 则是 ST 家 F4 系列里性价比很高的一颗 MCUCortex-M4 内核带浮点单元168MHz 主频1MB Flash192KB SRAM外设资源丰富I2C、UART、SPI、CAN 一应俱全。这两个搭在一起一个负责精准采温一个负责数据处理和通信调度分工明确。整体设计思路是这样的PJ85718DM 通过 I2C 总线挂在 STM32F405RG 下面MCU 周期性读取温度数据经过滤波和校准之后一路送到本地显示模块比如 OLED 或段码屏另一路通过远程通信接口RS485 或有线以太网上传到上位机或云端网关。整个系统需要解决的核心问题包括I2C 通信的稳定性、温度数据的精度校准、本地显示的刷新策略、远程传输的协议设计以及整机的低功耗和抗干扰能力。为什么不用模拟传感器加 ADC 的方案因为数字传感器省去了信号调理电路出厂已经校准过一致性好而且 I2C 总线可以挂多个器件扩展方便。对于 HVAC 这种需要多点测温的场景数字方案在布线和维护上的优势非常明显。当然数字传感器也不是没有缺点比如 I2C 总线在长距离传输时容易受干扰这就需要我们在 PCB 布局和线缆屏蔽上多花心思。这个项目适合谁参考我觉得三类人可以看看一是刚接触嵌入式传感器开发的朋友可以把它当作一个完整的练手项目二是做 HVAC 或工业控制的工程师里面关于抗干扰和远程通信的部分应该有帮助三是想了解 I2C 通信实操细节的开发者我会把踩过的坑都写出来。2. 核心器件解析与选型考量2.1 PJ85718DM 温度传感器的关键特性PJ85718DM 这颗传感器我实际用下来最大的感受就是“省心”。它是数字输出不需要外部 ADC直接通过 I2C 读寄存器就能拿到温度值。分辨率可以配置最高能到 0.0625°C虽然实际精度达不到这么细但在 HVAC 场景里完全够用了。测温范围覆盖 -40°C 到 125°C覆盖了绝大多数室内外环境监测的需求。它的 I2C 地址可以通过引脚配置这意味着同一条总线上可以挂多颗传感器而不会冲突。这一点在多区域温度监测里特别有用比如一个 HVAC 系统需要同时监测回风、送风、室外三个点的温度挂三颗 PJ85718DM 就行地址分别设成不同的值MCU 轮流读取。还有一个细节值得注意这颗传感器内部有可编程的报警功能。你可以设定上限和下限阈值当温度超出范围时它的报警引脚会拉低可以直接接到 MCU 的外部中断引脚上。这样就不需要 MCU 一直轮询只在异常时响应省 CPU 也省功耗。我在项目里就用了这个功能来做超温报警响应速度比纯轮询快很多。2.2 STM32F405RG 作为主控的优势STM32F405RG 这颗 MCU 在嵌入式圈子里口碑很好我用它做过好几个项目稳定性没得说。168MHz 的主频对于温度监测这种任务来说绰绰有余甚至有点大材小用。但为什么还是选它主要是看中了它的外设资源和浮点运算能力。温度数据虽然不需要复杂的数学运算但如果你要做滑动平均滤波、多点校准曲线拟合有硬件浮点单元会轻松很多。另外F405RG 的 I2C 外设支持硬件 CRC 和 SMBus 模式在干扰环境下比软件模拟 I2C 可靠得多。我试过用软件模拟 I2C 读这颗传感器在电机干扰大的场合偶尔会出现数据错位换成硬件 I2C 之后就没再出现过。它的 UART 和 CAN 外设也很实用。远程通信如果走 RS485直接用 UART 加一个收发器就行如果走 CAN 总线F405RG 自带 CAN 控制器加个收发器就能用。这种灵活性让同一个硬件平台可以适配不同的现场通信需求不用重新画板子。2.3 本地与远程双通道的架构设计本地和远程这两个通道听起来只是“显示”和“上传”的区别但在设计上要考虑的东西完全不一样。本地显示要求实时性高刷新率至少 2Hz 以上人眼看起来才不卡顿远程传输则更看重可靠性和协议兼容性刷新率可以低一些但数据不能丢。我的做法是在 MCU 内部维护一个温度数据结构本地显示和远程上传都从这个结构里取数据。本地显示走的是 I2C 接口的 OLED 屏刷新周期 200ms远程上传走 RS485每 1 秒发送一次数据帧。两个任务用不同的定时器触发互不干扰。这样即使远程通信出现阻塞本地显示也不会卡住。注意本地显示和远程通信如果共用一条 I2C 或 SPI 总线一定要做好总线仲裁和超时处理否则一个设备卡死会拖垮整个系统。3. 硬件连接与信号链实操要点3.1 I2C 总线布线规范与上拉电阻计算I2C 总线的布线是这个项目里最容易出问题的地方。我见过太多人因为上拉电阻选错或者走线太长导致通信失败。先说上拉电阻的计算标准模式下 I2C 总线速率 100kHz快速模式 400kHz。PJ85718DM 支持快速模式所以我一般跑 400kHz。上拉电阻的取值取决于总线电容和上升时间要求。总线电容包括 PCB 走线电容、引脚电容和线缆电容经验值大约是每厘米走线 1pF 左右。假设总线电容是 200pF快速模式下上升时间要求小于 300ns根据公式 R t / (0.8473 × C)算下来 R 大约是 1.8kΩ。但实际取值还要考虑功耗太小了静态电流大。我一般用 2.2kΩ 到 4.7kΩ 之间实测 2.2kΩ 在大多数场景下都能稳定工作。PCB 走线方面SDA 和 SCL 要尽量平行走长度不要超过 30cm。如果传感器和 MCU 不在同一块板上中间用排线连接的话一定要在传感器端加上拉电阻不要只在 MCU 端加。因为排线的电容比较大单端上拉会导致上升沿变缓通信误码率升高。3.2 电源滤波与去耦电容配置温度传感器对电源噪声很敏感尤其是 PJ85718DM 这种高精度器件。我在传感器 VCC 引脚旁边放了两个电容一个 100nF 的陶瓷电容紧贴引脚负责高频去耦一个 10μF 的钽电容放在附近负责低频滤波。这两个电容的接地端要尽量靠近传感器的 GND 引脚回路面积越小越好。MCU 这边的电源也要处理好。STM32F405RG 的每个 VDD 引脚都要配 100nF 去耦电容VDDA 引脚额外加一个 1μF 的电容。如果系统里有继电器或电机这类大功率负载建议给 MCU 和传感器单独用一路 LDO 供电不要和负载共用电源。我之前有个项目就是因为传感器和继电器共用 5V 电源继电器一吸合温度读数就跳变后来加了独立 LDO 才解决。3.3 远程通信接口的硬件防护远程通信走 RS485 的话硬件防护不能省。我在 A/B 差分线上各串了一个 10Ω 的电阻然后并了一个 TVS 管做浪涌保护。收发器选的是带隔离的型号虽然贵一点但在工业现场能省很多麻烦。如果不带隔离至少要在收发器和 MCU 之间加光耦否则地环路问题会让你头疼。线缆方面一定要用双绞线屏蔽层单端接地。我试过用普通排线走 RS485距离一超过 10 米就频繁丢包换成屏蔽双绞线之后 100 米都没问题。这个钱不能省。4. 固件开发与核心代码实现4.1 I2C 驱动初始化与传感器配置STM32F405RG 的硬件 I2C 初始化我用的是 HAL 库配置起来比较快。时钟速率设成 400kHz占空比 2:1。初始化的时候要注意I2C 的 GPIO 要配置成开漏输出加上拉速度等级设成 Very High。hi2c1.Instance I2C1; hi2c1.Init.ClockSpeed 400000; hi2c1.Init.DutyCycle I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 0; hi2c1.Init.AddressingMode I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 0; hi2c1.Init.GeneralCallMode I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(hi2c1);传感器配置方面PJ85718DM 的配置寄存器需要设置分辨率和报警阈值。我一般把分辨率设成 12 位转换时间大约 150ms对于 HVAC 场景足够了。报警阈值根据具体应用设定比如室内温度报警上限设 35°C下限设 5°C。4.2 温度数据读取与滑动平均滤波读取温度数据的流程是启动转换、等待转换完成、读取温度寄存器、转换成实际温度值。PJ85718DM 的温度寄存器是 16 位的高 12 位有效低 4 位是标志位。转换公式是温度 原始值 × 0.0625。float read_temperature(void) { uint8_t buf[2]; HAL_I2C_Mem_Read(hi2c1, PJ85718DM_ADDR, TEMP_REG, 1, buf, 2, 100); int16_t raw (buf[0] 8) | buf[1]; raw 4; return raw * 0.0625f; }原始数据会有抖动直接显示会跳来跳去。我用的是滑动平均滤波窗口大小 8。具体做法是维护一个长度为 8 的环形缓冲区每次新数据进来就替换最旧的数据然后求平均。这样既能平滑数据又不会引入太大延迟。#define FILTER_WINDOW 8 float temp_buffer[FILTER_WINDOW]; uint8_t buf_index 0; float filter_temperature(float new_temp) { temp_buffer[buf_index] new_temp; buf_index (buf_index 1) % FILTER_WINDOW; float sum 0; for (int i 0; i FILTER_WINDOW; i) { sum temp_buffer[i]; } return sum / FILTER_WINDOW; }实操心得滑动平均的窗口不要设太大否则温度突变时响应会滞后。8 到 16 之间比较合适具体看你的采样率。4.3 本地显示刷新与远程数据帧封装本地显示我用的是 0.96 寸 OLEDI2C 接口和传感器共用一条总线。这里要注意OLED 的 I2C 地址和传感器不能冲突。PJ85718DM 的地址我设成 0x48OLED 一般是 0x3C 或 0x3D不会冲突。显示刷新我放在定时器中断里每 200ms 触发一次。中断里只置一个标志位实际刷新在 main 循环里做避免在中断里做耗时操作。远程数据帧的格式我设计成固定长度方便上位机解析。帧头 2 字节温度值 4 字节浮点校验 2 字节 CRC16帧尾 1 字节。总共 9 字节。发送周期 1 秒用 UART 的 DMA 发送不占用 CPU。typedef struct { uint16_t header; float temperature; uint16_t crc; uint8_t tail; } remote_frame_t;CRC 校验我用的是标准 CRC16-CCITT多项式 0x1021。这个校验方式在工业协议里很常见上位机解析起来也方便。5. 常见问题排查与避坑经验5.1 I2C 通信失败排查流程I2C 通信失败是最常见的问题我整理了一个排查流程按顺序检查基本能定位到原因。排查步骤检查内容常见问题1上拉电阻是否焊接漏焊或阻值过大2电源电压是否正常传感器未供电或电压偏低3I2C 地址是否正确地址配置引脚接错4总线是否有电容过大走线过长或挂载设备过多5时序是否满足要求时钟速率过高我遇到最多的情况是上拉电阻漏焊尤其是手工焊接的板子。还有就是传感器地址搞错PJ85718DM 的地址引脚如果悬空地址是不确定的一定要明确接高或接低。5.2 温度读数跳变的处理方法温度读数跳变一般有三个原因电源噪声、I2C 通信误码、传感器自发热。电源噪声前面说过了加去耦电容和独立 LDO 能解决。I2C 误码可以通过开启 CRC 校验来检测如果发现误码率高就要检查布线和上拉电阻。传感器自发热这个容易被忽略。PJ85718DM 的工作电流很小一般不到 100μA自发热可以忽略。但如果传感器旁边有发热元件比如 LDO 或功率电阻读数就会偏高。我的做法是在 PCB 布局时让传感器远离热源至少保持 5mm 以上的距离。5.3 远程通信丢包与干扰抑制RS485 丢包在工业现场很常见主要原因有地环路、浪涌干扰、终端电阻不匹配。地环路问题用隔离收发器解决浪涌用 TVS 管终端电阻要在总线两端各接一个 120Ω 的电阻。还有一个容易被忽略的点RS485 的使能引脚控制。发送和接收切换时要确保使能信号在数据发送完成之后再切换否则会截断数据帧。我一般用 UART 的 TC传输完成中断来切换使能引脚这样最可靠。注意如果现场干扰特别严重可以考虑降低波特率。9600bps 比 115200bps 的抗干扰能力强很多虽然慢一点但稳定性优先。6. 系统联调与性能验证6.1 精度校准方法与实测数据PJ85718DM 出厂已经校准过但实际使用中还是会有偏差主要来自 PCB 热传导和参考电压漂移。我的校准方法是用一个高精度温度计作为基准把传感器和基准温度计放在同一个恒温环境里等温度稳定后记录两者的差值然后在固件里做偏移补偿。实测数据方面我在 10°C、25°C、40°C 三个点做了对比。未校准前最大偏差 0.8°C校准后偏差控制在 0.2°C 以内。对于 HVAC 应用来说这个精度完全够用了。6.2 长时间运行稳定性测试稳定性测试我跑了 72 小时连续运行每 10 秒记录一次数据。测试期间温度读数没有出现跳变或丢包远程通信的丢包率低于 0.01%。这个结果说明硬件设计和固件逻辑都是可靠的。测试中唯一出现的问题是 OLED 屏在运行 48 小时后出现了轻微残影这是 OLED 本身的特性和电路无关。解决办法是每隔一段时间做一次全屏刷新或者改用 LCD 屏。6.3 功耗优化与低功耗模式尝试如果项目对功耗有要求STM32F405RG 支持多种低功耗模式。我的做法是在没有通信任务的时候让 MCU 进入 Sleep 模式用定时器唤醒。传感器也支持单次转换模式转换完成后自动进入休眠需要读数时再唤醒。实测下来正常模式整机电流大约 45mA优化后能降到 12mA 左右。如果进一步降低采样率还能更低。不过对于 HVAC 这种有市电供电的场景功耗不是首要考虑因素稳定性才是。7. 项目扩展与个人体会这个项目做完之后我又在此基础上做了几个变种。一个是增加了多点测温一条 I2C 总线上挂了 4 颗 PJ85718DM分别监测不同区域的温度。另一个是增加了数据记录功能用 SD 卡把温度数据存下来方便后期分析。扩展的时候要注意I2C 总线上挂的设备越多总线电容越大上拉电阻要相应减小。我挂 4 颗传感器的时候上拉电阻从 4.7kΩ 换成了 2.2kΩ通信才稳定。我个人在实际操作中的体会是嵌入式温度监测这个方向硬件设计占七成固件占三成。很多问题看起来是软件 bug实际上是硬件没做好。所以我在调试的时候会先用示波器看波形确认硬件没问题之后再查代码。这个习惯帮我省了很多时间。最后分享一个小技巧如果你不确定 I2C 通信是否正常可以先写一个最简单的扫描程序遍历所有可能的地址看哪些地址有应答。这个程序虽然简单但在调试新板子的时候特别有用能快速判断传感器是否正常工作。