基于STM32与I2C温度传感器的本地远程测温系统设计与实现

发布时间:2026/10/22 12:16:52
基于STM32与I2C温度传感器的本地远程测温系统设计与实现
1. 方案是怎么定下来的先想清楚“本地/远程”到底要测什么这两年我做嵌入式板级和 HVAC 机组项目手头最常用的一套测温组合就是 PJ85718DM 配 STM32F205RB。很多人一开始看到这个选型都会疑惑市面上一块钱的 DS18B20、一块多的 NTC 加 ADC、甚至直接上 PT100 变送器方案不是一大把吗为什么绕一圈选了个不怎么大众的 I2C 传感器加一颗 Cortex-M3 主控这个选择背后其实是一长串需求推导出来的今天就把整个思路、硬件设计、软件写法和现场踩坑记录全摊开讲。1.1 需求落地三种测温口径先要分清很多人把“本地温度”和“远程温度”理解成“传感器放在旁边”和“传感器放得远”这个理解不算错但在实际项目里必须拆得更细因为不同的测温口径对应完全不同的硬件方案。第一类是板级本地温度。PJ85718DM 芯片自身或者芯片周围 PCB 的温度通常是 CPU、电源模块、驱动板这些位置用来做过热保护、降频策略、风机启停判断。这类温度变化快、量程相对窄读数不能有太大延迟而且要跟主控的地挨得很近走线不超过几厘米。第二类是探针式远程温度。传感器在控制板附近但测温点通过线缆引到几十厘米甚至十几米外比如 HVAC 机组的回风口、送风管、冷媒管路、室外机换热器翅片、压缩机壳体。这类应用最麻烦的不是传感器本身而是长线引入的干扰和线阻误差NTC 在这里会哭的1-Wire 的时序也会因为线缆电容和阻抗不匹配变得很难看。第三类是通讯级远程温度。现场有多个机组、多个测点数据要通过 RS485、Modbus 或者其他总线汇集到上位机中控室能看到分布在几百米范围内的所有温度。这个“远程”跟传感器本身没有直接关系但方案架构一开始就得把通讯接口和协议栈留好。PJ85718DM 这套方案刚好能把三件事一把抓芯片内置本地测温通道外部引脚可以接一个二极管探针做远端测温主控再用串口转 RS485 把两个温度一起上报。也就是说“本地和远程温度监测”在一个芯片加一颗 MCU 上就完整闭环了。1.2 为什么选 PJ85718DM 而不是 DS18B20 / NTC ADC最早我也走过弯路。第一版方案是用 NTC 加 STM32 内部 ADC电路倒是简单可精度受 ADC 参考电压、滤波电容、走线阻抗影响很大想要做到 ±0.5°C 就得每个板子单独校准产线上根本玩不起。后来试过每个测点挂一颗 DS18B20短距离单点测温确实挺好用但 HVAC 现场经常要测冷媒管表面和风道里的温度探针线一拉长1-Wire 总线就容易出现应答超时、CRC 错误多颗传感器组网时还要处理寄生供电和上拉电阻匹配维护成本比想象中高不少。对比下来PJ85718DM 有几个很适合嵌入式与 HVAC 场景的特性。它是 I2C 接口时序容错比 1-Wire 强得多400kbps 速率下也有很长的走线余量内部有本地测温单元外部又可以通过专用的二极管接口接远程探针等于一颗料同时出了两个温度值省掉一路模拟前端数据格式是数字量直接读寄存器拿 raw 值换算不需要做线性化要是后续想做多点监测靠 I2C 地址线和一颗 TCA9548A 之类的切换器也能扩展。至于主控为什么选 STM32F205RB理由更直接。F205 系列是 Cortex-M3 内核主频 120MHzFlash 有 1MBRAM 有 128KB对一个小型温度监测节点来说性能是溢出很多但恰恰因为溢出才有空间做显示驱动、Modbus 协议栈、历史数据缓存甚至以后加个简易网页配置界面都不会卡。HVAC 设备里这种主控算是主流档位采购、备料、调试工具链都很顺手。提示选型时一定先把“远程”的定义固定下来。如果你说的远程是指探针引线长那核心是传感器的远程通道和抗干扰如果你说的远程是指多设备集中监控那核心是通讯协议和路由。两个目标定反了后面整条设计链路都会跑偏。2. 硬件设计与选型细节硬件层面很多人关心的是“传感器怎么接线”“主控怎么搭最小系统”但从工程角度看真正决定成败的是远程探针的走线和抗干扰设计。这一节我会先交代 PJ85718DM 的接口细节再讲 STM32F205RB 的最小系统最后把远程测温布线的坑一个个填上。2.1 PJ85718DM 基础寄存器与接口PJ85718DM 典型封装是 8 脚小封装供电 3.0V 到 5.5V我习惯给 3.3V因为 STM32 的 I/O 也是 3.3V不用做电平转换。I2C 地址由 A0/A1 引脚决定相当于可以在同一条总线上挂 4 颗做多点板内测温很宽松。器件的主要接口引脚是 SCL、SDA、D、D-其中 D/D- 就是远程二极管探针的接入端。寄存器布局大致如下当前本地温度存在 0x00 和 0x01当前远程温度存在 0x06 和 0x07配置寄存器 0x08 可以控制测温分辨率、转换周期、比较/中断模式。温度值默认是 12 位有符号格式最低位代表 0.0625°C读取后左移或者查表换算都行。接线时要注意两个细节。一是 SDA/SCL 一定要接上拉电阻阻值 4.7kΩ 在 400kHz 下比较稳如果线缆长或者挂的设备多可以降到 2.2kΩ二是 D 和 D- 是远程测温的敏感输入走线要尽量成对差分不要跟电源线、继电器控制线绑在一起。很多 HVAC 板子变频器和压缩机启动瞬间电流很大强干扰路径一旦耦合进 D/D-远程温度立刻就开始跳舞。2.2 STM32F205RB 最小系统搭建STM32F205RB 的最小系统不算复杂但每一步都有讲究。供电用 3.3V给 VDD 和 VDDA 都加上 0.1µF 陶瓷电容电源入口再加一个 10µF 钽电容或电解电容NRST 引脚外接 100nF 电容到地防止上电抖动导致反复复位。外部晶振我直接用 8MHz 无源晶振加两个 20pF 负载电容通过 PLL 倍频到 120MHz这样主频跑起来I2C 的时钟也能拿到比较准的整数分频。I2C1 我习惯映射到 PB7(SCL) 和 PB6(SDA)或者 PB8/PB9 也可以看板子布线怎么方便。上拉电阻跟传感器共用一路即可。调试口留 SWD 四根线VDD、GND、SWDIO、SWCLK加上复位引脚调试器就能稳定连接烧录和在线单步都方便。远程通讯这部分是少不了的我用了一片半双工 RS485 收发器接到 USART1A/B 端加 120Ω 终端电阻靠近连接器位置放 TVS 管。Modbus 协议跑 RS485 是工业现场最保守、最不容易出问题的组合后续上位机用 Modbus Poll、边缘网关转 MQTT 都行协议栈对被控设备来说也没有识别压力。实操心得STM32F205RB 的 I2C 外设相比 F1 系列要顺手很多支持多主模式、超时检测和错误中断。新手容易忽略的是 I2C 外设时钟必须使能而且 GPIO 要配置为开漏输出带上拉否则总线哪怕有一颗芯片拉低整个通讯都会卡死在 ACK 阶段。2.3 布线技术长线远程探针的干扰问题这是 HVAC 现场最容易翻车的地方也是我这套方案里花精力最多的位置。PJ85718DM 的 D/D- 是远程测温通道探针可以是一颗封装好的二极管也可以直接焊接在目标物体表面但探针引线只要超过 20cm就会像天线一样接收变频器、风机、继电器触点产生的电磁噪声。常见做法是给 D/D- 各串联一个 1kΩ 电阻再在靠近传感器侧加一个 100pF 到 1nF 的共模滤波电容把高频干扰按在入口之前。探针线用双绞屏蔽线屏蔽层单端接地接在主控板的地上千万不要两端都接不然地环路反而会引入更大噪声。实测在 30 米双绞屏蔽线的情况下远程温度波动可以控制在 ±0.3°C 左右对于 HVAC 场景完全够用。还有一个很容易被忽略的点D/D- 引脚对电源短路就会永久损坏传感器。探针走线如果会经过有冷凝水、油污、金属板金的环境必须在线缆外加耐高温绝缘套管连接器用带锁扣防水的类型。传感器探头固定在冷媒管上时要用导热硅脂填充缝隙再用铝箔胶带压紧不要只靠绝缘胶带缠那样热阻太大读到的温度滞后严重。3. 软件实现与调试硬件只是骨架软件才是把 PJ85718DM 和 STM32F205RB 连起来的肌肉。这一节直接从寄存器读写讲到 Modbus 上报代码都是我在实际项目里跑过的套路抄的时候注意根据现场参数微调。3.1 PJ85718DM 驱动从零手写 I2C 读取代码我建议用标准库或者 LL 库直接操作寄存器HAL 的抽象层次太多温度采集这种简单外设反而显得啰嗦。先看初始化void PJ85_Init(void) { // 开启 GPIOB 和 I2C1 时钟 RCC-AHB1ENR | RCC_AHB1ENR_GPIOBEN; RCC-APB1ENR | RCC_APB1ENR_I2C1EN; // PB6 SCL, PB7 SDA, 开漏输出, 带上拉 GPIOB-AFR[0] | (4 24) | (4 28); GPIOB-MODER | (2 12) | (2 14); GPIOB-OTYPER | (1 6) | (1 7); GPIOB-PUPDR | (1 12) | (1 14); // I2C1 时钟 100kHz, 根据 PCLK1 计算 I2C1-CR2 42; // 42MHz PCLK1 I2C1-CCR 210; // 100kHz I2C1-TRISE 43; I2C1-CR1 | I2C_CR1_PE; }读取本地温度和远程温度的流程一样先写寄存器指针地址再读两个字节。为了稳定性每轮采样连续读四次取中间值这个后面在滤波里细说。核心读函数大致这样uint16_t PJ85_ReadTemp(uint8_t reg_addr) { uint16_t raw 0; uint8_t buf[2] {0}; // 发送起始位 器件地址 写位 I2C1-CR1 | I2C_CR1_START; while (!(I2C1-SR1 I2C_SR1_SB)); I2C1-DR (PJ85_ADDR 1) | 0; while (!(I2C1-SR1 I2C_SR1_ADDR)); (void)I2C1-SR2; // 写寄存器地址 I2C1-DR reg_addr; while (!(I2C1-SR1 I2C_SR1_TXE)); // 重启 读模式 I2C1-CR1 | I2C_CR1_START; while (!(I2C1-SR1 I2C_SR1_SB)); I2C1-DR (PJ85_ADDR 1) | 1; while (!(I2C1-SR1 I2C_SR1_ADDR)); (void)I2C1-SR2; // 读高字节然后读低字节 停止位 I2C1-CR1 | I2C_CR1_ACK; while (!(I2C1-SR1 I2C_SR1_RXNE)); buf[0] I2C1-DR; I2C1-CR1 ~I2C_CR1_ACK; while (!(I2C1-SR1 I2C_SR1_RXNE)); buf[1] I2C1-DR; I2C1-CR1 | I2C_CR1_STOP; raw ((uint16_t)buf[0] 8) | buf[1]; return raw; }这段代码没有加错误处理实际工程里还要检查 AF应答失败、BERR总线错误、TIME_OUT 等标志位。I2C 总线的特点是“一错就容易死锁”所以比较稳妥的写法是每读一次就检查总线状态出错就调用一个复位函数把 I2C 外设重新初始化一遍能让你在现场少跑很多冤枉路。3.2 温度换算与两点校准PJ85718DM 默认 12 位分辨率转换结果用二进制补码表示换算公式是float PJ85_ToCelsius(uint16_t raw) { int16_t signed_val (int16_t)raw; return (float)signed_val * 0.0625f; }要注意的是只有当量程在 -55°C 到 125°C 之间时0.0625°C/LSB 这个比例才完全线性。超出量程后读数会接近上下限饱和现场看到温度恒为 -127 或者 127多半不是真的到了这个温度而是传感器已经挂了或者接线开路。判断逻辑里可以直接把这两个值当成异常状态来处理。出厂精度一般能做到 ±0.5°C 左右但 HVAC 客户有时候要求在关键测点做到 ±0.3°C这就要求做两点校准。方法是准备一个恒温源分别设定低温 0°C 和高温 70°C记下传感器读数然后算出增益和偏置float PJ85_Calibrated(float raw_degc) { // gain 和 offset 由两点标定得到 return raw_degc * gain offset; }校准数据可以存放在 STM32 内部 Flash 的独立扇区里每台设备出厂时写一次。没有恒温源的话也可以用两个精度更高的参考温度计做替代但校准点至少要覆盖设备实际使用范围的两端只做单点校准只能解决偏置解决不了斜率误差。关于滤波我最终采用的是“移动中值 一阶惯性”的组合。每轮采集 5 个原始值去掉最大最小剩下三个求平均再跟上一轮结果做一次递推平滑filtered filtered * 0.7f current_avg * 0.3f;这个系数要根据测温点的热惯性调整。冷媒管表面温度变化快系数可以调到 0.5/0.5空气温度变化慢0.8/0.2 更合适。总之不是越平滑越好滤波太深会让报警响应变得迟钝HVAC 的压缩机保护逻辑等不了那么久。3.3 Modbus RTU 远程上报保持寄存器与 CRC远程监控如果只靠传感器本身那只能算“引线远程”真正意义上的集中监控必须把数据送到上位机。我用 Modbus RTU 从机模式把本地温度和远程温度分别映射到保持寄存器 0x0001 和 0x0002这样组态软件直接读地址就能显示。Modbus RTU 的关键是 CRC16字节序和多项式的坑特别多。我直接贴一个验证过很多遍的实现uint16_t Modbus_CRC16(uint8_t *data, uint16_t len) { uint16_t crc 0xFFFF; for (uint16_t i 0; i len; i) { crc ^ data[i]; for (uint8_t j 0; j 8; j) { if (crc 0x0001) crc (crc 1) ^ 0xA001; else crc 1; } } return crc; }帧格式是地址码、功能码、寄存器地址、数据、CRC 低字节、CRC 高字节。我用定时器或者串口空闲中断来断帧一般判断 3.5 个字符时间没有新数据就认为一帧收到了。现场如果发现偶尔掉帧、一包数据被拆成两段多半是主站发的间隔不稳可以在代码里把断帧时间放宽到 5 个字符长度代价是响应时间慢了不到 1ms无关紧要。从机地址用拨码开关来配置可以支持 1 到 247 号站。地址冲突是 HVAC 现场经常出现的问题多个节点在不知道的情况下配成同一个地址上位机读到的温度就会跳来跳去。所以我习惯在设备上电时用 GPIO 读取拨码状态再在状态页显示出来方便调试时确认。3.4 看门狗、连续失效保护、掉电检测温度监测如果用在压缩机保护、除霜判断、火灾预警这类环节软件不能只负责“读温度发数据”还要考虑传感器失效时系统的行为。我先定义了连续失效保护和掉电/低电压逻辑软件里维护一个“连续无效计数”连续 5 次读到异常值就切到故障状态不再用错误数据去驱动控制逻辑等连续 3 次读到有效值再恢复这能避免电磁干扰引发的瞬时误判导致压缩机频繁启停。独立看门狗 IWDG 是标配喂狗只能在主循环的正常路径上执行不能放在中断里“曲线救国”。否则一旦主程序死循环中断还在跑看门狗照样被喂得死死的系统就永远无法自动复位。掉电检测方面可以用 STM32 的 PVD 功能在 3.0V 以下触发中断及时把当前状态保存到备份寄存器避免突然断电导致温度校准参数或者累计运行时间丢失。提示PJ85718DM 的 ALERT 输出引脚可以用来做硬件级过温中断。像冷媒管表面温度超过 90°C、控制板温度超过 85°C 这种阈值判断直接在传感器内部比较ALERT 引脚触发 STM32 的外部中断响应速度比主循环轮询快得多也更安全。4. 现场实测与踩坑记录整个系统在实验室跑通只是一半真正让方案成熟的是现场安装、长线测试和故障排查。我把两次比较有代表性的实测经历整理出来参数、现象、处理办法都列清楚方便你直接对标。4.1 从焊台到工程样机的搭建步骤第一版验证板是手工焊接的大概流程如下先把 STM32F205RB 最小系统的电源、晶振、SWD 调试口焊好下载一个 LED 闪烁程序确认 MCU 工作正常再把 PJ85718DM 焊到 I2C 总线上用逻辑分析仪抓 SCL/SDA 波形确认地址应答和设备 ID 正确接着接上远程探针放在一杯冰水混合物和热水里分别测试读数最后才接 RS485 收发器用 USB 转 485 线连电脑在 Modbus Poll 里读寄存器。样机外壳用的是标准导轨式 DIN 外壳板子上下留了散热孔但传感器尽量避开电源模块和继电器之类的高温源。因为板内发热器件离 PJ85718DM 太近会导致本地温度读数比环境温度高出 4-6°C这在精度测试中会被客户直接打回来。远程探针的安装是另一个关键环节。HVAC 机组里冷媒管表面温度变化快探针要垂直贴管壁用金属卡箍固定接触面涂导热硅脂。有人图省事直接把探针放在管道附近的空气里测出来的不是管温而是环境温度除霜判断和回油控制都会失效。4.2 实测数据与长线测试为了验证远程探针在长线下的稳定性我做了一组测试数据大概如下探针线长度本地温度读数远程温度读数参考温度计远程偏差0.1m25.31°C36.50°C36.42°C0.08°C5m 屏蔽线25.28°C36.56°C36.40°C0.16°C20m 屏蔽线25.30°C36.62°C36.43°C0.19°C50m 屏蔽线25.29°C36.75°C36.45°C0.30°C可以看出长度增加主要带来的是偏差缓慢变大但波动幅度没有明显恶化说明屏蔽和滤波电路是有效的。如果出现 1°C 以上的偏差首先要怀疑探针跟被测物之间的热阻太大其次要检查 D/D- 线上是不是有大的共模电压差把两个测量点的地电位拉平一下偏差通常会回来。4.3 踩过的三个大坑第一个坑是本地温度自热。最开始我把 PJ85718DM 放在 STM32 和 RS485 收发器中间结果本地温度读数比环境高 10°C因为散热片和铜皮把热量直接传给了传感器。后面改版把传感器挪到板子边缘底下挖空铜皮同时在固件里做了一点热补偿修正才把误差压回来。第二个坑是探针线用了普通平行线没有双绞也没有屏蔽。在变频器附近测试时远程温度稳定在 30°C 的读数能偶尔跳到 45°C 再跳回来明显是变频器 PWM 干扰耦合进来。换双绞屏蔽线并单端接地后问题彻底消失。这个教训对我影响很大以后凡是远程模拟信号一律默认走屏蔽双绞。第三个坑是 Modbus 上电冲突。多个设备同时上电时RS485 总线如果空闲电平没拉好收发器输出状态不确定会导致第一帧数据乱掉上位机报通信故障。解决方法是每个节点上电后延时 500ms 再初始化 RS485 为接收状态同时 A/B 线加上下拉电阻固定空闲电平。5. 常见问题与排查速查表现场问题来来回回就那么几类我把高频故障和排查手段整理成了速查表。遇到问题先按表格过一遍大部分都能定位只有少数疑难杂症需要接示波器慢慢看。故障现象可能原因排查与解决温度恒为 -127 或 127D/D- 开路或短路传感器内部转换异常万用表量探针通断检查线缆是否折断D/D- 是否碰到电源脚温度读数跳变剧烈长线引入干扰滤波电容缺失换双绞屏蔽线靠近芯片端加 100pF 电容检查屏蔽层是否单端接地本地温度高于环境很多传感器靠近发热元件PCB 铜皮导热板级走线避开发热区传感器下方挖空铜皮固件做热补偿I2C 通讯偶尔超时或死锁总线电容过大上拉电阻偏大降低上拉电阻到 2.2kΩ降低 I2C 速率到 100kHz增加总线复位逻辑远程温度严重偏低探针未贴紧被测物体热阻过大重新涂抹导热硅脂用金属卡箍固定探针Modbus 偶发无响应从机地址冲突CRC 校验失败断帧时间不对检查拨码地址核对 CRC 低位高位顺序调整串口断帧判断时间上电后设备直接进入故障保护传感器供电未稳定连续无效计数触发上电后延时 200ms 再读温度把无效计数阈值从 3 调到 5RS485 总线上有信号但主站读不到终端电阻缺失或 A/B 极性接反总线两端各加 120Ω 终端电阻A 接 A、B 接 B个别设备 A/B 定义不同排除问题时拿万用表和逻辑分析仪配合最快。先确认供电再看 I2C 波形最后查串口帧结构。不要一上来就怀疑芯片坏了现场十次里有八次是接线和配置问题。6. 后续扩展与个人体会这套组合跑稳之后扩展方向其实很自然。想接更多测点就通过 I2C 地址扩展或者 TCA9548A 通道切换多挂几颗 PJ85718DM想做就地显示用 SPI 接口的段码屏或 12864 LCD把本地和远程两个温度直接显示出来想进物联网平台STM32F205RB 的资源足够跑一个轻量级协议栈把 Modbus 数据转成 MQTT 上发但要注意 HVAC 现场的网络隔离和安全管理别把控制网络直接暴露在公网里。我个人在几个项目里比较深的体会是测温系统看起来简单真正麻烦的是让它在现场各种恶劣条件下长期稳定。PJ85718DM 这种数字传感器简化了硬件设计STM32F205RB 提供了足够的软件余量两者配合可以让团队把精力放在协议、校准、失效保护这些真正影响客户体验的环节而不是天天跟模拟电路里的零点漂移和温漂较劲。最后再分享一个小技巧批量生产时别忘了在产线测试环节写一个传感器自检程序同时把本地和远程探针放进两个已知温度的恒温槽里自动记录每台设备的偏差并写入 Flash。这一步多花十分钟但能挡住一大批出厂后才发现测温不准的返工性价比极高。