☰
STM32与PJ85718DM温度监测系统实战:I2C本地采集+RS485远程汇聚
2026/10/22 6:42:13 网站建设 项目流程

搞嵌入式或者暖通控制的朋友都清楚,温度监测看起来是最不起眼的功能,但真正要把“温度”测准、传稳、在本地和远程都可靠,往往比想象中多花两三倍时间。这个项目里我用了 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,主频能到 168MHz,Flash 1MB,SRAM 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 到 1,alpha 越大响应越快、滤波越弱。在 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 现场温度监测,传感器探头别买太便宜的,安装工艺比传感器品牌更重要。探头装配到位、导热膏抹好、线缆走线规范,哪怕一颗中等精度的传感器也能稳定工作很多年;安装敷衍的话,再贵的传感器也会被现场环境“教做人”。做完这套系统之后再用同型号器件做别的场景,我每次都会把布线和安装规范放在和硬件设计同等重要的位置。这也是这套方案能保持稳定运行最核心的经验。

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

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

立即咨询