YAOTU INSIGHTS

基于PIC18F86J15与PJ85718DM的嵌入式温度监测系统设计与实现

基于PIC18F86J15与PJ85718DM的嵌入式温度监测系统设计与实现
1. 项目背景与核心需求拆解嵌入式温度监测这件事说起来简单做起来全是细节。我最早接触这类需求是在一个暖通空调控制板的项目里当时客户的要求很朴素本地要能看到温度远程也要能拿到数据成本还得压得住。听起来像是随便找个带ADC的单片机加个温度传感器就能搞定的事但真正落地的时候问题一个接一个冒出来——本地测温精度不够、远程传输数据跳变、多点采集时通道切换引入噪声、长期运行后传感器漂移……这些坑我基本都踩过一遍。这个项目的核心是用PJ85718DM这颗温度传感器配合PIC18F86J15这颗8位单片机搭建一套既能本地显示、又能远程上报的温度监测系统。PJ85718DM 是一颗模拟输出型温度传感器输出与温度成线性关系的电压信号PIC18F86J15 则负责采集这个电压、做换算、驱动本地显示同时通过串口把数据送到远程节点。整套方案的特点是成本低、电路简单、适合大批量部署特别适合嵌入式设备和暖通空调这类对价格敏感、但对可靠性有要求的场景。适合谁来参考这篇文章如果你是做嵌入式硬件或者固件开发的手头正好有温度采集的需求又不想上太复杂的数字传感器方案那这套组合值得一看。如果你是完全的新手也没关系我会把每一步的原理和操作都拆开讲包括为什么选这颗传感器、ADC怎么配置、温度怎么换算、远程通信怎么做校验尽量让你看完就能动手复现。先说清楚这套方案能解决什么问题。第一本地温度监测通过PIC18F86J15的ADC模块采集PJ85718DM的输出电压换算成温度值驱动LCD或者数码管显示。第二远程温度上报通过UART串口把温度数据打包发送到上位机或者另一个控制节点实现远程监控。第三多点扩展PIC18F86J15有多路ADC通道可以挂多个PJ85718DM实现多区域温度采集这在暖通空调里特别常见——一个控制器要同时监测回风、送风、室外等多个位置的温度。为什么不用DS18B20这类数字传感器这是很多人会问的问题。数字传感器确实方便一根线就能读温度但它的成本比模拟传感器高而且多点组网时时序要求严格长距离布线容易出问题。PJ85718DM这类模拟传感器输出的是电压信号抗干扰能力在短距离内反而更好配合单片机的ADC整体成本能压下来不少。当然模拟方案也有代价——需要校准、对电源噪声敏感、ADC精度直接影响测温精度。这些后面会详细讲。2. 核心器件选型与原理剖析2.1 PJ85718DM 温度传感器的工作特性PJ85718DM 是一颗模拟输出温度传感器它的核心是一个对温度敏感的半导体结输出电压与温度呈线性关系。典型参数是这样的供电电压范围在2.7V到5.5V之间输出电压斜率大约是10mV/摄氏度在25摄氏度时输出约500mV具体数值以实际数据手册为准不同批次可能有偏差。这意味着温度每升高1度输出电压增加10mV每降低1度输出电压减少10mV。这个线性关系是整套方案的基础。假设单片机ADC读到电压是600mV那温度就是600-500/10 25 35摄氏度。看起来很简单但实际用的时候有几个坑要注意。第一个坑是零点偏差。每颗传感器的零点电压不可能完全一致有的在25度时输出495mV有的输出505mV。如果不校准测温误差可能有正负1度甚至更多。解决办法是在已知温度下测一次实际输出电压把这个值作为零点写入固件。第二个坑是电源噪声。模拟传感器对电源特别敏感如果单片机和传感器共用一路电源单片机工作时产生的纹波会直接串到传感器输出上导致ADC读数跳动。我实测过不加滤波电容的时候读数能跳十几个LSB。解决办法是在传感器电源脚旁边并一个0.1uF的陶瓷电容再并一个10uF的钽电容基本能把噪声压下去。第三个坑是输出阻抗。PJ85718DM的输出阻抗不算低如果直接接到ADC输入端采样保持电容充电时间不够会导致读数偏低。PIC18F86J15的ADC输入要求源阻抗在一定范围内如果传感器输出阻抗偏高中间最好加一个电压跟随器或者把ADC采样时间调长一点。2.2 PIC18F86J15 的 ADC 模块配置要点PIC18F86J15 是Microchip PIC18系列的一款8位单片机自带10位ADC模块最多支持多路模拟输入通道。10位ADC意味着它能把参考电压分成1024份如果参考电压是5V那每一份大约是4.88mV。前面说了传感器斜率是10mV/度那理论上温度分辨率就是4.88mV除以10mV/度约等于0.488度。这个分辨率对于暖通空调来说够用了毕竟空调温度控制精度一般也就正负0.5度。ADC配置有几个关键参数需要设置。首先是参考电压可以用单片机的VDD作为参考也可以用外部基准。用VDD做参考最简单但VDD如果有波动测温就会跟着漂。如果对精度要求高建议用一颗外部基准芯片比如输出2.5V或4.096V的基准源这样ADC读数就稳定了。其次是采样时间。PIC18F86J15的ADC采样时间可以通过寄存器配置采样时间太短采样保持电容充不满读数偏低采样时间太长转换速度慢。一般建议采样时间至少几个微秒具体要看传感器输出阻抗和外部滤波电容的大小。我通常会把采样时间设到中间偏长的档位宁可慢一点也要保证读数稳定。第三是转换时钟。ADC转换时钟不能太快PIC18F86J15的ADC时钟周期要求不低于一定值具体看数据手册太快会导致转换精度下降。一般选择Fosc/8或者Fosc/16保证ADC时钟在合理范围内。第四是通道切换后的丢弃。如果多个传感器挂在不同的ADC通道上切换通道后第一次采集的数据要丢弃因为采样保持电容还残留着上一个通道的电压。我一般会连续采两次取第二次的值这样能避免通道串扰。2.3 本地显示与远程通信的方案取舍本地显示这块最简单的方案是驱动一个1602字符LCD显示当前温度值。1602 LCD便宜、驱动简单、可视角度够用在暖通空调控制器上很常见。如果产品定位高一点可以用OLED或者段码LCD但成本会上去。我选1602是因为它跟PIC18F86J15的IO口兼容性好4位或8位并行接口都能驱动固件也成熟。远程通信这块PIC18F86J15自带UART模块可以直接接RS485收发器或者无线模块。RS485适合有线长距离传输暖通空调的控制器之间经常用RS485组网。如果不想布线可以接无线模块但无线模块的成本和功耗都要考虑。我一般建议先用UART加RS485做有线方案稳定可靠调试也方便。通信协议方面不建议直接发ASCII字符串虽然调试方便但抗干扰能力差。我习惯用二进制帧格式帧头加地址加数据加校验。比如两字节帧头、一字节设备地址、两字节温度数据、一字节校验和。这样即使传输过程中有干扰接收端也能通过校验判断数据是否有效。3. 硬件电路设计与关键细节3.1 传感器接口电路PJ85718DM的接口电路不复杂但细节决定成败。供电脚接3.3V或5V地脚接地输出脚接单片机的ADC输入通道。关键是在输出脚和地之间并一颗0.1uF电容这颗电容的作用是滤除高频噪声同时给ADC采样保持电容提供一个低阻抗的电荷源。如果传感器离单片机比较远比如超过10厘米建议在输出脚串联一颗100欧姆电阻再并电容。这颗电阻和电容构成一个低通滤波器截止频率大概是1/(2πRC)100欧姆加0.1uF算下来约16kHz能滤掉大部分开关噪声又不会影响温度这种慢变信号。电源方面如果单片机和传感器共用5V建议在传感器电源脚旁边再并一颗10uF钽电容用来吸收电源纹波。我实测过不加这颗电容的时候ADC读数峰峰值能到20个LSB加上之后峰峰值降到3个LSB以内。注意传感器输出脚不要直接接大电容比如100uF以上因为上电时电容充电会导致输出脚电压上升缓慢单片机如果上电后立刻采样会读到错误值。0.1uF是合适的。3.2 单片机最小系统与ADC参考PIC18F86J15的最小系统包括晶振、复位电路、去耦电容。晶振频率根据需求选一般用8MHz或10MHz配合PLL可以跑到更高频率。如果对功耗有要求可以用内部振荡器但内部振荡器精度不如外部晶振对ADC转换时钟有影响。ADC参考电压的选择很关键。如果用VDD做参考VDD的波动会直接反映到测温结果上。比如VDD从5.0V掉到4.9VADC读数会变化2%温度读数就会漂0.5度左右。如果系统对精度要求高建议用外部基准芯片比如输出4.096V的基准源。4.096V的好处是它是2的幂次10位ADC每一份正好是4mV换算方便。如果实在不想加基准芯片至少要在VDD脚旁边并足够的去耦电容并且用低噪声的LDO供电。开关电源的纹波比较大直接给模拟部分供电会影响测温精度。3.3 本地显示与远程接口1602 LCD的接口有两种8位并行和4位并行。8位并行占用IO口多但驱动简单4位并行占用IO口少但驱动稍微复杂一点。PIC18F86J15的IO口够用我一般用4位并行省下来的IO口可以接按键或者指示灯。LCD的对比度调节脚接一个10k电位器调节到字符清晰为止。背光脚根据需求接限流电阻一般串一个100欧姆电阻接5V。远程接口用UART加RS485收发器。PIC18F86J15的UART引脚是固定的TX和RX分别接RS485收发器的DI和RO。收发器的DE和RE脚接单片机的一个IO口用来控制发送和接收方向。RS485总线两端要接120欧姆终端电阻中间节点不用接。如果总线长度超过100米建议加隔离防止地电位差损坏收发器。4. 固件实现与温度换算实操4.1 ADC采集与滤波固件的第一步是配置ADC。以PIC18F86J15为例需要设置ADCON0和ADCON1寄存器。ADCON1设置参考电压和引脚配置ADCON0设置通道和启动转换。下面是一段简化的ADC初始化代码void ADC_Init(void) { ADCON1 0x0E; // 参考电压为VDD和VSS所有引脚为模拟 ADCON0 0x01; // 选择通道0开启ADC模块 // 设置采样时间根据数据手册配置 }采集的时候先选择通道等待采样时间然后启动转换等待转换完成读取结果。如果多个通道轮流采集每次切换通道后要丢弃第一次结果。unsigned int ADC_Read(unsigned char channel) { ADCON0 (ADCON0 0xC3) | (channel 2); // 切换通道 __delay_us(20); // 等待采样 ADCON0 | 0x02; // 启动转换 while(ADCON0 0x02); // 等待转换完成 return (ADRESH 8) | ADRESL; // 读取10位结果 }滤波方面我一般用滑动平均滤波连续采8次或16次去掉最大值和最小值剩下的取平均。这样能有效抑制随机噪声又不会引入太大延迟。温度是慢变量延迟几百毫秒完全没问题。unsigned int ADC_Read_Filtered(unsigned char channel) { unsigned int samples[8]; unsigned int sum 0; unsigned char i; for (i 0; i 8; i) { samples[i] ADC_Read(channel); } // 去掉最大值和最小值 unsigned int max samples[0], min samples[0]; for (i 1; i 8; i) { if (samples[i] max) max samples[i]; if (samples[i] min) min samples[i]; } for (i 0; i 8; i) { if (samples[i] ! max samples[i] ! min) { sum samples[i]; } } return sum / 6; }4.2 电压到温度的换算ADC读到的值是0到1023之间的整数需要先换算成电压。如果参考电压是4.096V那电压就是ADC值乘以4mV。然后根据传感器的斜率换算温度。假设传感器在25度时输出500mV斜率10mV/度那温度计算公式是温度 (电压mV - 500) / 10 25用整数运算实现避免浮点int ADC_To_Temperature(unsigned int adc_value) { // 参考电压4.096V每LSB为4mV unsigned int voltage_mv adc_value * 4; // 温度 (电压 - 500) / 10 25 // 用整数运算(电压 - 500) * 10 / 100 250单位0.1度 int temp_x10 ((int)voltage_mv - 500) * 10 / 100 250; return temp_x10; // 返回0.1度为单位 }这里用0.1度为单位是为了保留一位小数显示的时候除以10就行。注意整数运算的溢出问题voltage_mv最大是4096减去500是3596乘以10是35960在16位整数范围内没问题。校准的时候把传感器放在已知温度环境里比如冰水混合物0度读ADC值反推零点电压写入固件。如果不想这么麻烦至少用一颗已知精度的温度计对比一下把偏差补偿进去。4.3 本地显示与远程上报本地显示用1602 LCD驱动代码网上很多核心是初始化、写命令、写数据。显示温度的时候把0.1度单位的整数拆成整数部分和小数部分分别显示。void Display_Temperature(int temp_x10) { char buf[8]; int integer temp_x10 / 10; int decimal temp_x10 % 10; sprintf(buf, %d.%d C, integer, decimal); LCD_WriteString(buf); }远程上报用UART波特率一般设9600或19200。数据帧格式我习惯用帧头0xAA 0x55设备地址温度高字节温度低字节校验和。校验和可以是前面所有字节的异或或者累加和。void UART_Send_Temperature(unsigned char addr, int temp_x10) { unsigned char frame[6]; frame[0] 0xAA; frame[1] 0x55; frame[2] addr; frame[3] (temp_x10 8) 0xFF; frame[4] temp_x10 0xFF; frame[5] frame[0] ^ frame[1] ^ frame[2] ^ frame[3] ^ frame[4]; for (int i 0; i 6; i) { while (!TXIF); // 等待发送缓冲空 TXREG frame[i]; } }接收端解析的时候先找帧头再读地址和数据最后校验。校验不通过就丢弃不要用错误数据。5. 常见问题与排查技巧实录5.1 温度读数跳动大怎么办这是最常见的问题。原因通常有三个电源噪声、滤波不足、通道串扰。先查电源。用示波器看传感器电源脚如果有明显纹波加电容。如果纹波来自开关电源考虑给模拟部分单独加LDO。再查滤波如果固件里没有滤波或者滤波窗口太小加大到16次或者32次。最后查通道串扰如果多个传感器轮流采集切换通道后丢弃第一次结果。我遇到过一种情况读数跳动不是因为噪声而是因为ADC采样时间太短。传感器输出阻抗偏高采样保持电容充不满读数偏低且不稳定。把采样时间调长后问题解决。5.2 远程数据偶尔出错怎么排查远程数据出错先看物理层。RS485总线两端有没有接终端电阻线缆是不是双绞线屏蔽层有没有接地这些都会影响通信质量。如果物理层没问题再看协议层。有没有校验校验算法对不对接收端有没有做超时处理我建议接收端加一个超时机制如果超过一定时间没收到完整帧就重置接收状态防止半帧数据卡死。还有一种情况是波特率不匹配。发送端和接收端的波特率误差不能超过2%否则累计误差会导致帧错误。如果用内部振荡器波特率误差可能比较大建议用外部晶振。5.3 长期运行后温度漂移传感器长期运行后零点可能会漂移。这跟传感器本身的稳定性有关也跟工作环境有关。如果环境湿度大传感器表面可能吸附水汽导致输出变化。解决办法有两个一是定期校准比如每年校准一次二是选稳定性更好的传感器。如果成本允许可以用数字传感器数字传感器内部有校准长期稳定性更好。另外单片机ADC的参考电压如果用的是VDDVDD长期漂移也会导致测温漂移。用外部基准芯片能解决这个问题。5.4 常见问题速查表问题现象可能原因排查方法解决措施读数跳动大电源噪声示波器看电源纹波加去耦电容用LDO读数偏低采样时间不足调长采样时间测试增加采样时间多点采集串扰通道切换残留切换后丢弃第一次连续采两次取第二次远程数据出错校验缺失检查协议加校验和超时机制长期漂移传感器老化对比标准温度计定期校准或换传感器通信距离短终端电阻缺失检查总线两端加120欧姆终端电阻实操心得调试的时候先用串口打印原始ADC值不要直接打印温度。原始值能告诉你很多信息——如果原始值跳动那是硬件或ADC配置问题如果原始值稳定但温度不对那是换算或校准问题。这个习惯能帮你快速定位问题。6. 多点扩展与系统优化6.1 多传感器组网方案PIC18F86J15有多路ADC通道可以挂多个PJ85718DM。每个传感器接一个通道固件里轮流采集。通道切换后丢弃第一次结果然后滤波。如果传感器数量超过ADC通道数可以用模拟开关扩展。比如用CD4051这类8选1模拟开关用3个IO口选择通道1个ADC通道采集。这样能扩展到8个甚至更多传感器。多点采集的时候要注意采样时间。通道越多轮询一圈的时间越长。如果每个通道采16次8个通道就是128次转换每次转换几十微秒一圈下来几毫秒。温度是慢变量几毫秒的延迟完全没问题。6.2 低功耗优化如果设备是电池供电低功耗很重要。PIC18F86J15有休眠模式可以在不采集的时候休眠定时器唤醒。传感器PJ85718DM的功耗不高但一直供电也会耗电。如果传感器可以间歇供电采集前上电采集完断电能进一步降低功耗。ADC采集的时候单片机不能休眠但采集完成后可以立刻休眠。UART发送的时候也不能休眠发送完再休眠。整体功耗取决于采集频率和发送频率。如果每分钟采集一次平均功耗可以做到很低。6.3 抗干扰与可靠性设计工业环境里干扰大硬件和固件都要做防护。硬件方面传感器输入加RC滤波电源加TVS管防浪涌RS485加隔离。固件方面ADC多次采样取中值通信加校验和重传关键数据存EEPROM防掉电丢失。看门狗一定要开。PIC18F86J15自带看门狗固件里定期喂狗如果程序跑飞看门狗能复位。复位后重新初始化系统能自动恢复。EEPROM用来存校准参数和设备地址。校准参数掉电不丢设备地址可以现场配置。写EEPROM的时候要注意寿命不要频繁写一般只在校准的时候写一次。7. 个人实操体会与建议这套方案我前后做过几个版本从最早的洞洞板到后来的PCB踩了不少坑。最大的体会是模拟电路部分布局和去耦比原理图更重要。同样的原理图布局不好读数就是不稳。传感器离单片机越近越好电源去耦电容越近越好模拟地和数字地要分开走最后单点接地。另一个体会是校准不能省。哪怕传感器手册上写了典型值实际批次之间也有差异。批量生产的时候每台设备都要校准或者至少抽检。校准工装可以很简单一个恒温槽加一个标准温度计把每台设备的零点测出来写入EEPROM。固件方面不要用浮点。8位单片机跑浮点又慢又占空间温度换算用整数完全够用。显示的时候再拆成整数和小数用户体验一样好。最后通信协议要留扩展位。我最早设计的帧格式只有温度后来要加湿度、加状态字帧格式不够用只能改协议。建议一开始就留几个字节的扩展位以后加功能不用改协议版本。这套方案的成本很低PJ85718DM加PIC18F86J15加外围电路批量成本能控制在很低的水平。对于暖通空调、嵌入式设备这类对成本敏感的应用是个很务实的选择。精度方面校准后能做到正负0.5度以内满足大部分暖通空调的控制需求。如果你对精度要求更高那就得上数字传感器或者更高位的ADC但成本也会上去。选型永远是权衡没有最好的方案只有最合适的方案。