资讯动态

嵌入式温度监测实战:基于PIC18F8520与PJ85718DM的HVAC双点测温方案

发布时间:2026/10/22 16:59:29 来源:尧图企业网站定制
做HVAC控制器和嵌入式温度监测这些年我把NTC、PT100、单总线18B20、I2C数字传感器基本都试了一圈最后在需要同时管住板级本地温度和远端盘管温度的项目里稳下来的方案是PJ85718DM加PIC18F8520。PJ85718DM是一片带SMBus/I2C接口的数字温度传感器兼容LM75A/JC42这类常见封装内部直接完成模数转换不需要像NTC那样插分压电阻和查标定表PIC18F8520则承担主控制器角色通过I2C总线轮询两个传感器一个放在主控板上测本地温度另一个用四线线缆拉到远端测出风或盘管温度。整个系统只占一条I2C总线、两个地址、一个外设模块硬件简洁逻辑清楚很适合HVAC控制器、变频驱动器和各类嵌入式设备做多点温度监测。这篇记录就从硬件选型、总线设计、固件实现、调试踩坑和扩展方向几个层面把这套方案完整拆开讲清楚。1. 项目拆解为什么要做本地加远程双点测温1.1 本地温度与远程温度是两类完全不同的需求先说“本地”和“远程”这两个词。很多第一次接触嵌入式测温的人容易误会以为本地温度是本机CPU温度远程温度是网络拉远到机房服务器的温度。在我做的HVAC和嵌入式场景里定义要具体得多。本地温度指主控板所在位置的空气温度。PCB上密密麻麻的功率器件、继电器、变压器运行时会把板上局部温度抬得很高温度传感器放在板上无非两种用途一是做板级热保护二是参与风扇调速防止机箱内积热。这个测量点在主控板内部走的是PCB铜箔上的焊盘信号路径短设计起来没有太多物理限制。远程温度则指离开主控板一定距离的测点典型的是HVAC机组里的风管回风温度、表冷器进出风温度、压缩机的排气管壁温或者嵌入式设备里散热器末端、电池包内部温度。这些测点没法焊在主板上必须通过连接器和线缆拉到远端。远程测温比本地复杂的地方在于线缆会引入电阻、电容和噪声供电会在线上产生压降插接件可能松动氧化这些都会影响最终读数稳定性所以不能照搬板级设计。这两类测温需求在同一个项目里经常同时存在。比如一台组合式空调柜控制器本身就是个发热源主控板需要测自己的环境温度来管理散热风扇与此同时控制器还要知道送风温度、回风温度用来做PID调节。以前我见过不少工程师图省钱把控制器板子上的传感器读数当回风温度用结果传感器紧挨着变压器温度读数集体偏高控制曲线全部失真。把本地温度和远程温度分开采集不是堆功能而是工程上必须解决的问题。1.2 方案选型数字I2C传感器为什么比NTC和单总线省心这块我多说几句因为选型直接影响后面的走线、抗干扰和软件复杂度。NTC热敏电阻是成本最低的方案一颗电阻几分钱精度也够用但它有几个隐性成本需要基准分压网络、需要ADC通道、需要查表或多点标定非线性更关键的是远程测温时线阻会直接串进分压网络产生系统误差。普通两线制NTC拉出两三米线阻稍微波动温度可能偏出好几度不适合远程可靠测量。PT100测得更准但配套的恒流源、调理电路、三线四线制接法又贵又占地方在消费级和轻工业HVAC场景里属于杀鸡用牛刀。单总线18B20这类器件我也用过优点是真正一线总线挂多个器件时只需要一条数据线缺点是协议时序要求严格中断里操作容易失步而且它的器件编号管理、上电复位时序在MCU资源紧张的时候会很折腾。更麻烦的是单总线在超过一定长度后对寄生电容非常敏感现场如果用了劣质导线通信不稳定是常态。PJ85718DM走的是标准I2C/SMBus接口协议成熟时序宽容直接用主控芯片的硬件I2C外设就能驱动不需要软件模拟方波。它内部有Σ-Δ ADC出厂做过校准温度值以数字形式直接给出省掉了线性化表和分压误差。封装和寄存器与LM75A、JC42这类常见温度传感器引脚兼容这意味着供应链上可以多选几个型号互换不至于被单一货源卡住。它的A0/A1地址引脚支持4个不同地址一颗总线上挂4颗传感器做本地加远程双点绰绰有余还能扩展到多点。这个特性对我后面做多测点组网非常关键。精度方面我在实际板上对比过PJ85718DM在0到70℃范围内的读数误差在±0.5℃级别CPU高速跑起来板面到70℃属于正常现象这个精度对HVAC的舒适度控制和嵌入式热保护完全够用。转换周期大约在几十到一百毫秒级别HVAC温度变化很慢甚至气压波动、门开关这类扰动都要好几秒才能反映过来这个延迟不影响控制效果。1.3 PIC18F8520在整套方案里的分工PIC18F8520这颗8位MCU属于PIC18F系列里引脚和资源都比较充裕的型号内置MSSP外设可以硬件实现I2C主模式这就是整个测温方案的基石。硬件I2C的好处是字节的移位、时钟、ACK/NACK都由外设管理CPU只在合适时刻读写数据寄存器延迟抖动比软件模拟小很多调试起来出问题的概率也低很多。它的片内存储和RAM足够放下测温、滤波、报警、显示的全套逻辑。我在这套系统里同时还要驱动段码LCD、读取按键、控制继电器和蜂鸣器PIC18F8520的IO数量和定时器能撑得住。另外它还有多路10位ADC虽然主测温走I2C但空出来的ADC可以留给NTC做辅助校准、电偶冷端补偿、母线电压采样等杂活。还有一点是5V逻辑电平。HVAC现场是强电环境接触器吸合、压缩机启停会产生大量电磁干扰CMOS级别的5V信号比3.3V信号抗干扰能力好一些I2C总线直接接5V区域时电平匹配简单。这也是我把这颗芯片和PJ85718DM都选在5V电源域工作的原因之一。不少人一上来就想着上ARM Cortex-M或者更高端的处理器但对这个量级的应用一颗成熟稳定的8位MCU开发周期短、成本低、维护容易比盲目堆算力更实际。2. 硬件连接与总线设计中的关键细节2.1 供电与上拉电阻怎么定先说供电。PJ85718DM常见工作电压范围在1.8V到5.5VPIC18F8520工作电压范围也比较宽我直接让两个器件都跑在5V。5V电源域的噪声容限大和板上其他逻辑电平统一省去电平转换芯片。远程传感器那一端同样用5V和主控共地通过线缆里同一路电源供电。需要注意去耦本地传感器在VCC和GND之间放一颗100nF电容尽量靠近芯片引脚远程传感器小板上也放同样的电容。HVAC柜里接触器动作频繁电源会有瞬态跌落去耦电容能吸收一部分尖峰PIC18F8520内部的BOR电路也会在电压跌落时复位系统防止逻辑跑飞。上拉电阻是I2C总线最容易忽略的关节。I2C协议的SDA和SCL都是开漏结构必须接上拉电阻才能输出高电平。上拉电阻有一个可用取值范围下限由芯片的灌电流能力决定上限由总线电容和通信速率决定。取值太小低电平时灌电流太大取值太大沿太慢时钟和数据都上不去。我实测中标准模式100kHz时单板上两颗传感器上拉4.7kΩ很稳定一旦把远程传感器用线缆接出去总线电容变大4.7kΩ可能不够需要把上拉降到2.2kΩ甚至1kΩ。具体估算可以按这个思路来上拉电阻下限约等于(VCC - VOLmax) / IOLVOLmax是开漏引脚低电平的最大电压IOL是允许灌入电流典型值算出来在1kΩ到2kΩ附近上限则需要满足RC时间常数电容包括器件引脚电容、PCB走线电容和线缆电容远程线缆每米可能有几十pF线长两米时总线电容直奔上百pF100kHz下再用4.7kΩ就会让上升沿明显变圆。所以我的习惯是本地单板用4.7kΩ接了远程线缆后直接在主控板上换成2.2kΩ或1kΩ然后把通信速率降到50kHz到100kHz不要硬跑400kHz快速模式。2.2 两个传感器的地址分配与远程走线PJ85718DM的地址由A0、A1两个引脚的高低电平决定。我的方案里本地传感器A1接地、A0接地地址落在0x48远程传感器A1接地、A0接高地址落在0x49。两颗芯片都能挂在同一条I2C总线上CPU通过地址就能区分本地和远程。远程传感器单独做了一块手指大的小板只放了PJ85718DM、去耦电容、可选小上拉。小板通过四芯线缆和主控板连接四根线分别是VCC、GND、SCL、SDA。线缆建议用带屏蔽的双绞线双绞对SCL/SDA屏蔽层在靠近主控板一端接地。屏蔽层单端接地是常识HVAC柜里变频器和接触器是主要的噪声源屏蔽层能明显降低耦合进来的干扰。线长控制在1到2米以内直连可行如果超过两三米总线电容和信号完整性问题会突出需要添加总线缓冲芯片或者改用其他传输方式。这个方案里还有一个细节远程小板的SCL和SDA不要自己再加一次上拉整条总线只在主控端统一上拉。两端都上拉会让等效并联阻值过小低电平时灌电流偏大波形反而变差。如果远程板有预留上拉位必须保持不贴。2.3 报警输出与HVAC联动思路PJ85718DM带有OS比较器输出引脚可以独立于主控MCU工作。我在固件里给它设置了高温阈值TOS和迟滞THYST温度超过设定值后OS引脚会从高电平拉低我把它接到了PIC18F8520的一个外部中断引脚上。这让报警响应不用靠主循环轮询即使MCU正在处理显示刷新或通信任务过温信号也能立刻打断进来。在HVAC里我可以把这个信号用作电脑板保护逻辑出风温度超过阈值时OS引脚触发中断主控立刻关掉电加热或者压缩机同时面板上显示故障代码。迟滞值要设置合理我通常设1到3℃防止温度在阈值附近波动导致OS引脚反复翻转继电器和接触器频繁吸合可不是什么好事。3. 固件实现I2C读取温度与数据换算3.1 MSSP模块初始化回到PIC18F8520的MSSP模块它既能做SPI也能做I2C。把它配置成I2C主模式需要操作几个寄存器SSPCON1里设置主模式、SSPCON2清零、SSPSTAT设置时钟沿和SMP位SSPADD设置波特率。波特率公式在数据手册里写得很清楚I2C主模式下SSPADD Fosc / (4 × FSCL) - 1假设晶振Fosc是40MHz目标FSCL是100kHz算出来SSPADD 40e6 / (4 × 100e3) - 1 99。这里-1的原因手册里有说明不过实际项目中直接算出99即可。如果用内部振荡器或PLL倍频后的频率注意把实际时钟频率吃进去别把晶振频率和指令周期搞混。初始化代码大概长这样#define I2C_CLOCK 100000UL void I2C_Init(void) { SSPCON1 0b00001000; // I2C主模式 SSPCON2 0b00000000; // 关闭所有操作 SSPSTATbits.SMP 0; // 标准模式100kHz SSPSTATbits.CKE 0; SSPADD (unsigned char)(((_XTAL_FREQ / 4) / I2C_CLOCK) - 1); PIR1bits.SSPIF 0; SSPCON1bits.SSPEN 1; // 使能MSSP模块 }使能模块之前需要先确认SDA和SCL引脚配置为外设功能如果引脚被默认设成数字IO输出口总线就拉不起来了。这个坑我踩过一次后面在调试实录里展开讲。3.2 温度寄存器读取与换算PJ85718DM的温度值存在0x00这个寄存器里。完整读一次温度时序分四步发START、发设备地址加写位、发寄存器地址0x00、重发START、发设备地址加读位、读两个字节、最后发NACK和STOP。读取两个字节时高字节在前。这里最关键的是把两个字节拼成16位有符号数然后再按分辨率右移。我在代码里只固定使用12位分辨率配置寄存器里对应位设好之后换算公式统一是count (int16_t)((uint16_t)msb 8 | lsb) 4; temperature count × 0.0625℃为什么是右移4位12位分辨率下有效温度数据占16位寄存器的最高12位最低4位固定为0把16位带符号数算术右移4位后得到以0.0625℃为单位的带符号计数。count乘0.0625就是实际温度。用有符号右移保证负数时符号扩展正确不然零下温度会算成几百度。几个典型读数可以自己验算25.0℃时寄存器高字节0x19、低字节0x00拼出来0x1900右移4位得到400乘0.0625得25.0℃-25.0℃时寄存器的16位字是补码表示的负值右移后得到-400乘0.0625得-25.0℃0.5℃时得到8乘0.0625为0.5℃。这些值都可以拿来做自检程序里写进测试向量防止有人改代码时把字节序改错。完整读取函数我写成这样int16_t PJ85_ReadTemp(uint8_t devAddr) { uint8_t msb, lsb; int16_t word; // 发送地址写发送寄存器地址0x00 I2C_Start(); if (I2C_WriteByte((devAddr 1) | 0) 0) return SENSOR_ERR; if (I2C_WriteByte(0x00) 0) return SENSOR_ERR; // 重发START发送地址读 I2C_RepeatedStart(); if (I2C_WriteByte((devAddr 1) | 1) 0) return SENSOR_ERR; msb I2C_ReadByte(ACK); lsb I2C_ReadByte(NACK); I2C_Stop(); word (int16_t)(((uint16_t)msb 8) | lsb); return word 4; // 返回以0.0625度为单位的计数 }实际工程里返回值转成浮点还是保持定点计数要看后续用途。如果只是比较阈值、做PID我建议全程用定点数避免浮点库占用大块资源。需要显示时再在显示函数里统一转一次字符串。3.3 软件滤波、阈值报警与故障处理温度传感器读数在HVAC现场偶尔会跳变尤其是远程传感器线缆受接触器干扰时一次转换结果可能突然跳出去好几度。我在读取后加了一阶低通滤波filtered filtered (new_count - filtered) / N;N取4到8HVAC温度变化慢取4时手感平滑又能跟上正常变化。N值从1开始加载避免启动时滤波值一直从零慢慢爬。其实也可以用滑动平均但一阶滤波代码简单、内存开销小PIC18F8520上跑完全没问题。阈值报警我做了两级传感器内部OS引脚负责硬保护适合直接关断负载固件里再维护一个软件阈值适合报警提示和风扇启停。软件阈值的好处是修改阈值不用重新写传感器配置寄存器调试阶段换个值直接改宏定义重编译就行。故障处理方面I2C远程传输不是永远可靠的。我在每次读取后检查ACK和超时标志连续3次失败就认为该传感器离线。离线后先把之前最后一次有效值保持住避免控制逻辑拿到一个极端默认值导致误动作同时置故障位让上位机或面板报故障。这里有一个重要的设计原则传感器出错的读数一定要和真实温度区分开否则PID或者保护逻辑会被假数据带偏。我用的方法是定义SENSOR_ERR为0x7FFF这种远离真实温度范围的哨兵值调用方收到哨兵值时只做故障处理不参与控制计算。3.4 轮询调度与HVAC控制联动主循环里轮询两个传感器时还要考虑转换周期。PJ85718DM一次转换大约几十毫秒到一百毫秒每次读取之间稍微隔开不要紧挨着连续读。我在主循环里用一个10ms时基做非阻塞调度先读本地隔50ms再读远程再配合滤波和报警检查。这个调度节奏对HVAC足够了实测温度曲线平滑。控制联动上温度值最终会汇入一个统一的逻辑层本地温度负责风扇转速、面板温度显示远程温度负责PID回风温度控制、过热保护、化霜判断。我把两个温度值封装成带时间戳的结构体每次控制周期开始时取最新值这样即使某次读取不及时控制逻辑拿到的也是刚更新的数据不会因为一次轮询失败就误判。4. 调试经验与问题排查4.1 I2C总线卡死的恢复办法I2C最经典的问题是总线被拉死。现象是程序跑着跑着SCL正常但SDA一直为低或者干脆两个脚都低。原因基本都出在从机收到了半个字节后主机异常复位从机状态机卡死还在等着后续时钟。恢复办法是主机侧用GPIO模拟发出9个时钟脉冲把卡死的从机顶出去再发一个START或STOP让总线回到空闲态。我把它做成一个I2C_BusReset函数在每次通信失败或检测到SDA长时间为低时调用。注意这9个脉冲期间SDA要置为高让从机有机会在脉冲结束后释放SDA。实际项目中远程线缆插拔瞬间偶尔会触发总线卡死有了这个复位函数系统能自动恢复不用整机断电。4.2 温度读数跳变的排查有一回现场反馈远程温度偶尔跳到-50℃又跳回来我一开始怀疑滤波不够把滤波参数调重之后效果不理想。后来把串口打印打开一边打印原始寄存器值一边观察发现跳变发生在接触器吸合的瞬间而且跳变方向始终是偏低不是偏高。顺着这个现象查下去确认是远程传感器小板的排针和线缆插头氧化接触电阻变大插拔时偶尔接触不良SDA线上出现毛刺读到的字节错位。换了镀金排针、重新压接端子后问题消失。这类问题在HVAC柜里特别常见强电接触器每一次动作都在轻微震动整个柜体连接器质量不行迟早出问题。建议远程传感器的连接器选择带锁扣的装配后打胶固定避免震动松脱。还有一个容易忽略的点是PJ85718DM的转换结果更新不是瞬时的寄存器可能正在更新时被你读取。理论上I2C读取时数据字节是锁存的不会读到一半的数据但极个别兼容芯片行为有差异。稳妥做法是连续读两次如果两次差值超过1到2个LSB就再读一次取稳定值。这个逻辑放在滤波之前能滤掉绝大多数瞬时毛刺。4.3 远程传输的误差修正远程传感器和主控之间有几条线长距离走线线阻带来的最大问题是电源压降。PJ85718DM工作电压范围宽但如果远端电压被拉低到某个边缘区内部参考电压会跟着变化读数就会整体偏移。我实测过一条三米长的0.25平方毫米导线满载时远端电压比主控端低0.15V左右对读数影响不算大但如果是几十米线缆、细导线、多颗传感器共用一个远端电源误差就明显了。修正办法也不复杂远程线的VCC用粗一点的导线实在不行就在远端小板旁边加一颗低压差的电容储能再不行就提高给传感器供电的电压档位只要在器件允许范围内。供电稳了温度数据自然会稳。还有一个误差是线缆本身的热电效应。SCL和SDA的铜线在两端焊点如果存在温差会引入微小的额外电压但这个量级对数字传感器没有直接影响真正要命的是大面积铺地形成地环路。所以我在远程小板设计上把模拟地、数字地、电源地都统一到一个单点避免形成地环路噪声。4.4 工具与现场检查清单调试这类I2C测温系统我的工具优先级是逻辑分析仪排第一。逻辑分析仪能直接看到START、地址、字节序、ACK和时序长度比示波器容易上手。示波器主要看模拟波形质量尤其上拉电阻改完之后看上升沿有没有明显塌陷。串口打印则负责看业务层面的数据我习惯在固件里预留串口调试命令能随时调出两个传感器的原始寄存器、滤波后值、故障码这样现场问题不用反复烧固件。现场如果出现温度反复异常我有一套固定排查顺序先看读数是不是固定的某个极端值比如-128或127如果是优先怀疑通信错误再看读数是否随扳手靠近机柜时变化如果是走线屏蔽和滤波有问题最后看读数是否整体偏移如果是检查远端供电和共地。异常现象优先怀疑方向快速检查手段读数为固定极端值I2C通信错误、从机地址错误逻辑分析仪抓总线核对从机地址读数随机跳变接触不良、干扰、转换毛刺观察跳变时机检查连接器加大滤波读数整体偏移远端供电不足、线阻压降万用表测远端VCC换粗电源线总线偶尔卡死插拔瞬间状态机错乱加9脉冲复位函数检查SDA电平5. 这套方案还能怎么扩展5.1 HVAC多温度点组网PJ85718DM支持4个地址一条I2C总线上插4颗很稳。HVAC场景里主控板本地温度、回风、出风、盘管表面温度四个点刚好可以用完。每个点放在独立小板上插接件引出主控统一上拉固件里做成一张表来管理传感器地址、名称、滤波系数和报警阈值。这样新增测温点时不需要改主控板硬件只要在配置表里加一行。多点测温在HVAC里能做的事情就多了回风温度和出风温度之差可以估算制冷量盘管温度结合水温能判断化霜时机多点平均温度能避免单一测点被局部气流干扰。这些都是单点方案提供不了的信息。5.2 嵌入式设备机箱监测嵌入式设备里比如工控箱、变频器柜、通信电源也经常需要同时监测壳内环境温度和某几个功率器件的热点温度。壳内环境温度用本地传感器功率器件热点用远程传感器硬件方案完全一样。远程传感器可以贴近IGBT散热片或者电池表面用导热胶固定温度反映的是器件所在位置的空气或外壳温度不直接测结温但作为热保护参考足够。这类应用里PIC18F8520的多路ADC还能顺便采样母线电压、电流互感器输出形成一套完整的功率设备监控系统比单纯做测温的性价比高很多。5.3 往分布式节点演进如果远程测点超过四五米或者数量超过4个I2C总线就不合适了。我倾向于把每个远端节点做成独立的小MCU加PJ85718DM节点本地完成采集和滤波然后通过RS-485或者PIC18F8520自带的CAN接口把温度值上报主控。每个节点有独立地址通信协议用Modbus这类成熟总线协议。这样单条总线可以带几十个节点传输距离几十米抗干扰能力也更强。本地节点和远程节点还可以运行同一份固件只是角色配置不同维护成本低。这套从单板到分布式演进的路子我在后面一个多联机空调组网项目里实践过主控本地用PJ85718DM测控制器温度每台内机节点上报出风温度整体结构干净清晰。PIC18F8520自带CAN外设做节点间总线通信时连外部协议芯片都省了资源正好合适。我个人在实际项目里踩过几次坑之后最大的体会是PJ85718DM这类I2C数字温度传感器成败不是传感器本身而是总线和电源的细节。很多人把远程传感器接到两三米线上通信卡了、读数跳了就怪芯片其实把上拉电阻按线缆调整到位、速率降到50到100kHz、做好屏蔽和滤波大部分问题都能解决。后续如果再让我做类似的方案我会把远程小板做成标准化模块加上防插反和锁扣连接器固件里多留几个调试字段现场维护会轻松很多。希望这篇记录能帮你少走几条弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