做嵌入式温度采集这么多年,我印象最深的一次改动,就是把一路DS18B20换成了PJ85718DM配合STM32F407VGT6的方案。那是在一套商用HVAC风柜控制系统里,原来只测送风温度,后来甲方要求同时看机组回风口温度和变频器IGBT附近的温度,还要求本地屏和监控室都能读。DS18B20做多点串联倒是能解决“多路”的问题,但IGBT附近那一路温度很难用数字传感器直接贴,因为体积大、引线长、误差难控。换成PJ85718DM这种带远程二极管测温能力的专用温度传感器之后,一路I2C接口同时测本地环境温度和远端PN结温度,再通过STM32F407VGT6的串口走Modbus上报给楼宇自控平台,问题一下就拆干净了。
这篇内容我会从器件选型逻辑、硬件连接、I2C软件实现、远程上报链路到现场校准和踩坑经验完整过一遍,适合正在做HVAC控制器、电控柜、电机保护器这类项目的嵌入式开发者参考。哪怕你对PJ85718DM不熟,只要做过STM32 I2C读写,照着思路就能迁移。
1. 项目背景:PJ85718DM 在 HVAC/嵌入式测温里的定位
先说清楚这个标题里的“嵌入式和HVAC应用”到底意味着什么。嵌入式测温大家都懂,但HVAC场景跟普通消费电子差异很大:现场电磁干扰强,电机启停频繁,电源波动大,线缆可能要走一米以上,温度变化相对缓慢但精度要求并不低。冷冻站、空调箱、风机盘管这类设备,测温点往往分布在控制板、气流通道、管道壁和电机绕组几个位置,单纯测一路环境温度远远不够。
1.1 为什么不是 DS18B20 或热敏电阻:双通道测温的特殊价值
DS18B20是单总线数字温度传感器,便宜、好上手,但它只能测器件自身所在的局部温度。你要测IGBT模块外壳温度,传感器本体没法贴到那个位置,只能通过引线外接,可是DS18B20没有专门为长线远程测温设计,线拉长了受寄生电容影响,读数跳变、时序不稳定,现场维护成本很高。
PJ85718DM这类器件的价值在“两路测温在同一个芯片里”:一路本地通道测芯片周围空气温度,一路远程通道通过两个引脚接一个外部二极管(或者二极管接法的三极管),专门测远端目标物体的温度。这样传感器本体可以放在控制板上,只把一对细导线引到IGBT、电机外壳或管道表面,测温点布置就灵活多了。
热敏电阻虽然也能远程测,但每路都要做分压、滤波、查表、标定,通道多了电路面积和BOM成本成倍上升。PJ85718DM直接输出数字温度,I2C总线读回,多路要靠多颗芯片挂在同一条总线上实现,软件上几乎零成本。
1.2 “本地”与“远程”两个温度的含义
很多第一次接触这个器件的人会被“本地/远程”搞糊涂。这里的“本地”不是指局域网,而是指芯片自身所在位置的温度,一般用来测控制板环境温度,或者作为远程通道的冷端参考。“远程”则指芯片通过外部二极管感应的那个温度值,英文手册里经常叫Remote Diode Temperature或External Temperature。
HVAC系统里最典型的远程测温点:变频器IGBT散热器、电机绕组端部、压缩机油温探头、管道表面温度夹。这些点离控制板远、工作电压高、干扰大,用远程二极管测温天生就是为这种场景设计的——它只需要一对细线接到二极管两端,不接触高压回路,电气上隔离,安全性也好。
2. 硬件连接:STM32F407VGT6 与 PJ85718DM 的可靠握手
硬件设计是整个项目里最不能省心的地方。很多I2C测温失败的问题,根源不在软件,而在端接电阻、上拉电阻和布线方式。以下是我在HVAC控制板上的实际接法,可以作为第一版原理图的参考。
2.1 最小电路与 I2C 总线设计
PJ85718DM供电范围一般是3V到5.5V,和STM32F407VGT6的3.3V I/O电平匹配时,直接共用3.3V供电和I2C总线即可。SDA和SCL必须外接上拉电阻到VCC。总线速度我建议拉在100kHz或400kHz,HVAC场景布线长、干扰大,跑1MHz反而容易出问题。
上拉电阻阻值要按总线走线长度算。如果芯片就在STM32旁边走线不超过10cm,4.7kΩ就行了。如果I2C线需要从控制板拉到接线端子再接传感器板,总线电容会明显增大,我一般换成2.2kΩ或者1kΩ。阻值太小会增加静态功耗,太大则边沿变缓,容易触发错误。我的判断标准是:用示波器量SCL上升沿,保证小于1μs,别超过1.5μs。
ALERT引脚是开漏输出,也必须上拉。它用于温度越限时主动通知MCU,比STM32轮询状态寄存器省资源。我把它接到STM32F407VGT6的一个普通GPIO上,配置为外部中断。
硬件连接基本如下:
- PJ85718DM的VDD接3.3V,GND共地
- SDA、SCL分别接STM32F407VGT6的PB9、PB8(I2C1,实际以你的引脚规划为准)
- ALERT接PA0,复用为EXTI0
- 远程二极管正负极分别接器件的D+、D-引脚
2.2 远程二极管接法与 HVAC 现场布线
远程通道的核心测温器件是外部PN结。用三极管比用二极管好,因为三极管可以做成二极管接法,即集电极和基极短接作为正极,发射极作为负极,这样等效PN结的面积和理想因子一致性更好。工程上常用小信号三极管,比如2N3904、2N3906或者BC847这类,封装小、好固定。某些HVAC厂家会直接用TO-92封装的管子,用扎带绑在管壁或散热器上,再用导热胶固定。
D+和D-到三极管之间的线缆建议使用双绞线,长度尽量控制在1米以内。如果超过1米,远程二极管的引脚上并联一个1nF~10nF的陶瓷电容可以滤除共模干扰,但电容太大可能影响芯片内部的采样稳定性。另外,屏蔽层单端接地,不要两端都接,避免形成地环路。
我见过有人在远程通道上用普通整流二极管1N4007,结果读数满偏十几度。原因有二:一是大功率整流二极管的正向压降电流系数和芯片期待的小信号PN结不一致;二是封装大、热容量大,对快速温度变化响应慢。测轴承温度时这种惰性会掩盖真实故障,非常危险。所以远程三极管选型一定不能图便宜拿桥堆代替。
2.3 从机地址、ALERT 中断与 STM32 引脚分配
PJ85718DM从机地址由引脚配置决定,通常有一个地址选择位,可以把器件设成两个地址之一。我习惯把地址配置成不复用的独立地址,这样以后I2C总线上挂第二颗PJ85718DM测多路远程温度时不用改地址冲突。
STM32F407VGT6这边引脚规划:
- I2C1_SCL PB8,I2C1_SDA PB9,都配置为开漏输出,内部上拉可不开,因为外部已有上拉
- ALERT接PA0,配置为上拉输入+外部中断,下降沿触发
- 如果有需要,加一个状态LED接PD12,方便现场调试时观察温度越限状态
提醒一下,I2C引脚在STM32上要复用功能,用HAL库时先调用GPIO_InitStruct.Alternate = GPIO_AF4_I2C1,别漏掉这一句,否则SDA和SCL就是普通GPIO,通信挂死。
3. 软件实现:寄存器读写与温度计算细节
软件部分我会直接给可用的HAL库代码。读取PJ85718DM温度的过程本质是:通过I2C写入寄存器指针,然后读回数据,再按数据手册的温度格式换算成摄氏温度。整个过程跟读其他SMBus温度传感器差不多,但有几个细节需要注意。
3.1 I2C HAL 驱动的初始化与 SMBus 兼容性
PJ85718DM的时序兼容SMBus,STM32F407VGT6的I2C1可以工作在同一I2C电平下。即使不开启CRC校验也能通信,但要注意SMBus对时钟低电平超时、总线空闲时间有要求。HAL库默认的I2C时序参数在100kHz下能满足绝大多数场景,没有特殊需求不用手动调时序寄存器。
初始化代码直接复用标准HAL模板即可,但有一个很容易被忽视的点:I2C_InitStruct.ClockSpeed记得设成100000或400000,同时DutyCycle如果是400kHz要选I2C_DUTYCYCLE_2。如果这两项乱填,要么通信慢,要么波形错误导致无法应答。
3.2 读本地/远程温度:寄存器映射与符号扩展
PJ85718DM内部按SMBus温度传感器惯例,本地和远程温度寄存器是以0.125°C为LSB的12位数据。实际读取时,主寄存器给出整数部分,扩展寄存器给出小数部分。不同厂家地址偏移不同,但格式统一。下面我按常见映射给出代码逻辑,具体寄存器偏移量务必以你手里的芯片数据手册为准。
核心逻辑为:
- 向器件写入要读取的温度寄存器地址指针
- 连续读高字节和低字节
- 高字节按有符号数处理
- 低字节的扩展位作为0.125°C小数
static float read_temperature(uint8_t reg_high) { uint8_t h = 0, l = 0; float temp = 0.0f; uint8_t reg_ptr = reg_high; HAL_I2C_Master_Transmit(&hi2c1, PJ85718DM_ADDR, ®_ptr, 1, 100); HAL_I2C_Master_Receive(&hi2c1, PJ85718DM_ADDR, &h, 1, 100); reg_ptr = reg_high + 1; /* 低字节扩展寄存器 */ HAL_I2C_Master_Transmit(&hi2c1, PJ85718DM_ADDR, ®_ptr, 1, 100); HAL_I2C_Master_Receive(&hi2c1, PJ85718DM_ADDR, &l, 1, 100); int16_t val = (int16_t)((h << 8) | l); temp = (float)(val >> 3) * 0.125f; return temp; }高字节位7是符号位。负数场景在HVAC里很常见,北方冬季新风机组要测零下温度,如果把高字节当UINT8处理,-5°C会读成251°C,整个报警逻辑全乱。上述代码里先拼成INT16再右移3位,符号扩展就自动处理了。
3.3 报警阈值设置与中断处理
HVAC系统一般需要两个阈值:高温报警和高温回差。PJ85718DM提供了上下限寄存器,ALERT引脚在温度超限后拉低。这里要注意,很多温度传感器芯片的ALERT行为和SMBus标准不同,锁存与否由配置寄存器决定。我建议把ALERT设成锁存模式,温度恢复正常后软件读状态寄存器清除标志,避免现场干扰造成LED和蜂鸣器反复触发。
static void set_high_limit(uint8_t limit) { uint8_t buf[2]; buf[0] = LIMIT_REG_POINTER; buf[1] = (uint8_t)limit; HAL_I2C_Master_Transmit(&hi2c1, PJ85718DM_ADDR, buf, 2, 100); }3.4 关键代码:完整温度读取流程
采集任务不要直接在主循环里阻塞运行I2C。HVAC控制系统中,电机启停瞬间总线电压可能被拉低,I2C通信偶发NACK不是罕见事,所以必须加超时重试和结果滤波。我在项目中用简单的一阶低通滤波:
typedef struct { float current; float alpha; } LowPassFilter; float temp_filter(LowPassFilter *f, float raw) { f->current = f->current + f->alpha * (raw - f->current); return f->current; }alpha根据现场采样间隔调整,采样1秒一次时alpha取0.2左右,既能跟上管道温度变化,又能把开关电源纹波带来的微小跳变抹平。远程二极管的原始寄存器值如果连续跳动超过1°C,先别怀疑滤波参数,更可能是硬件问题,优先检查双绞线、去耦电容和屏蔽接地。
4. 从本地到远程:基于 STM32F407VGT6 的上报链路
标题里“本地与远程温度”还有另一层含义:数据不仅要能被本地上位机读走,还要能到远处的监控室。STM32F407VGT6的优势在这一步体现得很明显:串口、以太网MAC、USB应有尽有,无论走RS-485、Modbus还是直接出网口,外设资源都够用。
4.1 HVAC 场景下有哪些“远程”目标
我在项目里遇到过几种“远程上报”需求:
- 监控室楼宇自控系统通过RS-485总线Modbus RTU读取温度
- 现场触摸屏通过以太网读取温度
- 云平台或边缘网关通过4G DTU转发数据,DTU和控制器之间多用串口对接
不管最终走去哪,STM32F407VGT6内部都是先把温度数据整理成结构化变量,然后由不同外设(USART2、USART3或ETH)各自的协议栈消费。设计时先定义好一份“温度状态结构体”,再写接口,后续加任何上报通道都不用改底层采集逻辑。
4.2 RS-485/Modbus 上报实现思路
RS-485在HVAC行业几乎是最普及的现场总线,温度寄存器按Modbus保持寄存器定义,一个地址一个寄存器。发送时直接把温度乘10或乘100变成整数,接收方再除以缩放系数,这样既能保证0.1°C分辨率,又避免浮点数在Modbus中传输的尴尬。
Modbus上报我一般用定时器查询机制:主循环每100ms调一次数据采集,Modbus从机模块被外部读写请求触发时才组合应答帧。这样即便总线上的上位机频繁轮询,也不会阻塞温度采集。
4.3 以太网或串口转 Wi-Fi 的扩展方式
如果现场已经有以太网,STM32F407VGT6自带MAC,外接一个PHY就能跑轻量TCP/IP。工程上更省事的做法是串口接一个DTU模块,控制器只负责按串口协议定时上报温度字符串或二进制帧,DTU负责转成网络数据。这种方式实现快,而且控制器更换、调试时不用动网络配置。
4.4 上报帧设计、超时与总线冲突处理
温度上报帧不要裸发裸收,我建议至少包含:
- 帧头(固定字节,用来对同步,如0xAA 0x55)
- 设备地址或设备ID
- 数据长度
- 两路温度值,各2字节(整数部分+小数部分分开或统一放大)
- 校验字节(CRC16或简单的异或)
接收端校验失败直接丢帧,不要解析一半。发送端如果RS-485总线正在被其他设备占用,需要做防冲突机制,最简单的是加上发送前监听总线空闲时间的逻辑。这个细节在只有一台上位机时无所谓,现场一旦接入了多台调试设备,总线冲突就会冒出来,提前处理比事后救火好。
5. 实测结果与校准:把异常温度读数拉回真实值
软件调通不代表温度准。我拿到第一批样机后,先做了一轮从室温到模拟故障温度的标定测试,读数偏差和修正方法记录在这里。
5.1 室温环境下的标定测试
测试条件:控制板放在恒温间,远程三极管贴在铝块上,铝块放在恒温水浴中,用标准铂电阻温度计做参考。PJ85718DM默认配置下,本地温度读数与标准表的偏差在±1°C以内,远程通道如果接线短、没有干扰源也能在±1°C左右,这在HVAC应用里可以接受。
如果发现远程温度和真实温度有一个固定的差值,比如普遍偏低2°C,多半不是代码问题,而是器件内部偏置电流和二极管理想因子不匹配。这时要先检查三极管型号和接线,不要急着改软件补偿。
5.2 远程二极管的理想因子与串联电阻误差
远程通道测的是二极管的Vbe随温度变化关系。理想因子在1.0到1.2之间,不同三极管差异明显。芯片内部补偿参数有时可以通过偏移寄存器小幅调整,如果芯片只支持固定理想因子的补偿,就要在软件里做一次线性修正。
串联电阻是另一个大坑。我的三极管引脚到D+、D-引脚之间如果有一段长线,线电阻会和动态阻抗分压,造成测温偏高或偏低。工程上定一条规矩:远程三极管连接线必须控制在总长度1米以内,超过就加屏蔽双绞线,并且测量时保留一段不带屏蔽的“校准状态”,确认无电阻贡献后再固定安装。
5.3 校准寄存器与软件线性修正
如果数据手册里有偏置校准寄存器,那就好办。有些芯片会自动对串联电阻做补偿,写个0x00~0x1F的值就能把等效串联电阻压下来。我的建议是确定线缆长度和线规后固定写一次,不必动态调整。
软件修正可以用一元线性变换:T_real = a * T_read + b。a和b通过两组实测点(比如0°C冰水混合点和60°C温水点)拟合出来。修正只针对远程通道,本地通道一般不需要。修正之后再做一次重复性测试,确认三极管安装位置不变、线缆固定良好时读数稳定在±0.3°C以内,这时候再交付现场。
5.4 长时间运行稳定性与滤波策略
HVAC设备常年不间断运行,温度采集模块最容易出现的问题不是读错,而是漂移。三极管老化、线缆端子氧化、芯片自身发热都会让远程通道读数慢慢偏。我一般要求现场每半年做一次比对测试,如果偏差超过±2°C就在上位机校准页面输入偏移值,不用重新编译固件。
软件滤波方面,前面的一阶低通滤波器要注意不能套在报警通道上。报警越限必须用原始值判断,否则滤波会把短时高温尖峰抹掉,等发现时已经过了保护窗口。我实际的做法是:显示和上报用滤波值,报警判断用原始瞬时值。
6. 现场踩坑与调试技巧
最后这部分是我最想写的内容。这个项目从实验室到现场,我踩的坑一个接一个,其中有些问题在实验室里完全复现不出来。
6.1 I2C 通信偶发失败:总线电容与上拉电阻的博弈
第一版样机在测试台上运行两天没有任何I2C故障,装进电控柜接上电机线缆之后,一天内出现数次总线卡死。定位了很久才发现问题不在软件时序,而在总线上拉电阻太大,现场强干扰让SDA线上的毛刺超过了容限。
解决手段有两步:把上拉电阻从4.7kΩ换成2.2kΩ,同时在SDA和SCL对地各加100pF电容。加电容是双刃剑,滤波效果好,但会降低边沿速率、限制总线距离。后来确认走线只有10cm,100pF没问题。如果你的I2C线长超过30cm,不要照抄这个参数,优先缩短走线,而不是加更大的电容。
6.2 远程温度跳动 10°C:二极管接法与共模干扰
有台空调箱送风温度读数在实测试时上下跳了差不多10°C,数据记录曲线的毛刺和变频器输出频率完全同步。检查发现远程三极管的两根引线没绞在一起,而是沿着线槽和变频器输出线并排走了30cm,被耦合了大量共模干扰。
把两根引线绞成双绞线,并让它们远离变频器输出线之后,毛刺消失。如果空间受限实在避不开,给三极管两根线套磁环也有一定效果,但只是抑制手段,真正靠谱的还是物理隔离和双绞。还有一次是远程三极管集电极和基极没有短接,接成了普通二极管用法,温度读数也是明显异常,这个封装上的细节很多人容易漏。
6.3 电源退化导致本地温度整体偏高
现场有一块控制板反馈本地温度比实际高4°C,拆回来测量发现是PJ85718DM的VDD引脚上纹波过大,芯片内部参考源被干扰。换上低ESR的10μF陶瓷电容之后,读数恢复正常。测量温度传感器时,很多人只关注I2C线,忽略了电源质量,实际上供电纹波对内部ADC影响很大,尤其是远程通道还在用恒流源激励时,电源噪声会直接叠加上去。
6.4 几个值得保留的经验
归纳一下我这轮做下来的几条土经验:
- 原理图上给PJ85718DM的VDD和GND之间加0.1μF和10μF双电容,位置尽量靠近芯片引脚
- ALERT引脚必须处理,就算不用中断,也要接上拉并留给上位机查询,方便现场诊断
- 代码里给I2C操作包一层状态机,不要在中断里直接阻塞收发
- 远程三极管的固定位置要设计成可拆卸式,比如用端子夹或扎带,方便现场换件和校准
- 不要把滤波后的温度用于报警,报警判断必须基于原始数据,宁可误报一次也不能漏报
PJ85718DM本身不是什么神秘器件,STM32F407VGT6也是老熟人,这套系统的难点从来不在跑通I2C,而是在真实HVAC环境里让温度测准、传稳、跑长久。希望这篇内容能帮你少走一点弯路。