☰
嵌入式与HVAC温度监测:STM32F756ZG与PJ85718DM本地远程采集方案
2026/10/22 6:41:03 网站建设 项目流程

嵌入式项目里,温度是最常见但也最容易让人头疼的物理量;HVAC项目里,温度又是控制策略的命根子。我最近梳理了一套完整方案:用一颗 PJ85718DM 数字温度传感器,搭配 STM32F756ZG 主控,做一套能同时覆盖本地与远程温度监测的采集系统。这套方案既能服务嵌入式设备内部的板级温度监控,也能落地到 HVAC 的回风、送风、盘管温度采集场景,本地显示和远程上报同时走,硬件上只花一块主控板的成本。这篇文章把这套方案的硬件选型、软件实现、调试流程、常见坑全部拆开讲一遍。适合正在做嵌入式传感器采集、设备入网、暖通控制系统,或者想给现有设备加远程看板的工程师参考。

1. 方案拆解:为什么用 PJ85718DM 搭 STM32F756ZG

1.1 先看标题背后的两个真实使用场景

“嵌入式”和“HVAC”这两个词放在一起,表面看是两套行业,实际对温度监测的需求高度相似:温度变化慢、数据连续性强、对单次采样精度有要求,但更看重长期可靠和历史趋势。嵌��式场景里,我见过太多因为 IGBT 模块、电源板、主控芯片局部过热导致的宕机,温度监测不是为了显示一个数字,而是为了做保护性停机、风扇调速、寿命预估这些决策。HVAC 场景则反过来,回风温度、送风温度、冷水/热水盘管温度直接参与 PID 调节和节能策略,错一度,房间舒适度差一大截,能耗也跟着飘。

这两类场景的共同点是:数据要采集,要本地能看,还要能上传到一个更远的平台,让运维人员不用跑现场。这也是标题里“本地与远程温度监测”的本质需求。方案拆开就是四个字:采集、转发。前端把温度读准,后端把数据送出去,中间主控负责兜底。PJ85718DM 负责前端,STM32F756ZG 负责中间和后端。

1.2 PJ85718DM:为什么选这颗数字温度传感器

先说传感器。温度采集的常规方案有 NTC 热敏电阻、PT100/PT1000 铂电阻、数字 I2C 温度传感器、单总线温度传感器。NTC 便宜但非线性严重,每个探头都得标定,还要搭 ADC 电路;PT100 精度高但需要恒流源、仪表放大器,电路成本直接翻倍。PJ85718DM 这类数字 I2C 传感器的好处是:内部把 ADC 和标定逻辑做完了,单片机直接读寄存器拿温度值,不用做线性化表,不用校正 ADC 参考电压。

选型对比表:

方案接口复杂度精度表现典型成本适合场景
NTC + ADC中,需要查表和滤波低,依赖标定最低低成本消费板卡
PT100 + 运放高,需要调理电路高高工业过程控制
PJ85718DM(数字 I2C)低,两根线中高,手册典型 ±0.5℃中嵌入式板级和 HVAC 测点
单总线传感器低,一根线中低多点长距离布线

从嵌入式板级监测看,I2C 接口在 3.3V 电平下直接和 STM32 相连,省掉 OP 和 ADC 通道,还能把多个传感器挂同一条总线,靠地址区分节点。从 HVAC 应用看,这类传感器一般有较宽的工作温度范围和较小的封装,适合贴在风管或盘管表面。当然,不同厂家出的 PJ85718DM 引脚定义、寄存器地址、转换时间会有差异,我下面所有代码里的寄存器地址都按常见 I2C 温度传感器的模型来写,你们拿到实物后第一件事是翻数据手册把寄存器表核对一遍。

1.3 STM32F756ZG:为什么主控选这颗

STM32F756ZG 属于 STM32F7 系列,Cortex-M7 内核,主频 216MHz,带双精度浮点单元。做温度监测有点“大材小用”,但恰恰因为这个“大材”,让整个项目省掉了大量外围芯片。它内置 2MB Flash 和 320KB SRAM,带硬件加密引擎(AES、DES、HASH)和真随机数发生器,可以直接跑 MQTT over TLS,不用外挂安全芯片。这一点在远程上云时非常关键,否则 TLS 握手时 MCU 算力吃紧,连接动不动就超时。

