
做嵌入式测温的同行应该都有同感——在工业控制和HVAC暖通空调项目里最让人头疼的不是传感器选型而是“怎么用一套系统同时把本地和远程两个测温点稳定地收上来”。最近我完成了一个项目核心方案就是标题里这两颗器件PJ85718DM16位工业级数字温度传感器搭配PIC32MX675F256LMIPS内核的32位MCU。这个组合解决了一个非常具体的问题在HVAC控制器这类设备里一块板子既要测PCB附近的本地温度又要通过长线缆测风管或室外的远程温度还要保证数据精度和传输稳定。这篇内容适合正在做嵌入式健康监测、HVAC控制器、工业数据采集的工程师也适合想了解“为何选这颗MCU而不选更常见方案”的硬件爱好者。整篇文章不是产品手册而是我踩完坑之后的项目笔记从硬件选型到软件滤波、从I2C调试到Modbus上传尽量把每个“为什么”都讲清楚。1. 项目背景与整体设计思路1.1 为什么选PIC32MX675F256L做控制核心先聊MCU。PIC32MX675F256L是某半导体大厂的高性能32位MCUMIPS M4K内核最高主频80MHz256KB Flash、64KB RAM带两个I2C、多个UART、多个定时器、12位ADC。它不算最新但在这个项目里非常合适。原因有三点第一温度监测需要“同时跑”的任务不少。本地测温、远程测温、数据滤波、通信协议栈、看门狗刷新、甚至简单的人机界面刷新这些任务如果全挤在8位MCU上调度起来会非常痛苦。PIC32有80MHz主频和64KB RAM可以跑FreeRTOS也可以直接用一个超循环加中断实现留给开发者的余量很大。第二外设资源刚好覆盖场景。HVAC控制器往往还带有继电器控制、RS-485通信、按键扫描等需求。PIC32MX675F256L的引脚足够多SPI、UART、I2C都能同时挂上不用为了引脚不够去加扩展芯片。第三调试工具成熟。它的调试方案很稳定代码烧写和在线调试在工程现场都验证过这点对于需要长时间跑工业现场的设备尤其重要。PIC32MX675F256L不是那种“颜值很高”的芯片但它是典型的“干实事”类型。功耗、速度、外设、成本四者平衡得不错。当然如果你问我“用STM32行不行”回答当然是行但项目既然定了PIC32后续所有设计都围绕它展开这也是产品延续性的考量。1.2 为什么选PJ85718DM做温度采样PJ85718DM是一颗I2C接口的16位数字温度传感器测温范围覆盖-40℃到125℃典型精度在±0.3℃具体看工作范围供电电压2.0V到3.6V待机电流只有微安级非常适合嵌入式系统。它的重点是“数字输出、免标定、直接读寄存器”。实际项目里很多工程师习惯用NTC热敏电阻做测温然后通过ADC采样计算温度。但NTC有四个绕不开的麻烦非线性的分压计算、每颗物料阻值离散性带来的个体偏差、ADC参考电压的温漂、PCB走线噪声对模拟信号的干扰。PJ85718DM把这些麻烦全部“数字化”掉了。它内部有ADC、有线性化处理、有温度寄存器MCU读出来直接就是温度值不用自己做复杂的查表和插值。另外还有一个实际考虑是双通道一致性。既然是“本地和远程”两个测温点那两路传感器的一致性就很重要。两颗独立的PJ85718DM天然就是一致的不会出现一路是NTC线性化误差、一路是数字传感器的系统性偏差这种问题。对HVAC这类对温控精度有要求的应用来说一致性差会让PID控制器产生不必要的振荡。1.3 双通道测温架构本地 vs 远程项目需求其实很直白系统要能采集两路温度。一路是“本地温度”也就是控制器PCB附近的空气温度通常用于设备机柜温度保护一路是“远程温度”通过线缆接到风管、送风口或者室外侧墙壁用于环境温度监测和HVAC联动控制。这里有一个容易忽略的设计点本地和远程两路虽然用的是同一型号传感器但物理连接方式不同。本地传感器直接焊在PCB上走线短、干扰小远程传感器则通过接插件和线缆延伸到几十厘米甚至几米之外线上会引入共模干扰和线阻问题。所以软件上要统一处理硬件设计上又要区分对待。这一部分我放到后面的硬件章节详细拆。2. 硬件电路设计与关键连接2.1 传感器接口电路详解PJ85718DM是标准的I2C接口。I2C总线在硬件上只需要两根线——SCL和SDA外加两个上拉电阻。很多新手画I2C电路时会忘记上拉电阻或者电阻选得不对导致通信偶尔失败。我的经验是在3.3V供电系统下上拉电阻选4.7kΩ比较稳妥如果I2C总线速度跑400kHz可以考虑减小到2.2kΩ但要考虑总线上挂的设备数量和线缆电容。具体连接方式是这样的SCL接MCU的SCL引脚比如PIC32上的某组I2C引脚SDA接MCU的SDA引脚传感器供电VDD接3.3V旁边放一颗0.1μF去耦电容再加一颗1μF~10μF的钽电容或陶瓷电容GND要就近接主地平面避免形成地环路AD0引脚如果有用于设置从机地址两路传感器可以设置成不同地址也可以共用一个地址但用独立I2C总线我在项目中把本地和远程两颗传感器挂在同一条I2C总线上通过AD0引脚把地址区分开。这样做的优点是省I/O口缺点是如果远程线缆太长总线电容会增大可能影响通信稳定性。后面调试时确实遇到过这类问题解决办法是降低I2C速率或者改用独立PIM的I2C外设分别管理两路。提示系统里如果还有其他I2C设备比如EEPROM或RTC记得在硬件设计阶段就规划好地址分配避免运行时才发现冲突。2.2 供电与去耦细节温度传感器本身的供电电流很小但“供得干净”直接决定读数稳定性。我在第一版硬件里就吃过亏传感器VDD和继电器驱动电源共用一个LDO输出结果继电器一吸合温度读数就跳几个LSB。后来把传感器的供电单独用一颗低噪声LDO或者至少用磁珠隔离问题就消失了。PIC32MX675F256L的供电也要重视。这颗MCU的VDD引脚多每个电源引脚附近都必须放0.1μF去耦电容并且要尽量靠近引脚放置。MCU内部MIPS内核在80MHz运行时瞬态电流不小如果去耦不到位可能导致运行不稳定或者ADC参考电压抖动。PCB布局上几个实用原则模拟区域和数字区域分开避免I2C数字信号线贴着传感器的模拟电源走传感器和MCU之间的I2C走线尽可能短如果有过孔两边都要放导通孔顶层铺地底层走信号线形成完整参考平面如果PCB面积允许传感器下面不要铺满铜减少寄生电容对I2C时序的影响2.3 远程测温的线缆设计方案远程传感器在HVAC设备里一般安装在风管处或机房的远端连接线少则几十厘米多则三四米。这就带来三个问题线缆压降、抗干扰、防反接。关于线缆我建议用三芯屏蔽线VDD、SDA、SCL各一根屏蔽层单端接地只在MCU端接地。如果只用两芯线GND得和供电回路共用地线电压浮动会影响通信电平千万不要为了省一根线去冒险。线长超过一两米时I2C总线电容会明显增加。I2C标准对总线电容有上限比如400kHz时约400pF但实际项目中一两米长的普通线缆很容易超过这个值。解决办法有几个降低I2C速率到100kHz牺牲一点速度换稳定性在传感器端的SDA、SCL上串联33Ω~100Ω的电阻抑制反射选用带“时钟拉伸”功能的传感器PJ85718DM本身这类工业级传感器一般会支持远程接插件选型上我用的是带锁扣的4针连接器防止现场震动导致松脱。另外加了TVS管做ESD保护因为风管处的线缆很可能在安装维护时被手触摸静电放电不防护的话传感器损坏率会很高。3. 软件实现驱动、转换与通信协议3.1 I2C驱动与寄存器操作PIC32的I2C外设使用起来逻辑清晰。PJ85718DM的寄存器结构不复杂核心的就三个配置寄存器设置分辨率/模式、温度高字节寄存器、温度低字节寄存器。读温度的基本流程就是发送从机地址写指针寄存器然后发起读操作连续读两个字节拼成一个16位数据。直接上代码这是我在项目里用的读温度核心函数以库函数风格示范#define PJ85718DM_ADDR 0x48 #define REG_TEMP_MSB 0x00 #define REG_TEMP_LSB 0x01 int16_t pj85718_read_temp(uint8_t addr) { uint8_t buf[2] {0}; // 写寄存器指针 i2c_start(); i2c_write((addr 1) | 0); // 写方向 i2c_write(REG_TEMP_MSB); // 重启起始条件切换读方向 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]; return raw; }注意这里的i2c_read_ack和i2c_read_nack区别读最后一个字节时回NACK告诉传感器“不需要继续发数据了”。很多新手在这里写错导致I2C总线状态机卡死。PJ85718DM默认的分辨率一般是12位或16位具体以数据手册为准。如果是16位模式通常LSB对应0.01℃。温度转换公式温度 raw × 0.01 ℃如果寄存器返回的是有符号数记得把int16_t符号位处理好负温度时raw是负数直接乘0.01就行不要先转成无符号整数再操作否则会出现温度突然变成几十万的bug。3.2 测温算法与数据平滑处理传感器读到了但能不能直接用答案是不能。HVAC环境里的温度变化本质上是大惯性过程空气温度不会在毫秒级突变。而实际的传感器数据里会有各种噪声电源纹波、I2C总线干扰、传感器自身量化噪声。所以必须在软件里做滤波。最简单的做法是“滑动平均”取最近N次采样值的平均值。N根据现场需求定我这边取的是16次采样周期1秒相当于16秒平滑窗口。这样做的好处是计算量小、实时性损失可接受、滤除高频噪声很有效。只做滑动平均还不够还要处理异常值。工业现场偶尔会出现单次采样的尖刺比如继电器打火、电机启停引起的电磁干扰可能导致某一次读数偏离真实值几十度。这时候平均算法会把异常值带入结果。更好的做法是“中值滤波滑动平均”组合先取最近5次采样的中值再对中值做滑动平均。#define FILTER_WINDOW 16 float temp_filtered 0.0f; float filter_temperature(float new_sample) { // 用一个环形缓冲区存储最近16个原始值 ring_buf[write_idx] new_sample; write_idx (write_idx 1) % FILTER_WINDOW; // 先做中值滤波取最近5个值排序取中间值 float recent[5]; for (int i 0; i 5; i) { recent[i] ring_buf[(write_idx - 1 - i FILTER_WINDOW) % FILTER_WINDOW]; } // 简单冒泡排序N5无所谓效率 sort_ascending(recent, 5); float median recent[2]; // 再做滑动平均 float sum 0.0f; for (int i 0; i FILTER_WINDOW; i) { sum ring_buf[i]; } temp_filtered sum / FILTER_WINDOW; return temp_filtered; }严格说这只是先用中值剔掉异常点再用均值平滑不是真正的“中值均值嵌套滤波”但在实际项目里效果已经足够好读数稳定到小数点后一位不会乱跳。3.3 上行数据协议设计Modbus RTU示例温度采回来之后要传给上位机或者楼宇自控系统。HVAC行业里最常见的协议是Modbus RTU跑在RS-485物理层上。PIC32MX675F256L的UART资源丰富扩展RS-485收发器即可。我的协议映射表简单清晰上位机通过功能码03H读保持寄存器就能拿到温度值寄存器地址数据类型说明0x0000uint16本地温度0.01℃为单位0x0001uint16远程温度0.01℃为单位0x0002uint16内部机柜温度备用扩展0x0010uint16状态字bit0传感器通信异常寄存器地址规划好之后上位机组态软件直接填表就能用不需要额外写驱动。 注意Modbus RTU的CRC16校验是必须的通讯异常能快速定位千万别省略。4. 温漂补偿与实测精度验证4.1 参考电压与PCB热源影响PJ85718DM内部是数字传感器本身没有外部参考电压这个说法但PCB上的“热”是会骗人的。传感器焊在板上旁边如果有大功率电阻、MOS管、电源芯片热会通过PCB铜皮传导到传感器导致读数偏高。我在实际调试中遇到过很典型的问题本地温度比实际室温高出3℃左右。排查下来原因是传感器位置离一颗发热的LDO太近铜皮没有做热隔离。解决办法有两个方向一是把传感器挪远一点走线拉出去二是传感器底下挖空铜皮减少热传导路径。HVAC设备对外壳内部温度有一定容忍但如果你想精确测量进风温度这种偏差是不能忽视的。另一个容易忽略的是传感器自发热。PJ85718DM的工作电流不大几十到几百μA本身自发热微乎其微但如果读取频率太高比如每10ms读一次传感器内部功耗累积可能导致零点几度的上升。我在项目里把采样周期设在1秒既满足控制需求又避开自发热问题。4.2 实测数据对比与校准方法样机做好之后我做了三组实测常温对比用精度0.05℃的标准水银温度计作参考放在同一个恒温箱里低温对比冰水混合物0℃左右高温对比恒温箱设定到45℃结果整理如下参考温度传感器1读数传感器2读数偏差0.0℃0.12℃0.08℃0.12℃ / 0.08℃25.0℃25.33℃25.26℃0.33℃ / 0.26℃45.0℃44.81℃44.76℃-0.19℃ / -0.24℃可以看到传感器本身精度在数据手册标称范围内但存在一个固定偏移。这个偏移可能是上料批次、PCB热传导、焊锡热应力的综合结果。实际项目中不需要追根究底只需要做一次单点校准在25℃附近记录偏移量然后在软件里加一个修正值。校准的核心逻辑校正后温度 原始读数 校准偏移校准偏移可以写死在Flash里也可以用上位机下发命令在线修改。我建议做成在线校准——产线不需要拆机通过串口或Modbus写偏移值能明显降低维护成本。注意校准偏移不能只做一次就万事大吉。如果产品在强震动环境或宽温范围工作离线测试中建议抽检偏移是否仍在可接受范围内。5. 常见问题与排查技巧实录5.1 I2C通信失败排查这个项目里I2C通信失败算是最常见的故障点症状五花八门有的设备上电后读不到温度有的读着读着突然返回0xFFFF有的远程通道时好时坏。我的排查顺序是这样的先查地址PJ85718DM有两颗确认AD0引脚电平设对了0x48和0x49不要搞混上拉电阻是否焊接I2C没有上拉电阻SCL/SDA电平浮空通信大概率失败逻辑分析仪挂总线看波形是否完整时序是否满足数据手册要求检查连线远程线缆是不是太长是不是用了细线导致信号压降逻辑分析仪是调试I2C的利器比示波器更直观能直接解码出从机回复的是ACK还是NACK。我遇到的一个典型问题就是远程传感器返回ACK后数据全是0xFF最后发现是线缆中SDA和SCL两根线在接插件端焊反了。5.2 温度跳变与读数漂移现象是温度值稳定几分钟后突然跳一下然后又稳定。这种问题在HVAC设备里绝大多数和电源噪声有关。排查方法是先把传感器读数的采样周期拉长或者把滤波窗口加大看“跳变”是否还有。如果还有用示波器量传感器VDD波形注意观察继电器或者压缩机的电流突变。我遇到过一次特别隐蔽的问题某台样机只要开启加热器温度就上升几度但实际上传感器位置远离加热器。后来发现是加热器的可控硅调压电路通过电源线传导噪声影响了LDO输出LDO的纹波抑制比在高频段不够噪声穿到了传感器供电端。解决方案是把传感器的供电从该LDO挪到独立电源轨并在传感器VDD处加一个100Ω1μF的RC滤波。5.3 远程传感器线缆干扰问题远程线缆短时没问题线拉到3米以上后偶发读数异常。这是典型的I2C总线电容超标或共模干扰问题。我的处理办法分成两步硬件上给远程SDA/SCL串联33Ω电阻降低振铃幅度降低I2C时钟到100kHz。如果还不行就要考虑屏蔽线是否正确接地了。屏蔽层在MCU端单端接地不要两端都接否则会形成地环路反而引入更大的噪声。 软件上配合异常值检测连续多次读到跳变超5℃的数值时标记通道故障给出报警而不是直接把错误温度送进PID。5.4 调试工具与方法心得最后聊聊调试工具。这项目里我最依赖的三样东西逻辑分析仪抓I2C时序、排查通信协议问题几十块的入门款就够用串口打印在MCU端加一个调试UART把采样原始值、滤波值、校准值周期性打印出来。调试时不打印出问题就只有瞎猜环境温度记录仪现场对比传感器和实际环境温度用来验证滤波算法是否过度延迟硬件调试时一定要“一次只改一个变量”。很多工程师一上来就同时改硬件电路、换传感器、改滤波参数结果出了问题根本定位不到原因。我在项目里坚持的做法是先固定硬件在软件里加打印确认原始读数稳定再逐步加滤波、加协议、加调度每一步都验证通过再往下走。这个项目做下来我的体会是PJ85718DM和PIC32MX675F256L这套组合不是那种“第一眼惊艳”的方案但胜在稳定、可控、好调试。HVAC和嵌入式温度监测拼的不是酷炫而是长期运行不漂移、现场故障定位快、成本可控。如果你正在做类似的温度采集项目希望这篇笔记能让你少走一两段弯路。最后再分享一个小经验——画PCB前一定先把传感器和发热元件的相对位置想清楚这个决定比你在软件里调三个月滤波算法都管用。