PIC18F85K90与PJ85718DM嵌入式温度监测方案设计与抗干扰实践

发布时间:2026/10/10 13:55:59
PIC18F85K90与PJ85718DM嵌入式温度监测方案设计与抗干扰实践
1. 项目缘起与整体设计思路嵌入式温度监测这个方向看起来简单实际上坑特别多。我最早接触这类需求是在一个 HVAC 控制板的项目里当时的需求很朴素本地要能看到当前温度远程上位机也要能读到同一路温度数据而且两边的数据不能打架。最开始想用一颗带模拟输出的温度传感器直接进 MCU 的 ADC结果发现精度和抗干扰都撑不住尤其是压缩机启停那一下读数能飘好几度。后来换成了数字温度传感器方案主控用 PIC18F85K90温度采集用 PJ85718DM这套组合跑下来稳定性明显好很多也就成了我后面几个项目里反复复用的一个基础架构。先把这套方案说清楚PJ85718DM 是一颗本地温度传感器输出的是数字信号直接给 MCU 读取不需要额外的 ADC 采样和校准PIC18F85K90 是一颗 8 位单片机片上集成了比较丰富的外设包括多路串口、I2C、SPI、定时器等用来做温度数据的采集、处理、本地显示和远程上报非常合适。整个系统的核心任务就三件事第一把本地温度准确读出来第二把温度数据在本地做显示或者做阈值判断第三把同一份数据通过通信接口送到远程端。听起来简单但真正做起来采样时序、通信协议、数据一致性、抗干扰这几块都得认真处理。为什么选这套组合而不是别的我当时的考量主要有几点。一是成本HVAC 这类产品对 BOM 成本非常敏感8 位 MCU 加一颗数字温度传感器整体成本可控二是开发周期PIC18 系列的开发工具链成熟寄存器操作直接调试起来心里有底三是可靠性数字传感器省掉了模拟链路的校准环节批量生产时一致性更好。这三点加起来基本就决定了方案选型。这个项目适合谁来参考如果你正在做嵌入式温度采集、HVAC 控制器、环境监测设备或者你手上有 PIC18 平台的项目需要接入温度传感器这套思路都可以直接借鉴。哪怕你用的是别的 MCU采集和远程上报的分层设计逻辑也是通用的。下面我会把整体设计、核心细节、实操过程、常见问题这几块拆开讲尽量把踩过的坑和验证过的做法都写出来。2. 核心器件解析与选型考量2.1 PJ85718DM 温度传感器的工作特性PJ85718DM 这颗传感器我在多个项目里用过它的核心价值在于把温度感知和数字输出集成在一起。它内部有感温元件、信号调理电路和数字接口逻辑对外呈现的就是一个可以直接读取的温度寄存器。和传统的热敏电阻加运放加 ADC 的方案相比它省掉了模拟链路里最容易出问题的几个环节运放失调、参考电压漂移、ADC 量化误差。这些在实验室里可能不明显但到了现场尤其是 HVAC 设备那种电机、继电器频繁动作的环境里模拟方案的读数抖动会非常明显。从使用角度看PJ85718DM 的读取流程一般是MCU 通过通信接口发送读取命令传感器返回温度数据MCU 再把原始数据转换成实际温度值。这里有个细节要注意温度数据的格式和分辨率在不同配置下可能不一样有的配置是整数精度有的是小数精度读取之前一定要确认当前配置否则转换出来的温度会差一个量级。我第一次用的时候就因为没注意分辨率设置读出来的温度比实际高了十几度排查了半天才发现是转换系数用错了。另外这颗传感器的供电范围、通信速率、上电稳定时间这些参数在数据手册里都有明确说明实际使用时建议留出足够的余量。比如供电如果系统里有大功率负载电源纹波可能会影响传感器内部参考最好在传感器供电脚附近加去耦电容位置越靠近引脚越好。通信线如果走线较长也要考虑加适当的滤波或者降低通信速率保证数据可靠。2.2 PIC18F85K90 作为主控的适配性分析PIC18F85K90 这颗 MCU在 8 位机里算是外设比较全的。它有多路通信接口可以同时接本地显示模块和远程通信模块不会因为接口不够而被迫做取舍。它的定时器资源也比较丰富可以用来做采样周期控制、通信超时判断、看门狗喂狗等。对于温度监测这种需要周期性采集、周期性上报的应用来说定时器的作用非常关键它决定了整个系统的节奏。我选它还有一个原因是它的中断系统比较灵活可以给温度采集和通信分别分配不同的优先级。比如温度采集可以放在定时器中断里保证采样周期稳定通信上报可以放在主循环里避免中断里做太多耗时操作。这种分层处理的方式能让系统在通信繁忙的时候也不会丢掉温度采样数据完整性更好。还有一个实际考量是它的 I/O 驱动能力。HVAC 控制板上经常要直接驱动一些指示灯、蜂鸣器或者小继电器PIC18F85K90 的 I/O 在合理配置下可以直接承担这些任务省掉额外的驱动芯片。当然如果负载电流较大还是要加三极管或者驱动芯片这个后面讲实操的时候再细说。2.3 本地与远程双通道的设计逻辑本地和远程这两个通道看起来只是把同一份数据发到两个地方但实际设计的时候要考虑的问题不少。首先是数据一致性本地显示和远程上报必须是同一时刻的同一份数据不能本地显示的是上一次采样的值远程收到的是这一次的值这样在调试或者故障分析的时候会非常混乱。我的做法是在采样完成后先把数据存到一个全局的温度变量里本地显示和远程上报都从这个变量取值保证源头一致。其次是更新频率的差异。本地显示通常要求响应快人眼看到温度变化要即时远程上报则要考虑通信带宽和上位机处理能力频率可以低一些。这两者如果处理不好要么本地显示卡顿要么远程通信拥塞。我的做法是本地显示每次采样后都更新远程上报则按一个较低的固定周期发送两者互不干扰。最后是异常处理。如果远程通信断了本地显示不能受影响系统要继续正常工作同时要记录通信异常状态等通信恢复后能继续上报。这个逻辑在代码里要明确处理不能因为通信失败就把整个系统卡死。3. 硬件连接与关键细节处理3.1 传感器与 MCU 的接口连接要点PJ85718DM 和 PIC18F85K90 之间的连接核心就是通信线和电源线。通信线一般走 I2C 或者类似的数字接口具体用哪种要看传感器型号和 MCU 外设配置。连接的时候有几个细节必须注意。第一上拉电阻。数字通信线在没有驱动的时候需要上拉电阻保持高电平阻值一般选 4.7k 到 10k 之间具体要看通信速率和总线电容。速率高、线长的时候阻值要小一些保证上升沿够快速率低、线短的时候阻值可以大一些降低功耗。第二走线布局。传感器如果离 MCU 较远通信线要尽量短并且远离电机、继电器、电源开关这些干扰源。如果实在避不开可以考虑用屏蔽线或者双绞线并且做好接地。我在一个项目里因为通信线和大电流负载线捆在一起走结果温度读数每隔几秒就跳一次后来把线分开走问题立刻消失。这个坑很典型硬件布局上的问题软件再怎么滤波都很难完全解决。第三电源去耦。传感器的供电脚旁边一定要加一个 0.1uF 的陶瓷电容位置越靠近引脚越好。这个电容的作用是滤掉高频噪声保证传感器内部电路稳定工作。如果系统里还有其他数字器件建议在电源入口再加一个 10uF 的钽电容或者电解电容做低频滤波。3.2 本地显示与远程通信的硬件资源分配本地显示我一般用段码 LCD 或者小尺寸的字符屏接口简单功耗低适合 HVAC 这种常年运行的应用。连接的时候要注意 LCD 的偏压电阻和对比度调节这些参数如果不对显示会偏淡或者偏浓影响可读性。远程通信我一般用串口转其他物理层的方式比如串口转 RS485 或者串口转无线模块具体看现场布线条件。RS485 适合有线长距离传输抗干扰好无线模块适合不方便布线的场合但要注意通信协议和配对管理。资源分配上PIC18F85K90 的串口资源要合理规划。如果本地显示也用串口那就要注意两个串口的波特率和中断优先级不能冲突。我的做法是本地显示用并行接口或者 I2C把串口留给远程通信这样资源不打架调试也方便。3.3 抗干扰与电源设计的实操经验HVAC 环境的干扰源主要是电机、压缩机、继电器这些感性负载。它们启停的时候会在电源线和空间里产生很大的瞬变干扰。对付这种干扰硬件上要做几件事一是电源入口加 TVS 管或者压敏电阻吸收浪涌二是通信线加共模电感或者磁珠抑制高频噪声三是传感器和 MCU 的接地要处理好模拟地和数字地分开走最后单点汇合。软件上也要配合比如通信数据加校验发现校验错就丢弃重读温度数据做滑动平均滤波滤掉突发的跳变关键寄存器定期回读防止干扰导致配置丢失。这些措施加起来系统在恶劣环境下的稳定性会好很多。我在一个压缩机控制柜里跑过这套方案连续运行几个月温度数据没有出现过异常跳变说明这套抗干扰设计是有效的。4. 软件架构与核心代码实现4.1 温度采集任务的调度与实现温度采集的调度我一般用定时器中断来做。比如设定定时器每 500ms 中断一次在中断里启动一次温度读取。这样采样周期稳定不受主循环里其他任务的影响。读取过程一般是发送读取命令等待转换完成读取温度寄存器转换成实际温度值存入全局变量。这里要注意等待时间传感器从收到命令到数据准备好需要一定时间这个时间在数据手册里有说明不能省略否则读到的可能是上一次的数据或者无效数据。代码实现上我习惯把温度读取封装成一个函数输入是传感器地址或者通道号输出是浮点温度值。函数内部处理通信时序、数据校验、单位转换。这样主循环里调用起来很简洁也方便以后换传感器型号时只改这一个函数。float read_temperature(uint8_t sensor_addr) { uint8_t raw_data[2]; float temperature; // 发送读取命令 i2c_start(); i2c_write(sensor_addr 1); i2c_write(TEMP_READ_CMD); i2c_stop(); // 等待转换完成 delay_ms(TEMP_CONVERSION_TIME); // 读取温度数据 i2c_start(); i2c_write((sensor_addr 1) | 1); raw_data[0] i2c_read_ack(); raw_data[1] i2c_read_nack(); i2c_stop(); // 数据校验与转换 if (check_crc(raw_data)) { temperature convert_to_celsius(raw_data); } else { temperature last_valid_temperature; // 校验失败沿用上次有效值 } return temperature; }这段代码里校验失败沿用上次有效值是一个实用技巧。温度变化通常比较慢短时间内沿用上次值不会造成明显误差但能避免因为一次通信干扰就显示异常值。4.2 本地显示刷新与远程上报的协同本地显示和远程上报的协同核心是数据源统一和更新节奏分离。我在主循环里这样安排温度采集在定时器中断里完成更新全局变量主循环里先检查本地显示是否需要刷新如果需要就调用显示刷新函数然后检查远程上报周期是否到了到了就调用上报函数。两个任务的周期可以独立设置互不影响。本地显示刷新我一般做一个小优化只有温度值变化超过一定阈值才刷新显示避免显示数字频繁跳动。比如温度变化小于 0.1 度就不刷新这样显示看起来更稳定。远程上报则每次都发当前值保证上位机拿到的是最新数据。void main_loop(void) { static float last_display_temp -100.0; static uint32_t last_report_time 0; while (1) { // 本地显示刷新 if (fabs(current_temperature - last_display_temp) 0.1) { update_local_display(current_temperature); last_display_temp current_temperature; } // 远程上报 if (get_system_tick() - last_report_time REPORT_INTERVAL_MS) { send_remote_report(current_temperature); last_report_time get_system_tick(); } // 其他任务 handle_communication_timeout(); feed_watchdog(); } }4.3 通信协议设计与数据校验远程通信协议我一般设计得比较简单但必须有校验。一个典型的数据帧包括帧头、设备地址、温度数据、状态字节、校验和、帧尾。帧头用来同步设备地址用来区分不同节点状态字节可以带传感器故障、通信异常等信息校验和用来验证数据完整性。校验和的计算方式有很多种简单一点的用累加和复杂一点的用 CRC。累加和实现简单对单字节错误检测效果不错CRC 检测能力更强但计算量稍大。在 8 位 MCU 上如果通信速率不高CRC 也完全跑得动。我一般用 CRC-8兼顾检测能力和计算开销。uint8_t calculate_crc8(uint8_t *data, uint8_t length) { uint8_t crc 0x00; for (uint8_t i 0; i length; i) { crc ^ data[i]; for (uint8_t j 0; j 8; j) { if (crc 0x80) { crc (crc 1) ^ 0x07; } else { crc 1; } } } return crc; }接收端收到数据后先找帧头再按固定长度取数据计算校验和并比对校验通过才处理数据否则丢弃。这个流程看起来简单但实际调试的时候帧头误判和缓冲区溢出是两个常见问题后面讲排查的时候会细说。5. 实操过程与调试记录5.1 从零搭建测试环境的步骤我搭建测试环境一般分几步走。第一步先把 MCU 最小系统跑起来确认供电、晶振、复位电路正常能下载程序并点亮一个 LED。这一步看起来基础但很多问题都是在这里埋下的比如晶振不起振、复位脚被拉低、电源纹波太大都会导致后面调试困难。第二步接上温度传感器写一个最简单的读取程序把原始数据通过串口打印出来。这一步不急着转换温度先确认通信能通能读到数据。如果读不到先用示波器看通信线上的波形确认时序对不对上拉电阻有没有起作用。第三步加上温度转换和显示确认读到的温度值合理。可以用手捏住传感器或者用吹风机加热看温度值是否跟着变化。这一步能验证传感器和转换逻辑是否正常。第四步加上远程通信用上位机或者串口助手接收数据确认数据帧格式正确、校验通过。这一步能验证通信协议和硬件连接是否可靠。第五步做长时间运行测试至少跑 24 小时观察温度数据是否稳定通信是否丢包系统是否死机。这一步能暴露很多偶发问题比如看门狗复位、通信超时、内存泄漏等。5.2 温度数据校准与精度验证温度数据的校准我一般用冰水混合物和沸水做两个参考点。冰水混合物是 0 度沸水在标准大气压下是 100 度用这两个点可以大致验证传感器的线性度和偏移。如果偏差较大可以在软件里加一个偏移量或者做两点校准。校准的时候要注意传感器要充分浸入参考环境等待读数稳定后再记录不能刚放进去就读。精度验证则要用更高精度的参考温度计做对比在多个温度点分别记录传感器读数和参考读数计算偏差。如果偏差在允许范围内就认为精度合格如果偏差较大要分析是传感器本身的问题还是电路的问题。我遇到过一次偏差大的情况最后发现是传感器供电电压偏低导致内部参考漂移调整供电后偏差就正常了。5.3 长时间运行稳定性测试长时间运行测试是验证系统可靠性的关键。我一般会记录几个指标温度数据的最大值、最小值、平均值通信丢包率系统复位次数。如果温度数据出现异常跳变或者通信丢包率偏高或者系统频繁复位都说明有问题需要排查。测试环境也很重要最好能模拟实际工作环境比如加上电机负载、继电器动作、电源波动等。如果条件不允许至少要在温度变化较大的环境下测试比如从空调房拿到室外观察系统是否能正常工作。我在一个项目里就是因为没有做温度循环测试结果产品到了北方冬天户外低温下传感器通信失败后来加了低温补偿才解决。6. 常见问题与排查技巧实录6.1 温度读数异常的问题排查温度读数异常是最常见的问题表现有几种读数固定不变、读数跳变剧烈、读数偏差大、读数偶尔无效。固定不变一般是通信没通或者读的是同一个寄存器跳变剧烈一般是干扰或者电源不稳偏差大一般是转换系数或者校准问题偶尔无效一般是通信时序或者校验问题。排查的时候我一般先用示波器看通信波形确认时序和电平正常然后看电源纹波确认供电稳定再检查转换系数和校准参数确认计算正确最后看校验逻辑确认无效数据被正确处理。这个顺序从硬件到软件从简单到复杂能比较快地定位问题。6.2 通信丢包与数据冲突的处理通信丢包的原因很多常见的有波特率不匹配、通信线太长、上拉电阻不合适、干扰太大、缓冲区溢出。排查的时候先确认两边的波特率、数据位、停止位、校验位完全一致然后检查通信线长度和上拉电阻必要时降低波特率或者加中继再看是否有干扰源必要时加屏蔽或者滤波最后检查接收缓冲区确保不会因为处理不及时而溢出。数据冲突一般发生在多节点通信的时候比如两个节点同时发送。解决办法是加仲裁机制比如主从模式只有主机能发起通信从机只能应答或者用令牌环拿到令牌的节点才能发送。在温度监测这种应用里一般用主从模式就够了主机轮询各个从机从机收到命令才回复。6.3 常见问题速查表问题现象可能原因排查方法解决措施温度读数固定不变通信未通、读错寄存器示波器看波形、检查命令修正通信配置、确认寄存器地址温度读数跳变剧烈干扰、电源不稳看电源纹波、检查走线加滤波、分开走线、加去耦电容温度偏差大转换系数错、未校准核对数据手册、做校准修正系数、加偏移量通信丢包波特率不匹配、线太长核对配置、测线长统一配置、降低速率、加中继系统频繁复位看门狗、电源跌落查看门狗配置、测电源调整喂狗周期、加稳压显示闪烁刷新太频繁、电源不稳看刷新逻辑、测电源加刷新阈值、加滤波电容6.4 独家避坑经验分享第一个坑是上拉电阻的位置。很多人把上拉电阻放在 MCU 端觉得这样方便但实际上如果传感器端离得远通信线上的电容会让上升沿变缓导致通信失败。正确的做法是把上拉电阻尽量靠近传感器端或者两端都放保证整条线的电平稳定。第二个坑是温度转换的整数除法。在 8 位 MCU 上做浮点运算比较耗时有些人为了省时间用整数运算结果转换的时候用了整数除法把小数部分直接截断了导致温度精度损失。如果要用整数运算一定要先做乘法再做除法保留足够的中间精度。第三个坑是看门狗喂狗周期。看门狗是为了防止程序跑飞但如果喂狗周期设得太短正常的长耗时操作也会触发复位设得太长又起不到保护作用。我的经验是喂狗周期设为最长正常操作时间的 1.5 到 2 倍并且在多个任务点都喂狗确保任何一个任务卡死都能被检测到。第四个坑是通信缓冲区的管理。接收中断里如果直接把数据存入缓冲区主循环里如果处理不及时缓冲区就会溢出。解决办法是加环形缓冲区并且加溢出标志溢出时丢弃最旧的数据或者复位缓冲区。这个逻辑一定要在代码里明确处理不能假设主循环一定能及时处理。7. 方案扩展与个人体会这套 PJ85718DM 加 PIC18F85K90 的温度监测方案基础功能跑通之后扩展空间其实挺大的。比如可以加多路温度传感器做多点温度监测适合大型 HVAC 系统可以加历史数据存储用 EEPROM 或者外部 Flash 记录温度曲线方便事后分析可以加报警功能温度超限时本地声光报警并远程推送还可以加自适应采样温度变化快的时候提高采样率变化慢的时候降低采样率节省功耗。我在实际使用中发现这套方案最值得投入精力的地方其实是抗干扰和异常处理。功能实现本身不难难的是在各种恶劣环境下都能稳定运行。每次遇到问题我都会把现象、排查过程、解决方法记录下来时间长了就形成了一套自己的排查流程再遇到类似问题就能很快定位。最后分享一个小技巧在通信协议里加一个设备状态字节把传感器的健康状态、通信质量、供电状态都编码进去。这样上位机不仅能拿到温度值还能知道这个值可不可信。这个字节平时看起来多余但真出问题的时候它能帮你快速判断是传感器的问题还是通信的问题省掉很多排查时间。