更实际的一点是 STM32F756ZG 内置以太网 MAC,配合外部一颗 PHY 芯片就能入网。做远程温度监测,联网是刚需。如果选一颗没有以太网 MAC 的 MCU,还得外接 SPI 接口的以太网控制器,驱动、内存占用、带宽全部受限。F756 这颗的 MAC 支持 RMII 接口,占用的引脚少,给传感器总线、显示、RS485 留出了充足资源。我实际的资源分配是:I2C 挂 4 路温度传感器、SPI 挂一块小屏、UART 挂 RS485 从站、RMII 走以太网,还剩一大半引脚空着。

2. 硬件接线与总线设计:先解决能不能稳定读数据

2.1 传感器侧:PJ85718DM 的接口、地址配置和上拉电阻

PJ85718DM 这类数字温度传感器,引脚基本离不开 VDD、GND、SDA、SCL,外加一个或两个地址选择脚。地址脚通常可以悬空、接高、接低,组合出几个不同的 I2C 从机地址。设计时别偷懒,直接把地址脚用 10kΩ 电阻固定到确定电平,避免悬空。我见过不少项目上手动飞线改地址,飞线一松,总线上两个传感器地址冲突,扫描结果时好时坏,折腾一下午才发现是地址脚悬空导致的上电不定态。

I2C 总线必须接上拉电阻。STM32 的 I2C 引脚内部有弱上拉,但驱动能力不够,多挂几个传感器、线长超过 20cm 就容易电平翻转不到位。我习惯在 SDA 和 SCL 上各接一个 2.2kΩ 上拉到 3.3V,这是一个折中值。上拉阻值太小,总线灌电流偏大;阻值太大,上升沿变慢,抗干扰能力下降。如果传感器和主控板分体,线缆做到 30cm~50cm,建议降到 1kΩ,同时把 I2C 速率从 400kHz 降到 100kHz。速度慢一点,可靠性高很多,温度采集根本不需要高速。

供电去耦是另一个容易被忽略的点。每个传感器的 VDD 和 GND 之间,紧贴引脚放一个 100nF 陶瓷电容,有条件再放一个 10μF 钽电容。HVAC 现场常有风机、压缩机启停,电源线上噪声很大,去耦电容直接决定读到的温度会不会周期性跳动。别图省事只在一端集中滤波,传感器端的高频噪声就地吸收才是正道。

2.2 主控侧:STM32F756ZG 的外设分配和引脚规划

硬件设计的核心是把每个功能模块挂到合适的外设上,提前规划引脚,避免最后发现两个功能冲突。我的分配方案如下:

功能模块外设引脚示例说明
温度传感器总线I2C1PB7 / PB6挂 4 路 PJ85718DM,按 A0/A1 区分地址
本地显示屏SPI1PA5 / PA7 / PA6 + 片选128x64 OLED,只显示不操作
本地调试和维护USART3PD9 / PD8输出日志,运行时接 RS485 转 Modbus 从站
远程网络ETH(RMII)PC1 / PC2 / PA1 / PA2 / PA7 / PC4 / PC5外接 PHY 芯片,RMII 模式
用户按键GPIOPA0切换本地显示通道
告警指示灯GPIOPA8超温告警,硬件冗余提示

这里要特别提醒 RMII 的引脚规划。RMII 接口需要一条 50MHz 的参考时钟,可以由主控 MCO 输出,也可以由外部有源晶振提供,但必须保证时钟信号干净。很多 PHY 芯片在 RMII 模式下对参考时钟的相位和占空比有严格要求,我用主控 MCO 输出 50MHz 接 PHY 时,偶尔出现链路协商不稳、ping 丢包的情况,后来改成由外部有源晶振直接给 PHY 供时钟,主控侧只收数据,问题就消失了。硬件设计如果能用独立时钟源,优先独立时钟源,少一个主控侧的麻烦。

2.3 本地与远程双通道怎么同时走

本地通道我设计成 OLED 显示加 Modbus RTU 从站。OLED 直接显示当前温度值,方便现场维护人员扫一眼就能判断;Modbus RTU 从站挂在 RS485 上,给 HVAC 的楼宇控制器或触摸屏读取。这个思路是:本地不只是“人看”,还要让本地设备能读。

