基于PJ85718DM与PIC32MX795F512L的嵌入式温度监测系统设计与实现 1. 项目缘起与整体设计思路嵌入式温度监测这件事说起来简单做起来全是细节。我最早接触这类需求是在一个HVAC控制器的改造项目里当时的要求很朴素本地要能看到机房回风温度远程要能在中控室读到同一路数据精度要求±0.5°C刷新率不低于1Hz而且两路数据必须来自同一个物理测点不能各测各的。这个约束直接把方案选择范围压缩得很窄——要么用一颗支持双路输出的数字温度传感器要么用两颗传感器做校准匹配前者显然更省心。PJ85718DM就是在这个背景下进入视野的。它是一颗I2C接口的数字温度传感器本地测温范围覆盖-40°C到125°C典型精度在-10°C到85°C区间内可以做到±0.5°C分辨率可配置到0.0625°C。更关键的是它支持多地址配置同一路I2C总线上可以挂多颗这对于HVAC场景里需要同时监测送风、回风、盘管表面温度的应用来说非常实用。而PIC32MX795F512L作为主控512KB Flash、128KB RAM、80MHz主频带多个I2C外设和以太网MAC跑一个本地显示加远程上报的任务绰绰有余。整体设计思路可以概括为三层感知层由PJ85718DM负责温度采集控制层由PIC32MX795F512L负责数据读取、滤波、本地显示和协议封装传输层通过板载以太网或串口转无线上报的方式把数据送到远程端。这个分层的好处是每一层职责清晰调试的时候可以单独隔离——传感器读数不对就查I2C波形本地显示不对就查驱动远程收不到就查网络配置不会一锅粥。为什么不用模拟传感器加ADC的方案我试过。NTC热敏电阻加分压电路成本确实低但线性化要查表或者跑Steinhart-Hart公式批量生产时每颗NTC的一致性差异还得单独标定产线工时上去了。PJ85718DM出厂就是数字校准的I2C读回来就是摄氏度省掉的标定环节在批量场景下价值很大。当然它的成本比NTC高所以选型时要看产品定位——如果是几十块钱的消费级温控器NTC够用如果是机房精密空调或者工业HVAC数字传感器带来的精度和一致性优势就值回票价。还有一个容易被忽略的点本地与远程的数据一致性。很多方案本地用一颗传感器、远程用另一颗结果两边读数差0.3°C运维人员就会质疑到底信哪个。PJ85718DM的方案里本地显示和远程上报读的是同一颗芯片的同一个寄存器数据同源这个争议从根上就没了。这一点在客户验收时特别重要我吃过亏后来所有项目都坚持数据同源原则。2. PJ85718DM与PIC32MX795F512L的硬件衔接细节2.1 传感器外围电路的关键参数PJ85718DM的典型应用电路不复杂但有几个参数不能拍脑袋。供电电压范围是2.7V到5.5V我一般用3.3V和PIC32的IO电平一致省掉电平转换。去耦电容用0.1μF陶瓷电容紧贴VDD引脚放置再并一个1μF的钽电容做低频滤波这个组合在电机启停频繁的HVAC环境里能明显抑制电源纹波对测温的干扰。I2C上拉电阻的选择经常被忽视。总线速率100kHz时4.7kΩ是常见值如果跑到400kHz建议降到2.2kΩ。但HVAC设备里I2C走线可能比较长分布电容大上拉太强会导致上升沿过冲太弱又爬不上去。我的经验是先用2.2kΩ然后用示波器看SCL和SDA的上升沿如果超过1μs还没到VIH就继续减小如果看到明显振铃就适当增大。这个调试过程花不了十分钟但能避免后面一堆通信偶发失败的问题。地址配置方面PJ85718DM通过ADDR引脚接不同电平可以设置多个I2C地址。实际布线时我会把ADDR引脚通过一个0Ω电阻接到VDD或GND而不是直接硬连这样万一地址冲突改电阻比割线方便。多传感器场景下我习惯按物理位置分配地址比如0x48给回风、0x49给送风、0x4A给盘管软件里用宏定义映射代码可读性好很多。2.2 PIC32MX795F512L的I2C外设配置PIC32MX795F512L有两个I2C外设I2C1和I2C2。我通常把温度传感器挂在I2C1上I2C2留给EEPROM或者别的慢速外设避免总线争用。配置的时候注意几个寄存器I2CxBRG决定波特率计算公式是I2CxBRG (FSCL / (2 * FSCL)) - 2其中FSCL是外设总线时钟。假设外设总线跑40MHz目标100kHz那BRG就是(40M / (2 * 100k)) - 2 198。这个值要算准偏差太大会导致通信不稳定。中断优先级也要规划好。温度采集对实时性要求不算极高我一般把I2C中断设成中等优先级比以太网中断低一级比串口调试中断高一级。这样网络数据包处理不会打断温度读取的时序但调试打印也不会把温度采集挤掉。PIC32的中断优先级有7级够用了。还有一个坑PIC32的I2C在从机模式下有时钟拉伸支持但主机模式下如果从机拉低SCL硬件不会自动处理需要软件超时机制。PJ85718DM一般不会拉伸时钟但总线上的其他器件可能会。我在I2C读写函数里加了超时计数超过一定循环次数就报错重试避免死等。2.3 本地显示与远程接口的硬件规划本地显示我一般用1602或者12864液晶并口驱动占用IO多但刷新快。如果IO紧张可以用I2C转接板但那样I2C总线上就多了个设备地址要重新规划。远程接口方面PIC32MX795F512L自带以太网MAC外接PHY芯片就能跑TCP/IP。如果现场没有网线可以用UART转无线模块但要注意无线模块的供电和天线布局HVAC机柜里金属多信号衰减厉害天线最好引到柜外。电源设计上PIC32和传感器可以共用3.3V但以太网PHY通常需要2.5V或1.8V内核电压要单独用LDO。我在一个项目里图省事把PHY也接3.3V结果发热严重夏天机柜内温度到60°C时PHY开始丢包。后来加了散热片和独立LDO才稳定。这个教训是HVAC环境的高温不是闹着玩的所有器件的降额设计要留足余量。3. 固件实现从寄存器读取到数据上报3.1 PJ85718DM的驱动编写要点PJ85718DM的寄存器不多核心就是温度寄存器和配置寄存器。温度寄存器是16位高12位有效低4位是标志位。读取的时候先发地址写再发寄存器指针然后重启发地址读连续读两个字节。转换公式是如果高12位最高位是0温度就是raw * 0.0625如果是1表示负温度要先取补码再乘。float pj85718dm_read_temp(uint8_t addr) { uint8_t buf[2]; i2c_start(); i2c_write(addr 1); i2c_write(0x00); // 温度寄存器指针 i2c_restart(); i2c_write((addr 1) | 1); buf[0] i2c_read_ack(); buf[1] i2c_read_nack(); i2c_stop(); int16_t raw (buf[0] 8) | buf[1]; raw 4; // 低4位是标志丢掉 if (raw 0x0800) { // 负温度 raw | 0xF000; // 符号扩展 } return raw * 0.0625f; }这段代码看着简单但有几个细节容易翻车。第一raw 4之后要判断符号位12位有符号数的范围是-2048到2047对应-128°C到127.9375°C。第二I2C的restart时序要正确有些驱动库的restart实现有问题会导致读回来全是0xFF。第三如果总线上有多个PJ85718DM每次读之前要确认地址正确我见过地址配错导致读的是另一颗传感器的数据本地显示和远程上报对不上查了半天才发现是地址宏定义写错了。配置寄存器里可以设置分辨率默认是12位转换时间约30ms。如果追求低功耗可以降到9位转换时间约5ms但分辨率变成0.5°C。HVAC应用一般12位够用刷新率1Hz的话30ms转换时间完全不影响。3.2 数据滤波与异常值处理原始温度数据直接显示会跳得厉害尤其是HVAC风道里气流波动大的时候。我一般用滑动平均加限幅滤波。滑动平均窗口取8个点既能平滑波动又不会引入太大滞后。限幅滤波是防止单次异常值污染整个窗口比如传感器偶发通信错误读回一个-128°C如果不处理滑动平均会被拉低好几度。#define WINDOW_SIZE 8 float temp_window[WINDOW_SIZE]; uint8_t window_idx 0; float filter_temp(float new_temp) { static float last_valid 25.0f; // 限幅单次变化超过5°C认为是异常 if (fabsf(new_temp - last_valid) 5.0f) { return last_valid; } last_valid new_temp; temp_window[window_idx] new_temp; window_idx (window_idx 1) % WINDOW_SIZE; float sum 0; for (int i 0; i WINDOW_SIZE; i) { sum temp_window[i]; } return sum / WINDOW_SIZE; }限幅阈值5°C是拍脑袋定的吗不是。HVAC系统里回风温度在正常运行时变化率不会超过1°C/s1Hz采样下相邻两点差5°C几乎不可能是真实变化。如果是快速温变场景比如冷库开门那阈值要放宽到10°C。这个参数要根据实际工况调没有万能值。还有一个细节上电初始化的处理。刚上电时滑动窗口里全是0如果直接参与平均前8个读数会偏低。我的做法是上电后先连续读8次填满窗口再开始正常输出。这8次读数的间隔可以短一点比如100ms一次这样1秒内就能进入稳定状态。3.3 本地显示与远程上报的协同本地显示和远程上报的刷新率可以不同。本地液晶刷新太快会闪我一般500ms刷一次远程上报可以1秒一次减少网络流量。但两者读的是同一个滤波后的温度值保证一致性。远程协议我常用两种Modbus TCP和MQTT。Modbus TCP在工业HVAC里兼容性好组态软件直接支持MQTT适合上云但需要网关。PIC32MX795F512L跑Modbus TCP没问题LwIP协议栈加上FreeModbusRAM占用大概30KBFlash占用60KB左右资源还富余。// Modbus保持寄存器映射 #define REG_TEMP_LOCAL 0 #define REG_TEMP_REMOTE 1 #define REG_STATUS 2 void update_modbus_regs(float temp) { uint16_t temp_raw (uint16_t)(temp * 100); // 放大100倍存整数 modbus_regs[REG_TEMP_LOCAL] temp_raw; modbus_regs[REG_TEMP_REMOTE] temp_raw; // 同源值相同 modbus_regs[REG_STATUS] sensor_ok ? 1 : 0; }这里有个设计决策本地和远程寄存器值相同还是本地存原始值、远程存滤波值我选择相同因为运维人员对比两边数据时如果发现不一致会怀疑系统有问题。同源同值最省心。状态寄存器用来标记传感器是否在线如果I2C读失败状态置0远程端就能知道数据不可信。4. 常见问题与排查技巧实录4.1 I2C通信失败的分层排查法I2C不通是最常见的问题我总结了一个从物理层到协议层的排查顺序。先看供电用万用表量传感器VDD是不是3.3V有时候LDO没使能或者保险丝断了电压是0。再看上拉SCL和SDA空闲时应该是高电平如果量出来是0V或者1.5V说明上拉有问题或者总线被拉死。然后看波形用示波器抓一次完整读写看起始条件、地址字节、ACK位是否正常。最后看软件确认地址宏、寄存器指针、读写方向位没写错。有个隐蔽的坑总线电容过大导致上升沿变缓。HVAC设备里I2C走线可能穿过多个板子分布电容到几百pF4.7kΩ上拉下上升时间可能超过1μs100kHz下勉强能用400kHz就挂了。解决办法是减小上拉电阻或者降低总线速率。我一般先用100kHz调通再尝试提速。还有一个偶发问题电机启停时I2C误码。HVAC里风机、压缩机启停会产生电磁干扰耦合到I2C线上导致某次传输错误。硬件上可以加磁珠或者屏蔽线软件上要加重试机制。我的做法是读温度失败后重试3次每次间隔10ms3次都失败才报错。实测下来加了重试之后误报率从每天几次降到几乎为零。4.2 温度读数偏差的校准思路PJ85718DM出厂校准过但焊接后PCB应力、附近热源辐射都会带来偏差。如果发现读数比参考温度计高1-2°C先检查传感器是不是靠近发热器件比如LDO、MCU或者功率电阻。布局时传感器要远离热源最好放在板边或者开槽隔离。如果布局没问题但仍有固定偏差可以做单点校准。用高精度温度计在稳定环境下对比算出偏移量在软件里减去。比如传感器读25.8°C参考温度计读25.0°C偏移就是-0.8°C。这个偏移量存在EEPROM里产线标定一次就行。注意校准要在热平衡状态下进行传感器上电后至少等5分钟再读数否则芯片自身发热会导致读数偏高。多点校准更准但更麻烦一般HVAC应用单点够了。如果温度范围跨越大比如-20°C到80°C可以在低温和高温各校一个点做线性补偿。但PJ85718DM的线性度本身很好非线性误差典型值只有0.1°C所以单点校准后全范围误差通常能控制在±0.5°C以内。4.3 远程数据断连的排查清单远程收不到数据先分清楚是网络问题还是设备问题。在设备端ping网关通的话说明网络层没问题不通就查IP配置、网线、交换机端口。如果ping通但Modbus读不到用Modbus调试工具直接读寄存器看是不是协议层的问题。我遇到过一次诡异的情况设备能ping通但Modbus TCP连接几秒后就断。查了半天发现是LwIP的TCP发送缓冲区太小温度数据上报频率1Hz每次报文100字节缓冲区只有2KB网络稍有延迟就满了然后连接被重置。把缓冲区调到8KB就好了。这个参数在lwipopts.h里改TCP_SND_BUF默认是(2 * TCP_MSS)我改成(8 * TCP_MSS)。还有一个常见问题是DHCP获取不到IP。HVAC现场的路由器可能没开DHCP或者地址池满了。我的做法是固件里支持静态IP和DHCP自动切换上电先尝试DHCP3秒超时后用静态IP。静态IP存在EEPROM里可以通过本地按键或者串口命令修改。这样现场调试不用重新烧固件。4.4 常见问题速查表现象可能原因排查方法解决措施I2C读回全0xFF总线未连接或地址错误示波器看波形确认地址检查接线和地址宏温度读数跳变严重电源纹波或气流波动示波器看VDD纹波加去耦电容软件滤波读数偏高1-2°C传感器靠近热源红外测温枪扫板子调整布局或软件校准远程连接频繁断开TCP缓冲区不足抓包看重传增大TCP_SND_BUF上电后IP获取失败DHCP不可用串口打印网络状态启用静态IP回退高温环境下丢包PHY过热测温枪测PHY温度加散热片或降额使用这张表是我这几年踩坑攒下来的基本上覆盖了80%的现场问题。剩下的20%往往是多个因素叠加比如电源纹波导致I2C误码误码导致温度跳变跳变触发限幅滤波最后显示值卡住不动。这种时候要一层一层剥先解决电源再看通信最后看软件逻辑。5. 从原型到产品的工程化考量5.1 PCB布局与热设计原型阶段用模块飞线能跑通就行但产品化必须考虑PCB布局。PJ85718DM的封装通常是SOT-23或者DFNDFN的底部散热焊盘要接到GND但注意这个焊盘也会把PCB的热量传导给传感器。如果PCB上有发热器件传感器要远离或者开槽隔离。PIC32MX795F512L是100引脚TQFP底部也有散热焊盘。布局时晶振要靠近芯片走线尽量短下面不要走高速信号。以太网差分对要走等长阻抗控制100Ω这些是常规要求但HVAC板子往往面积紧张容易忽略。我见过一个项目为了省空间把差分对走得弯弯曲曲结果网络误码率很高后来重新layout才解决。热设计方面HVAC机柜内温度可能到55°C甚至更高所有器件的结温要算清楚。PIC32在80MHz下功耗大概200mW结温升约20°C加上环境55°C结温75°C离125°C的极限还有余量。但PHY芯片功耗可能到300mW结温升更高要特别注意。我的经验是所有器件的结温降额至少留30°C余量否则夏天高温时故障率会明显上升。5.2 固件升级与参数存储产品出货后难免要改bug或者调参数固件升级功能要有。PIC32MX795F512L支持通过以太网或者串口升级我一般用串口简单可靠。升级协议自己定一个简单的上位机发命令进入bootloader然后分包传数据每包带CRC校验全部传完再跳转到应用区。参数存储用EEPROM或者Flash模拟。PIC32的Flash可以自编程但要注意擦写次数限制10万次左右。温度校准值、IP配置、Modbus地址这些参数不常改存Flash没问题。但如果是频繁写的参数比如累计运行时间就要用EEPROM或者铁电存储器。我一般外挂一颗24C02I2C接口和温度传感器共用总线地址不冲突就行。提示Flash自编程时CPU会暂停如果此时有中断触发可能导致时序问题。建议在擦写Flash前关中断擦写完再开。5.3 电磁兼容与现场防护HVAC现场电磁环境复杂变频器、接触器、电机都在附近。I2C总线容易受干扰除了前面说的上拉和重试还可以加TVS管做浪涌保护。电源入口加共模电感和压敏电阻防止电网浪涌打坏板子。以太网接口要加隔离变压器差分线加ESD保护。如果现场网线走室外还要考虑雷击防护加气体放电管。这些措施会增加成本但比现场故障后维修的成本低得多。我算过一笔账一块板子加防护器件多花5块钱一万台就是5万如果没加防护现场故障率1%一百台返修每台维修成本200块就是2万还不算停工损失和品牌影响。所以防护器件的钱不能省。软件上也要做防护。看门狗必须开PIC32的WDT可以配置超时时间我一般设2秒。主循环里定时喂狗如果程序跑飞2秒后自动复位。复位后要能恢复到正常状态温度数据重新采集网络重新连接。这些初始化流程要写得健壮不能复位后卡在某一步。6. 实际部署中的经验与扩展思路6.1 多传感器组网的实际案例在一个中型机房的HVAC改造里我用了6颗PJ85718DM分别监测3个机柜的回风、送风和盘管温度。6颗传感器挂在同一路I2C上地址从0x48到0x4D。PIC32每500ms轮询一遍每颗读一次总共耗时约200ms每颗30ms转换加通信开销剩下300ms处理显示和网络。轮询顺序有讲究。我把变化快的测点送风放在前面变化慢的盘管放在后面这样如果某一轮超时快测点的数据新鲜度优先保证。每颗传感器的数据单独滤波窗口大小根据测点特性调整送风波动大用12点窗口回风用8点盘管用4点。这些参数在代码里用结构体数组配置改起来方便。远程上报用Modbus TCP6个温度值映射到6个保持寄存器加上状态寄存器共7个。组态软件里直接读寄存器显示曲线运维人员看得很直观。本地液晶用12864分两屏显示按键切换。第一屏显示3个机柜的回风温度第二屏显示送风和盘管。这样现场巡检不用带电脑看液晶就行。6.2 低功耗场景的优化有些HVAC应用是电池供电的比如无线温度变送器。PJ85718DM支持单次转换模式转换完自动进入关断状态功耗降到微安级。PIC32也有低功耗模式空闲时进IDLEI2C中断唤醒。具体做法是PIC32定时唤醒比如每10秒发命令让PJ85718DM做一次转换等30ms读结果然后两者都进低功耗。平均功耗可以做到100μA以下一颗2000mAh的锂亚电池能用两年。但要注意低功耗模式下I2C上拉电阻会持续耗电如果上拉是4.7kΩ3.3V下每根线耗电0.7mA两根就是1.4mA比芯片本身还大。解决办法是用MOS管控制上拉电阻的供电通信时才打开。注意低功耗设计里所有外围器件的静态功耗都要算进去包括上拉电阻、LDO静态电流、液晶背光。有时候一颗LDO的静态电流就比MCU还大选型时要看数据手册的Iq参数。6.3 后续功能扩展的方向这个平台跑通之后扩展性其实很好。PIC32MX795F512L的资源还有富余可以加的东西不少。比如加一颗湿度传感器做成温湿度一体变送器加SD卡做本地数据记录断网时数据不丢加RTC做时间戳远程数据带时间信息。如果测点更多I2C地址不够用可以用I2C多路复用器一路变八路理论上能挂64颗传感器。但总线负载和轮询时间要重新算64颗每颗30ms就是近2秒一轮刷新率就下来了。这种场景更适合用RS485组网每颗传感器带一个RS485收发器主控轮询。但成本上去了要权衡。软件层面可以加个简单的Web服务器用PIC32的以太网跑HTTP浏览器直接看温度曲线。LwIP支持HTTPD加上SSI和CGI能做出不错的界面。RAM占用大概20KBFlash占用40KB资源够。这样现场调试不用装组态软件浏览器就行很方便。我个人在实际操作中的体会是嵌入式温度监测这个方向硬件选型决定了上限软件滤波决定了下限而工程化设计决定了能不能稳定跑三年。PJ85718DM加PIC32MX795F512L这个组合性能够用、开发资料全、成本可控适合中小批量的HVAC产品。真正花时间的不是写驱动而是处理现场的各种意外——电源波动、电磁干扰、高温降额、网络抖动。把这些坑都踩过一遍之后后面再做类似项目就快多了基本上两周能出原型一个月能小批量试产。最后分享一个小技巧所有温度数据在存储和传输时都放大100倍用整数表示避免浮点运算的精度损失和性能开销显示的时候再除回来这个习惯能省不少事。