基于51单片机的DS18B20温度监测系统
本文介绍了一个基于51单片机的DS18B20温度监测系统设计方案。系统通过DS18B20数字温度传感器采集环境温度,采用单总线协议通信,实现-55℃~125℃范围的温度测量。设计方案包含温度传感器驱动、数码管动态显示驱动和主控程序三个核心模块,详细解析了温度读取、数据处理和显示输出的实现方法。系统采用4位数码管显示带小数点的温度值,支持正负温度显示,并提供了硬件连接方案和常见问题解决方法。该设计体
基于51单片机的DS18B20温度监测系统详解
一、工程概述
本工程实现了一个完整的温度监测系统:
-
使用DS18B20数字温度传感器采集环境温度
-
通过51单片机处理温度数据
-
在4位数码管上实时显示温度值(带小数点)
-
支持正负温度显示(-55°C ~ +125°C)
工程包含7个关键文件:
-
ds18b20.h/c - 温度传感器驱动
-
smg.h/c - 数码管显示驱动
-
public.h/c - 公共函数和宏定义
-
main.c - 主控制程序
二、核心模块详解
1. DS18B20温度传感器驱动
工作原理:通过单总线协议(1-Wire)通信
// 复位函数(文档1)
void ds18b20_reset(void)
{
DS18B20_PORT = 0; // 拉低数据线
delay_10us(75); // 保持750μs(复位脉冲)
DS18B20_PORT = 1; // 释放总线
delay_10us(2); // 等待20μs(接收应答)
}
时序要点:复位脉冲需持续480-960μs,传感器会在15-60μs内回应低电平
温度读取流程:
float ds18b20_read_temperture(void)
{
ds18b20_start(); // 启动温度转换
ds18b20_reset(); // 复位总线
ds18b20_write_byte(0xCC); // 跳过ROM指令
ds18b20_write_byte(0xBE); // 读取暂存器
u8 datl = ds18b20_read_byte(); // 温度低字节
u8 dath = ds18b20_read_byte(); // 温度高字节
u16 value = (dath<<8) + datl; // 合并为16位数据
// 温度转换(12位精度)
if(value & 0xF800) { // 负温度处理
value = (~value) + 1;
temp = value * (-0.0625);
} else { // 正温度处理
temp = value * 0.0625; // LSB=0.0625°C
}
return temp;
}
关键点:温度值以16位补码形式存储,最低4位是小数部分
2. 数码管显示驱动
显示原理:动态扫描(人眼视觉暂留)
// 段码表(共阳极,文档3)
u8 gsmg_code[17] = {
0x3f, // 0
0x06, // 1
... // 2-9
0x71 // F
};
// 动态显示函数
void smg_display(u8 dat[], u8 pos)
{
for(u8 i=pos-1; i<8; i++) {
// 位选控制(文档4)
switch(i) {
case 0: LSC=1;LSB=1;LSA=1; break; // 第1位
case 1: LSC=1;LSB=1;LSA=0; break; // 第2位
... // 其他位
}
SMG_A_DP_PORT = dat[i-pos+1]; // 输出段码
delay_10us(100); // 显示延时1ms
SMG_A_DP_PORT = 0x00; // 消隐(防串影)
}
}
硬件连接:
-
位选:P2.2-P2.4(3-8译码器)
-
段选:P0口(需接上拉电阻)
3. 主控制逻辑
void main()
{
u8 i=0;
int temp_value;
u8 temp_buf[5]; // 显示缓冲区
ds18b20_init(); // 初始化温度传感器
while(1) {
i++;
// 每50次循环读取温度(约500ms)
if(i%50==0) {
temp_value = ds18b20_read_temperture()*10;
}
// 温度符号处理
if(temp_value<0) {
temp_value = -temp_value;
temp_buf[0] = 0x40; // 显示"-"号
} else {
temp_buf[0] = 0x00; // 正数不显示符号
}
// 温度值分解
temp_buf[1] = gsmg_code[temp_value/1000]; // 十位
temp_buf[2] = gsmg_code[temp_value%1000/100]; // 个位
temp_buf[3] = gsmg_code[temp_value%100/10]|0x80; // 小数点+十分位
temp_buf[4] = gsmg_code[temp_value%10]; // 百分位
// 从第4位数码管开始显示
smg_display(temp_buf, 4);
}
}
显示格式示例:
-
25.6°C➔ [空][2][5.][6] -
-12.3°C➔ [-][1][2.][3]
三、关键设计技巧
-
温度读取优化:
-
500ms读取一次(避免DS18B20转换未完成)
-
温度值×10转为整数处理(避免浮点运算开销)
-
-
显示抖动消除:
SMG_A_DP_PORT = dat[...]; // 显示 delay_10us(100); // 保持1ms SMG_A_DP_PORT = 0x00; // 消隐通过先显示后消隐的时序设计,有效防止数码管串影
-
负温度处理:
if(value & 0xF800) { // 检测符号位(高5位) value = (~value)+1; // 取补码 temp = value*(-0.0625); }利用位运算高效处理负温度
四、硬件连接参考
|
模块 |
单片机引脚 |
说明 |
|---|---|---|
|
DS18B20 DQ |
P3.7 |
单总线数据线 |
|
数码管段选 |
P0口 |
接74HC245驱动 |
|
数码管位选 |
P2.2-P2.4 |
接74HC138译码器 |
|
DS18B20 GND |
GND |
必须良好接地 |
|
DS18B20 VCC |
3.3V/5V |
寄生供电时接VCC |
布线建议:DS18B20数据线需加4.7K上拉电阻,总线长度不宜超过20米
五、常见问题解决
-
温度读取-85°C:
-
检查接线是否正确(DQ线虚接)
-
增加复位后的延时时间
-
添加总线ESD保护二极管
-
-
数码管显示闪烁:
// 修改public.c中的延时参数 void delay_ms(u16 ms) { for(u16 i=ms; i>0; i--) for(u16 j=110; j>0; j--); // 调整j值 }根据晶振频率校准延时(11.0592MHz时j=110)
-
负温度显示异常:
// 修改温度转换算法(文档1) if((value & 0xF800) == 0xF800) // 严格判断符号位
六、扩展建议
-
添加报警功能:
if(temp_value > 300) { // 30°C报警 BUZZER = 0; // 蜂鸣器响 } else { BUZZER = 1; // 关闭蜂鸣器 } -
多传感器支持:
// 在ds18b20_write_byte(0xCC)后改为 ds18b20_write_byte(0x55); // 匹配ROM指令 ds18b20_write_byte(rom_code[0]); // 发送64位ROM编码 ... -
温度数据记录:
添加AT24C02 EEPROM存储模块,实现温度历史记录
请大家点点关注和点赞,后面我一定会分享更多实用的项目的
通过本工程,可以深入理解单总线通信协议、数码管动态显示、浮点数处理等嵌入式开发核心技术。
更多推荐



所有评论(0)