远程通道走以太网加 MQTT。STM32F756ZG 的以太网 MAC 跑轻量级 TCP/IP 协议栈,上面挂 MQTT 客户端,将温度数据发布到 Broker。数据流是:PJ85718DM 传感器采集 → STM32 做滤波校准 → 同时写入本地显示缓存和 MQTT 发送队列 → 发布到订阅端。两条通道互不阻塞,本地显示卡了不能影响远程上报,远程网络断了也不能阻塞传感器读取。这就是为什么在软件上要分任务处理,而不是一个主循环从头跑到尾。

3. 驱动与上报实现:从寄存器到远端看板的一条完整链路

3.1 先写传感器驱动:初始化、读温度、寄存器细节

不管芯片手册怎么写,I2C 数字温度传感器的驱动都逃不开这几步:确认器件地址、发起转换、等待转换完成、读出温度寄存器、按分辨率换算成实际温度。PJ85718DM 的转换时间通常在几毫秒到几十毫秒之间,读寄存器前最好先看状态标志位,别一上电就猛读,读出来全 0 再怀疑硬件,那是驱动时序没对好。

下面这段是我反复用的读取模板。寄存器地址按常见模型举例,拿到实物必须替换成手册里的真实值:

#define PJ85718DM_REG_TEMP 0x00 // 举例:温度数据寄存器 #define PJ85718DM_REG_CONFIG 0x04 // 举例:配置寄存器 // 从 16 位数据中解析温度,分辨率按 0.0625℃/LSB 举例 float pj85718dm_get_temp(I2C_HandleTypeDef *hi2c, uint8_t sensor_addr) { uint8_t buf[2]; uint16_t raw; if (HAL_I2C_Mem_Read(hi2c, sensor_addr, PJ85718DM_REG_TEMP, I2C_MEMSIZE_8BIT, buf, 2, 100) != HAL_OK) { return NAN; } raw = ((uint16_t)buf[0] << 8) | buf[1]; // 有符号数:最高位是符号位,先转成 int16_t 再做换算 return (float)((int16_t)raw) * 0.0625f; }

注意 HAL 库的sensor_addr是 8 位 I2C 地址,也就是 7 位从机地址左移一位后的值。扫描 I2C 总线上有哪些设备时,我用HAL_I2C_IsDeviceReady直接遍历:

for (uint16_t addr = 0x00; addr < 0x80; addr += 2) { if (HAL_I2C_IsDeviceReady(&hi2c1, addr, 2, 100) == HAL_OK) { printf("found device at 0x%02X\r\n", addr); } }

这个 0x00 到 0x80 遍历是初学者最容易踩坑的地方。HAL 的参数要求 8 位地址,所以循环步进是 2,扫到的是左移后的地址。如果你按 7 位地址扫,漏掉设备的概率很大。

3.2 多点采集:地址配置、轮询节奏、总线上怎么放多个传感器

PJ85718DM 挂同一条 I2C 总线的关键是每个传感器地址不同。设计时把四个传感器的 A0/A1 地址脚组合编好,在代码里用宏定义每路的地址,轮询时依次读取,而不是在运行时动态探测,避免启动时误识别。

#define TEMP_SENSOR_COUNT 4U static const uint8_t temp_addr[TEMP_SENSOR_COUNT] = { 0x48 << 1, // 通道1,地址脚均为低 0x4A << 1, // 通道2,A0=高 A1=低 0x4C << 1, // 通道3,A0=低 A1=高 0x4E << 1 // 通道4,A0=高 A1=高 }; typedef struct { float value[TEMP_SENSOR_COUNT]; uint8_t fault[TEMP_SENSOR_COUNT]; } temp_report_t; temp_report_t report; void temp_task(void) { for (int i = 0; i < TEMP_SENSOR_COUNT; i++) { float t = pj85718dm_get_temp(&hi2c1, temp_addr[i]); if (isnan(t)) { report.fault[i] = 1; } else { report.value[i] = t; report.fault[i] = 0; } HAL_Delay(10); // 留一点总线间隔,避免连续操作太快 } }

