1. 项目概述:PIC单片机与DS18B20温度采集系统
在嵌入式开发领域,PIC单片机因其高性价比和稳定性能一直占据重要地位。这次我们要用PIC16F1824和PIC12F1822这两款经典8位单片机,配合DS18B20数字温度传感器,打造一个完整的温度采集系统。这个组合特别适合需要精确温度监测的小型设备,比如恒温控制器、环境监测仪等。
DS18B20是Dallas半导体(现被Maxim收购)推出的单总线数字温度传感器,最大特点就是只需要一根数据线就能完成供电和数据传输,精度达到±0.5°C(-10°C至+85°C范围内)。而PIC16F1824和PIC12F1822都内置了丰富的外设模块,包括定时器、ADC、EEPROM等,正好可以充分发挥DS18B20的性能。
提示:PIC12F1822是8引脚封装,适合空间受限的应用;PIC16F1824是14引脚封装,提供更多I/O资源。根据项目复杂度选择合适的型号。
2. 硬件设计与连接方案
2.1 元器件选型与特性分析
PIC16F1824主要参数:
- 14引脚PDIP/SOIC封装
- 7KB Flash程序存储器
- 256B EEPROM
- 12个I/O引脚
- 内置16MHz振荡器
- 工作电压2.3V-5.5V
PIC12F1822主要参数:
- 8引脚PDIP/SOIC封装
- 3.5KB Flash程序存储器
- 256B EEPROM
- 6个I/O引脚
- 内置32MHz振荡器
- 工作电压2.3V-5.5V
DS18B20关键特性:
- 测量范围:-55°C至+125°C
- 9至12位可调分辨率(默认12位)
- 单总线接口
- 寄生供电模式(无需外部电源)
- 每个器件有唯一64位序列号
2.2 电路连接方案
标准连接方式(外部供电模式):
code复制DS18B20 PIC单片机
VDD ----+ VDD (3.3V/5V)
|
4.7KΩ上拉电阻
|
DQ ----+-------- GPIO引脚(如RA2)
GND ------------ GND
寄生供电模式(仅需两根线):
code复制DS18B20 PIC单片机
DQ ----+-------- GPIO引脚(如RA2)
4.7KΩ上拉电阻
|
GND ------------ GND
注意:寄生供电模式下,总线必须定期提供强上拉(通过MOSFET或直接切换GPIO为强输出),否则转换可能失败。建议新手先用外部供电模式。
3. 软件开发环境配置
3.1 工具链准备
推荐使用MPLAB X IDE + XC8编译器组合:
- 下载安装MPLAB X IDE v5.50或更新版本
- 安装XC8编译器(免费版足够用于本项目)
- 为PIC16F1824/PIC12F1822安装器件支持包
3.2 新建项目步骤
- 在MPLAB X中选择File > New Project
- 选择"Microchip Embedded" > "Standalone Project"
- 选择器件型号(PIC16F1824或PIC12F1822)
- 选择工具链为XC8
- 配置项目名称和存储路径
- 在项目属性中设置:
- 主时钟:内部振荡器(4MHz或8MHz)
- 看门狗定时器:禁用(开发阶段)
- 低电压编程:禁用
- 代码保护:禁用
4. DS18B20驱动实现
4.1 单总线协议时序控制
DS18B20使用严格的时序协议,关键操作包括:
- 复位脉冲(480μs低电平)
- 存在脉冲(60-240μs低电平响应)
- 写时隙(写1:1-15μs低电平;写0:60-120μs低电平)
- 读时隙(主机拉低1μs后读取)
c复制// 复位DS18B20并检测存在脉冲
uint8_t DS18B20_Reset(void) {
DQ_DIR = 0; // 设置为输出
DQ = 0; // 拉低总线
__delay_us(480);
DQ_DIR = 1; // 释放总线(输入模式)
__delay_us(70);
if(DQ == 0) { // 检测存在脉冲
__delay_us(410);
return 1; // 器件存在
}
__delay_us(410);
return 0; // 无器件响应
}
4.2 温度采集完整流程
- 发送复位脉冲
- 跳过ROM命令(0xCC)
- 启动温度转换命令(0x44)
- 等待转换完成(750ms@12位分辨率)
- 再次复位
- 跳过ROM命令(0xCC)
- 发送读取暂存器命令(0xBE)
- 读取9字节数据(前2字节为温度值)
c复制float DS18B20_ReadTemp(void) {
int16_t temp;
uint8_t LSB, MSB;
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // 跳过ROM
DS18B20_WriteByte(0x44); // 启动转换
while(!DQ); // 等待转换完成(可改用超时检测)
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // 跳过ROM
DS18B20_WriteByte(0xBE); // 读暂存器
LSB = DS18B20_ReadByte();
MSB = DS18B20_ReadByte();
temp = (MSB << 8) | LSB;
return temp * 0.0625; // 12位分辨率,LSB=0.0625°C
}
5. 系统集成与优化
5.1 主程序框架设计
c复制#include <xc.h>
#include "ds18b20.h"
// 配置字设置
#pragma config FOSC = INTOSC // 内部振荡器
#pragma config WDTE = OFF // 看门狗关闭
#pragma config PWRTE = ON // 上电延时启用
#pragma config MCLRE = ON // MCLR引脚功能启用
#pragma config CP = OFF // 代码保护关闭
#pragma config CPD = OFF // 数据存储器保护关闭
void main(void) {
OSCCON = 0b01110010; // 内部8MHz振荡器
ANSELA = 0; // 所有引脚设为数字IO
TRISA2 = 1; // 设置RA2为输入(DS18B20数据线)
while(1) {
float temperature = DS18B20_ReadTemp();
// 此处添加显示或处理代码
__delay_ms(1000); // 每秒采集一次
}
}
5.2 抗干扰措施
-
总线稳定性:
- 确保上拉电阻靠近DS18B20安装
- 总线长度不超过20米(建议3米内)
- 在噪声环境中可降低至1.5kΩ上拉电阻
-
电源去耦:
- 在DS18B20的VDD和GND之间加0.1μF陶瓷电容
- PIC单片机电源引脚同样需要去耦电容
-
软件容错:
- 添加CRC校验(DS18B20数据包包含CRC字节)
- 实现超时机制,避免死等总线响应
- 重要数据多次读取取平均值
6. 常见问题与解决方案
6.1 温度读取异常排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 读取值为85°C | 电源上电后首次读取 | 这是正常现象,第二次读取即正常 |
| 读取值为-127°C | 总线短路或接触不良 | 检查硬件连接,确保上拉电阻正常 |
| 温度值跳变大 | 电源噪声干扰 | 加强电源滤波,缩短总线长度 |
| 无法检测到器件 | 接线错误或器件损坏 | 检查VDD/GND/DQ连接,更换器件测试 |
| 读取超时 | 总线负载过重 | 减少总线上的器件数量,检查上拉电阻值 |
6.2 精度优化技巧
-
分辨率选择:
- 9位:0.5°C,转换时间93.75ms
- 10位:0.25°C,转换时间187.5ms
- 11位:0.125°C,转换时间375ms
- 12位:0.0625°C,转换时间750ms
通过配置寄存器选择:
c复制void DS18B20_SetResolution(uint8_t resolution) { DS18B20_Reset(); DS18B20_WriteByte(0xCC); // 跳过ROM DS18B20_WriteByte(0x4E); // 写暂存器 DS18B20_WriteByte(0xFF); // TH报警寄存器 DS18B20_WriteByte(0x00); // TL报警寄存器 DS18B20_WriteByte((resolution-9)<<5 | 0x1F); // 配置寄存器 } -
软件滤波算法:
- 移动平均滤波:保留最近N次读数求平均
- 中值滤波:取多次读数的中间值
- 一阶滞后滤波:Y(n) = αX(n) + (1-α)Y(n-1)
7. 扩展应用与进阶方向
7.1 多传感器组网
DS18B20支持单总线上挂载多个器件,每个器件有唯一的64位ROM码。实现步骤:
- 发送搜索ROM命令(0xF0)
- 实现二叉树搜索算法识别所有器件ROM码
- 通过匹配ROM命令(0x55)选择特定器件操作
注意:单总线上器件数量理论上限是取决于总线驱动能力和时序要求,实际建议不超过8个。
7.2 温度报警功能
利用DS18B20内置的TH/TL报警寄存器:
- 设置TH(高温阈值)和TL(低温阈值)
- 配置报警搜索命令(0xEC)
- 当温度超出范围时,DS18B20会响应报警搜索
c复制void DS18B20_SetAlarm(int8_t TH, int8_t TL) {
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // 跳过ROM
DS18B20_WriteByte(0x4E); // 写暂存器
DS18B20_WriteByte(TH); // 高温阈值
DS18B20_WriteByte(TL); // 低温阈值
DS18B20_WriteByte(0x7F); // 12位分辨率
}
7.3 低功耗设计
对于电池供电应用:
- 使用PIC单片机的休眠模式
- 仅在需要时唤醒并读取温度
- 利用DS18B20的报警功能作为唤醒源
- 选择PIC12F1822实现最小系统
c复制// 进入休眠模式示例
void EnterSleep(void) {
DS18B20_SetAlarm(30, 10); // 设置报警范围10-30°C
SLEEP(); // 进入休眠
NOP(); // 唤醒后继续执行
}
8. 实际项目经验分享
在工业环境中部署这个系统时,我总结了几个关键经验:
-
长距离布线:当传感器需要远离控制器时:
- 使用屏蔽双绞线
- 每隔5米增加一个120Ω终端电阻
- 考虑改用RS-485接口的远程温度传感器
-
极端温度测量:
- 超过100°C时,避免使用寄生供电模式
- 考虑传感器自热效应(DS18B20约0.5°C/mW)
- 高温环境下延长采样间隔
-
EMC防护:
- 在I/O线上串联100Ω电阻
- 添加TVS二极管防止浪涌
- 在噪声强烈环境中使用光耦隔离
-
校准技巧:
- 在已知温度点(如冰水混合物0°C)进行单点校准
- 记录多个温度点的误差,建立补偿表
- 定期检查传感器精度(DS18B20长期漂移约0.1°C/年)
这个PIC+DS18B20的组合我已经在十多个项目中成功应用,从农业大棚监测到工业烤箱控制,稳定性令人满意。对于刚接触嵌入式开发的朋友,建议先从单个传感器开始,逐步扩展到多节点网络,这样能扎实掌握单总线协议的精髓。
