基于51单片机做温度监控系统ds18b20
时间: 2023-08-21 07:04:17 浏览: 104
基于51单片机和DS18B20的温度检测
5星 · 资源好评率100%
好的,针对您的问题,我可以给出一个基本的方案:
1. 硬件设计
硬件部分需要有以下几个模块:
- 51单片机
- DS18B20温度传感器
- 1602液晶显示屏
- 4个按键(分别为上、下、确认和返回)
- 蜂鸣器(可选)
其中,DS18B20是常用的数字温度传感器,它可以直接通过单总线进行通讯。1602液晶显示屏可以用来显示温度值和一些提示信息,按键用于菜单的操作和参数的设置,蜂鸣器可以用于报警。
2. 软件设计
软件部分需要实现以下几个功能:
- DS18B20温度传感器数据采集和转换为温度值
- 液晶屏显示温度值和菜单信息
- 按键操作和参数设置
- 温度报警功能
由于您并未提供具体的要求,因此我这里只提供一个基本的程序框架,您可以根据自己的需求进行修改和完善。
```c
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ = P3^7; //定义DS18B20数据引脚
uchar tempH, tempL; //存储温度值高八位和低八位
uchar alarmTemp = 30; //报警温度
uchar menuIndex = 0; //菜单选择项
uchar setTemp = 0; //设定温度
bit isTempSet = 0; //是否已经设置温度
bit isAlarmOn = 0; //是否报警
//延时函数,约1ms
void delay(uint i)
{
while(i--);
}
//DS18B20复位
uchar ds18b20Reset()
{
uchar presence;
DQ = 0;
_nop_();
_nop_();
_nop_();
_nop_();
DQ = 1;
_nop_();
_nop_();
presence = DQ;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
return presence;
}
//DS18B20写一个字节
void ds18b20WriteByte(uchar dat)
{
uchar i;
for (i = 0; i < 8; i++)
{
DQ = 0;
_nop_();
_nop_();
DQ = dat & 0x01;
_nop_();
_nop_();
DQ = 1;
_nop_();
_nop_();
dat >>= 1;
}
}
//DS18B20读一个字节
uchar ds18b20ReadByte()
{
uchar i, dat = 0;
for (i = 0; i < 8; i++)
{
dat >>= 1;
DQ = 0;
_nop_();
_nop_();
DQ = 1;
_nop_();
_nop_();
if(DQ) dat |= 0x80;
_nop_();
_nop_();
DQ = 0;
}
return dat;
}
//DS18B20转换温度
void ds18b20Convert()
{
ds18b20Reset();
ds18b20WriteByte(0xcc);
ds18b20WriteByte(0x44);
}
//DS18B20读取温度
void ds18b20ReadTemp()
{
ds18b20Reset();
ds18b20WriteByte(0xcc);
ds18b20WriteByte(0xbe);
tempL = ds18b20ReadByte();
tempH = ds18b20ReadByte();
ds18b20Reset();
}
//显示温度值
void showTemp()
{
uchar str[6];
sprintf(str, "%d.%dC", tempH, tempL);
lcdWriteCom(0x80); //设置光标位置为第一行第一列
lcdWriteStr(str);
}
//显示菜单
void showMenu()
{
uchar str[16];
lcdWriteCom(0x80); //设置光标位置为第一行第一列
switch(menuIndex)
{
case 0:
lcdWriteStr("1) Set alarm temp ");
break;
case 1:
lcdWriteStr("2) Clear alarm ");
break;
case 2:
lcdWriteStr("3) Exit menu ");
break;
}
lcdWriteCom(0xc0); //设置光标位置为第二行第一列
sprintf(str, "Alarm: %d.%dC", alarmTemp, 0);
lcdWriteStr(str);
}
//设置报警温度
void setAlarmTemp()
{
uchar key = getKey();
if(key == 1) //上键
{
if(alarmTemp < 100) alarmTemp++;
}
else if(key == 2) //下键
{
if(alarmTemp > -50) alarmTemp--;
}
else if(key == 3) //确认键
{
isTempSet = 1;
menuIndex++;
}
else if(key == 4) //返回键
{
isTempSet = 0;
menuIndex++;
}
}
//清除报警
void clearAlarm()
{
uchar key = getKey();
if(key == 3) //确认键
{
isAlarmOn = 0;
menuIndex++;
}
else if(key == 4) //返回键
{
menuIndex++;
}
}
//获取按键值
uchar getKey()
{
uchar key = 0;
delay(20); //去抖动
if(P2 != 0xf0) //有按键按下
{
delay(1000); //延时等待按键稳定
if(P2 != 0xf0) //再次检测是否有按键按下
{
switch(P2)
{
case 0xe0: //上键
key = 1;
break;
case 0xd0: //下键
key = 2;
break;
case 0xb0: //确认键
key = 3;
break;
case 0x70: //返回键
key = 4;
break;
}
}
}
return key;
}
//温度报警
void tempAlarm()
{
if(isTempSet && tempH < alarmTemp) //温度低于设定值
{
if(!isAlarmOn) //报警未开启
{
isAlarmOn = 1;
beep();
}
}
else
{
isAlarmOn = 0;
}
}
//蜂鸣器响
void beep()
{
P1 |= 0x01; //蜂鸣器接在P1.0
delay(1000);
P1 &= ~0x01;
delay(1000);
}
//初始化LCD1602
void initLcd()
{
lcdWriteCom(0x38); //开显示
lcdWriteCom(0x0c); //光标不显示
lcdWriteCom(0x06); //光标移动
lcdWriteCom(0x01); //清屏
}
//写命令到LCD1602
void lcdWriteCom(uchar com)
{
lcdEnable();
P0 = com;
P2 &= ~0x01; //RS=0,写入命令
lcdDelay();
P2 &= ~0x04; //E=0,清除使能位
}
//写数据到LCD1602
void lcdWriteData(uchar dat)
{
lcdEnable();
P0 = dat;
P2 |= 0x01; //RS=1,写入数据
lcdDelay();
P2 &= ~0x04; //E=0,清除使能位
}
//使能LCD1602
void lcdEnable()
{
P2 |= 0x04; //E=1,产生脉冲
lcdDelay();
P2 &= ~0x04; //E=0,清除使能位
}
//LCD1602延时函数
void lcdDelay()
{
delay(500);
}
//主函数
void main()
{
initLcd(); //初始化LCD1602
while(1)
{
ds18b20Convert(); //DS18B20开始转换温度
delay(1000); //等待转换完成
ds18b20ReadTemp(); //读取温度值
showTemp(); //显示温度值
tempAlarm(); //温度报警
if(!isTempSet) //未设置温度
{
showMenu(); //显示菜单
switch(menuIndex)
{
case 0: //设置报警温度
setAlarmTemp();
break;
case 1: //清除报警
clearAlarm();
break;
case 2: //退出菜单
menuIndex = 0;
break;
}
}
}
}
```
以上是一个简单的基于51单片机的温度监控系统的方案,您可以根据自己的需求进行修改和完善。注意,该方案只提供了基本的硬件和软件设计思路,实际实现过程中需要根据具体情况进行调试和优化。
阅读全文