轮询节奏上,温度量变化慢,1 秒采一轮完全够,HVAC 场景甚至可以 5 秒一轮。千万别一上来就把所有传感器放在一个for里零延时读完,I2C 连续快速读写容易触发总线错误,在长线场景尤其明显。每路之间加 10ms 间隔,代价微乎其微,换来的是可靠性和故障隔离。

3.3 数据质量:限幅滤波、移动平均、两点校准、告警迟滞

读到的原始温度往往带毛刺,特别在 HVAC 现场,风机启动瞬间的电磁干扰会让数值跳几度。处理毛刺我分两层做:先限幅滤波,把相邻采样变化超过 0.5℃ 的样本丢弃;再做去极值移动平均,消除小幅随机噪声。

#define LIMIT_DEG 0.5f float last_valid = NAN; float limit_filter(float sample) { if (isnan(last_valid)) { last_valid = sample; return sample; } if (fabsf(sample - last_valid) > LIMIT_DEG) { return last_valid; // 认为这是干扰,保持上次值 } last_valid = sample; return sample; }

去极值移动平均的思路是:取最近 5 个有效样本,去掉最大值和最小值,剩下 3 个取平均。这样即使偶发脉冲干扰没有被限幅滤波完全去掉,也会被极值剔除机制挡在平均结果之外。

校准是第二个重点。数字传感器出厂有标定,但贴在风管、散热器表面之后,因为热阻差异,读数和参考点之间常差那么零点几度。我习惯做两点校准:参考点一个选 0℃(冰水混合物),另一个选 40℃~60℃ 的恒温槽,记录原始读数和参考值,算出一条一次函数。代码里就保留两个系数:

#define CAL_GAIN 1.003f // 举例,由校准实验计算 #define CAL_OFFSET -0.12f // 举例,由校准实验计算 float cal_temp(float raw_temp) { return raw_temp * CAL_GAIN + CAL_OFFSET; }

告警逻辑一定要加迟滞。HVAC 场景里,如果送风温度目标值是 25℃,你用“高于 25℃ 就告警、低于 25℃ 就复位”,那系统会在临界点反复横跳,告警邮件一条接一条。至少设置 3℃~5℃ 的迟滞区间:

#define ALARM_ON 55.0f #define ALARM_OFF 50.0f bool alarm_state = false; void alarm_update(float t) { if (!alarm_state && t >= ALARM_ON) alarm_state = true; if (alarm_state && t <= ALARM_OFF) alarm_state = false; }

嵌入式设备里控制风扇转速、HVAC 里控制调节阀开度,都应该带迟滞,否则执行机构寿命会被频繁启停耗尽。

3.4 远程上报链路:轻量级 TCP/IP 协议栈 + MQTT 发布

STM32F756ZG 的以太网 MAC 在软件上要配一个轻量级 TCP/IP 协议栈,再加上 MQTT 客户端库。整个远程链路的搭建步骤我总结成下面几步:

  1. 初始化 PHY 芯片,配置 RMII 引脚,等 linkup。
  2. 配置 MAC 和 IP,我习惯先静态 IP 调试,跑通了再换 DHCP。
  3. 初始化 MQTT 客户端,设置 Broker 地址、端口、用户名密码。
  4. 温度任务采样后,将 JSON 报文投递到发布队列,由网络任务负责发送。
  5. 处理断线重连,重连成功后补发缓存数据。

MQTT 报文设计不用搞复杂。我用的 payload 是:

{"node":"channel1","type":"temp","value":24.6,"unit":"C"}

Topic 建议按设备/通道细分,比如sensors/deviceA/channel1。这样订阅端可以只订阅关心的通道,不用全部收下来再自己在业务里筛。QoS 建议用 1,保证消息至少到达一次,又不至于像 QoS 2 那样握手开销过大。设备掉线遗嘱消息也很有用,Broker 一旦检测到连接断开,可以向“设备离线”主题发布一条遗嘱,让看板知道这个节点失联了。

远程链路最容易翻车的是 TLS。F756 内置硬件加密引擎,理论上可以跑 MQTT over TLS,但证书体积、握手内存都吃资源。我的建议是:前期调链路阶段先跑明文 MQTT,把传感器数据打通了再上 TLS,不要一上来就叠加密,否则报错了你都不知道是网络问题还是证书问题。

4. 实测流程:从点亮 I2C 到远程看板出数的完整调试记录

4.1 第一步:硬件最小系统焊接与上电前检查

这个项目的最小系统就是 STM32F756ZG 主控板加一颗 PJ85718DM,加一块 USB 转串口线用于打印日志。焊接顺序我建议先焊主控、晶振、电源,再焊传感器的 I2C 上拉电阻和传感器本体,最后焊 PHY 和 RJ45。上电前用万用表测一遍 3.3V 和 GND 之间有没有短路,测 I2C 两条线有没有对电源短路,这些检查花不了五分钟,却能避免上电冒烟。

第一次上电不急着跑业务代码,先让主控跑一个 LED 闪烁程序,确认时钟和调试器正常。接着调串口打印,确认日志通道没问题。然后再开始扫描 I2C 设备。

4.2 第二步:用 I2C 扫描器找设备,先把地址对上

我的 I2C 扫描器代码很简单,就是在while(1)里不断调用HAL_I2C_IsDeviceReady,把找到的地址打出来。这一步能快速验证三件事:传感器供电正常、I2C 上拉正常、从机地址正确。插上 PJ85718DM 后,扫描到地址0x48<<1,也就是打印出0x90,说明器件应答了。

如果扫不到设备,按下面的顺序排查:先量传感器 VDD 电压,再量 SCL/SDA 有没有波形,最后检查地址脚是否悬空。扫不到设备九成是硬件问题,只有一成是代码问题。

4.3 第三步:本地显示和 Modbus 从站同时出数

设备地址确认后,我把读取到的温度显示在 OLED 上,然后又花了小半天把 Modbus RTU 从站跑起来。这里有个值得分享的思路:先用电脑端的 Modbus 主站工具去读,把功能码、起始地址、寄存器数量调对,再去对接真正的楼宇控制器。我在这个环节踩过最大的坑是字节序。Modbus 的 16 位寄存器默认大端,而 STM32 是小端,如果直接把int16_t塞进寄存器,主站读到的数值完全不对劲。我后来统一在从站代码里做了一次字节调换,用 Modbus 工具验证通过,才放给现场设备用。

4.4 第四步:以太网连接和远程订阅

以太网调试是最考验耐心的部分。先把 PHY 的 link 状态打印出来,确认插上网线后 PHY 上报“网线已连接”。接着 ping 通电脑,再配置 MQTT Broker。我准备了两个订阅端,一个电脑端工具,一个手机 App,同时订阅sensors/deviceA/#。当 STM32 发布第一条真实温度时,两个订阅端同时弹出数据,那种感觉就像设备突然“活”了。

远程断线重连的测试一定要做。我直接把网线拔了,观察 STM32 在 Broker 掉线后会不会自动重连。单纯在 MQTT 库回调里打印“断开”还不行,要确认重连后能正常续发数据。我在 Broker 端记录了连接断开和重连的时间戳,又补了本地缓存机制:断线期间的采样数据暂存在内部 SRAM 的环形缓冲区里,恢复连接后按顺序补发,避免丢一段时间的温度曲线。

4.5 HVAC 场景实测:安装位置比算法更影响数据质量

我在 HVAC 模拟环境里把传感器贴在风管送风口和回风口,发现一件事:传感器自身算法再准,安装位置不对,读数也没意义。送风温度传感器如果贴在靠近冷盘管出风口 20cm 内,读到的是混合不均的局部冷空气,和回风温度差了五六度,控制逻辑直接乱套。我的处理是让传感器探头贴着风管保温层外侧,并用导热硅胶填充空隙,尽量让探头感测的是管内空气平均温度,而不是某股射流温度。

采集周期在 HVAC 场景也很关键。写日志我发现,1 秒采样会把风机启停瞬间的毛刺全部记录下来,而 5 秒采样配合滤波之后,曲线平滑很多。最后我直接改成一个 5 秒的轮询周期,数据足够驱动 PID,日志量也小。

5. 常见问题与排查速查表:I2C、以太网、精度三大坑

5.1 I2C 与传感器读数类问题

现象排查方向解决方案
扫描不到设备供电、地址、上拉先量 VDD 和 GND;检查地址脚是否悬空;SDA/SCL 接 2.2kΩ 上拉
读到 0x0000 / 固定 0℃寄存器地址、转换时序核对手册里的温度寄存器;等转换完成再读;确认设备处于正常模式
数据周期性跳动电源纹波、EMI 干扰传感器端加 100nF 去耦;I2C 速率降到 100kHz;SDA/SCL 加串联 330Ω 电阻
总线偶尔卡死总线忙状态轮询时增加延时;为 I2C 加超时重试;严重时改用软件模拟 I2C
多路传感器读数串地址冲突确认每片传感器的 A0/A1 组合唯一,上电前用万用表量地址脚电平

I2C 卡死是最隐蔽的问题之一。HVAC 现场长线缆、强干扰下,总线上偶尔出现时序毛刺导致 SCL 被拉死,HAL_I2C_Mem_Read一直返回超时。我后来在驱动里加了软件重试:如果连续 3 次读失败,先把 I2C 外设复位,再重新初始化,大部分情况能自己恢复。硬件上也给 SDA/SCL 串了 330Ω 电阻,抗干扰能力明显提升。

5.2 以太网与远程传输类问题

现象排查方向解决方案
网线插上灯亮但 ping 不通PHY 地址、RMII 时钟确认 PHY 芯片地址引脚上电电平;检查 50MHz 参考时钟波形
时通时断时钟相位、电源质量用外部有源晶振独立给 PHY 供时钟;PHY 供电加磁珠和电容隔离
MQTT 连接被拒服务器配置、端口先本地局域网测试;确认用户名密码;检查防火墙是否拦截
数据发到 Broker 但订阅端无消息Topic 不匹配统一 topic 命名规则;用通配符#订阅根节点排查
断网后重连不上重连逻辑、半开连接设置 keepalive;在检测到断开后主动关闭旧 socket 再重连

5.3 精度一致性专项排查

温度传感器行业里最掉链子的反而不是传感器本身,而是安装环节。传感器外壳和被测面之间如果有空气隙,热阻会急剧增大,读数滞后和偏差都会放大。我实测过,同一颗 PJ85718DM,直接贴在铝板表面和不涂导热硅胶悬空放置,读数能差 1.5℃。所以 HVAC 现场安装传感器,导热硅胶、扎带固定、穿线密封这三件事一定要做扎实。

另外,传感器自热也是隐蔽误差源。I2C 温度传感器在工作时有电流消耗,虽然很小,但如果被测对象热容量很小,传感器自身温度会高于介质温度。我在小体积风管里做过对比,把 I2C 速率降到 100kHz、降低采样频率后,自热影响明显减小。对精度要求高的场景,可以考虑在传感器不工作时把电源关断,实现零漂移采样。

6. 写在最后:几点体会和扩展方向

这套系统我重新推演过好几遍,如果再来一次,我会把传感器的总线拓扑再仔细斟酌。I2C 总线确实方便,但在 HVAC 现场,传感器需要分布在风管、盘管、室外等多个位置,I2C 线缆太长就不可靠了。更合理的做法是让 STM32F756ZG 作为区域采集网关,附近短距离用 I2C,远端传感器改用 RS485 总线或无线方式汇总进来。远程协议上,如果甲方要求接楼宇系统,把 Modbus TCP 从站也加上,这样一套硬件既能上云,又能被本地 BMS 读取。

还有一个教训值得写出来:远程监测项目里,网络不会一直是好的。一定把本地存储、断线缓存、补发机制当作主功能来做,而不是当作锦上添花的功能。我在现场遇到过运维人员把网线踢掉一半,数据断了一个小时没人发现,事后要回溯温度曲线才发现少了一段。如果不是当时做了环形缓存,那段缺失的数据完全找不回来。

最后分享一个我个人的调试习惯:每次给传感器驱动加新功能之前,先把原始读数打印出来存成一份 CSV 日志。滤波、校准、告警这些算法都有没有生效,跑一轮数据对比一目了然。裸凭眼睛看 OLED 上跳动的数字,很难判断到底是算法问题还是传感器问题。这套 PJ85718DM 加 STM32F756ZG 的方案,整体不算复杂,但每一步都有它该有的细节,把这些细节磨透了,温度监测这件事就能做得很扎实。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询