Intelligent fire alarm system based on microcontroller 51

1. System Features

(1) can be set smoke density values ​​and high temperature alarm, emergency and emergency alarm unexpected situations can manually cancel the emergency alarm.

(2) When there is an emergency alarm button may be special cases the alarm, and a power-down save function, parameter settings stored in the internal microcontroller EEPOM.

(3) when a fire is releasing smoke sensor detects smoke, ADC0832 number conversion by the signal processing module for processing and then to the microcontroller, when detecting a concentration in excess of, the alarm will sound the buzzer by bit while the red light.

(4) At the same time, the system can also detect the temperature, usually ambient temperature fire will rise. When the detected temperature exceeds the set alarm temperature, the alarm buzzer will generate yellow light simultaneously.

Button (5) The system has even further add, subtract function, very easy to operate, the system can also enter the setting interface, after 30 seconds if no key is pressed to exit the setting screen automatically.

(6) Distance range: the smoke concentration: 0--9 level; temperature range: 0--99 °

2, circuit diagram

3, part of the code

#include <reg51.h>	         //调用单片机头文件
#define uchar unsigned char  //无符号字符型 宏定义	变量范围0~255
#define uint  unsigned int	 //无符号整型 宏定义	变量范围0~65535
#include <intrins.h>
#include "eeprom52.h"


//数码管段选定义      0     1    2    3    4    5	 6	 7	  8	   9	
uchar code smg_du[]={0x5f,0x44,0x9d,0xd5,0xc6,0xd3,0xdb,0x45,0xdf,0xd7,0x40,0xfd/*-*/};
//数码管位选定义
uchar code smg_we[]={0x7f,0xbf,0xdf,0xef};

uchar dis_smg[8]  = {0xa0,0x84,0x62,0x2a,0x39,0x2c,0x24,0xba};	

sbit CS=P2^3;		//CS定义为P3口的第2位脚,连接ADC0832CS脚  PCB
sbit SCL=P2^0;		//SCL定义为P3口的第3位脚,连接ADC0832SCL脚
sbit DO=P2^1;		//DO定义为P3口的第4位脚,连接ADC0832DO脚

sbit ledy = P1^6;   //温度报警指示灯
sbit ledr = P1^7;   //烟雾报警指示灯 x
sbit dq   = P1^5;	//18b20 IO口的定义
sbit beep = P3^6;   //蜂鸣器IO口定义
uint temperature,s_temp ;  //温度的变量
uchar dengji,s_dengji;     //烟物等级
uchar shoudong;            //手动报警键


bit flag_300ms = 1;
uchar key_can;		 //按键值的变量
uchar menu_1;        //菜单设计的变量

/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
	uint i,j;
	for(i=0;i<q;i++)
		for(j=0;j<120;j++);
}

/***********************小延时函数*****************************/
void delay_uint(uint q)
{
	while(q--);
}


/******************把数据保存到单片机内部eeprom中******************/
void write_eeprom()
{
	SectorErase(0x2000);
	byte_write(0x2000, s_temp);
	byte_write(0x2001, s_dengji);
	byte_write(0x2060, a_a);	
}

/******************把数据从单片机内部eeprom中读出来*****************/
void read_eeprom()
{
	s_temp   = byte_read(0x2000);
	s_dengji = byte_read(0x2001);
	a_a      = byte_read(0x2060);
}

/**************开机自检eeprom初始化*****************/
void init_eeprom() 
{
	read_eeprom();		//先读
	if(a_a != 1)		//新的单片机初始单片机内问eeprom
	{
		s_temp   = 50;
		s_dengji = 5;
		a_a = 1;
		write_eeprom();	   //保存数据
	}	
}

/***********************18b20初始化函数*****************************/
void init_18b20()
{
	bit q;
	dq = 1;				//把总线拿高
	delay_uint(1);	    //15us
	dq = 0;				//给复位脉冲
	delay_uint(80);		//750us
	dq = 1;				//把总线拿高 等待
	delay_uint(10);		//110us
	q = dq;				//读取18b20初始化信号
	delay_uint(20);		//200us
	dq = 1;				//把总线拿高 释放总线
}

/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{
	uchar i;
	for(i=0;i<8;i++)
	{					 //写数据是低位开始
		dq = 0;			 //把总线拿低写时间隙开始 
		dq = dat & 0x01; //向18b20总线写数据了
		delay_uint(5);	 // 60us
		dq = 1;			 //释放总线
		dat >>= 1;
	}	
}

/*************读取18b20内的数据***************/
uchar read_18b20()
{
	uchar i,value;
	for(i=0;i<8;i++)
	{
		dq = 0;			 //把总线拿低读时间隙开始 
		value >>= 1;	 //读数据是低位开始
		dq = 1;			 //释放总线
		if(dq == 1)		 //开始读写数据 
			value |= 0x80;
		delay_uint(5);	 //60us	读一个时间隙最少要保持60us的时间
	}
	return value;		 //返回数据
}

/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{
	uint value;
	uchar low;			   //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序
	init_18b20();		   //初始化18b20
	write_18b20(0xcc);	   //跳过64位ROM
	write_18b20(0x44);	   //启动一次温度转换命令
	delay_uint(50);		   //500us

	init_18b20();		   //初始化18b20
	
	write_18b20(0xcc);	   //跳过64位ROM
	write_18b20(0xbe);	   //发出读取暂存器命令
	
	EA = 0;
	low = read_18b20();	   //读温度低字节
	value = read_18b20();  //读温度高字节
	EA = 1;
	value <<= 8;		   //把温度的高位左移8位
	value |= low;		   //把读出的温度低位放到value的低八位中
	value *= 0.0625;	       //转换到温度值 
	return value;		   //返回读出的温度 
}


/***********读数模转换数据********************************************************/	
//请先了解ADC0832模数转换的串行协议,再来读本函数,主要是对应时序图来理解,本函数是模拟0832的串行协议进行的

unsigned char ad0832read(bit SGL,bit ODD)
{
	unsigned char i=0,value=0,value1=0;		
		SCL=0;
		DO=1;
		CS=0;		//开始
		SCL=1;		//第一个上升沿	
		SCL=0;
		DO=SGL;
		SCL=1;  	//第二个上升沿
		SCL=0;
		DO=ODD;
		SCL=1;	    //第三个上升沿
		SCL=0;	    //第三个下降沿
		DO=1;
		for(i=0;i<8;i++)
		{
			SCL=1;
			SCL=0; //开始从第四个下降沿接收数据
			value<<=1;
			if(DO)
				value++;						
		}
		for(i=0;i<8;i++)
		{			//接收校验数据
			value1>>=1;
			if(DO)
				value1+=0x80;
			SCL=1;
			SCL=0;
		}
		CS=1;
		SCL=1;	
		if(value==value1)				//与校验数据比较,正确就返回数据,否则返回0	
			return value;
	return 0;
}


/***********************数码显示函数*****************************/
void display()
{
	uchar i;
	P0 =0x00;			 //消隐 				          
	P2 = smg_we[i];	 		 //位选
	P0 = dis_smg[i];		 //段选	   
	i ++;
	if(i >= 4)			//4位数码管显示
		i = 0;  	
}


/*************定时器0初始化程序***************/
void time_init()	  
{
	EA   = 1;	 	  //开总中断
	TMOD = 0X01;	  //定时器0、定时器1工作方式1
	ET0  = 1;		  //开定时器0中断 
	TR0  = 1;		  //允许定时器0定时
}

/********************独立按键程序*****************/
uchar key_can;	 //按键值

void key()	 //独立按键程序
{
	static uchar key_new;
	key_can = 20;                   //按键值还原
	P1 |= 0x0f;
	if((P1 & 0x0f) != 0x0f)		//按键按下
	{
		delay_1ms(1);	     	//按键消抖动
		if(((P1 & 0x0f) != 0x0f) && (key_new == 1))
		{						//确认是按键按下
			key_new = 0;
			switch(P1 & 0x0f)
			{
				case 0x0e: key_can = 4; break;	   //得到k1键值
				case 0x0d: key_can = 3; break;	   //得到k2键值
				case 0x0b: key_can = 2; break;	   //得到k3键值
				case 0x07: key_can = 1; break;	   //得到k4键值
			}		
		}			
	}
	else 	   //按键松开
		key_new = 1;	
}

/****************按键处理数码管显示函数***************/
void key_with()
{
	if(key_can == 4) 	 //紧急报警键  手动报警
	{
		if(menu_1 == 0)
			shoudong = 1;
	}
	if(key_can == 1)	 //设置键
	{
		menu_1 ++;
		if(menu_1 >= 3)
		{
			menu_1 = 0;
		}
	}
	if(menu_1 == 0)
	{
		if((key_can == 2) || (key_can == 3))
			shoudong = 0;          //取消手动报警
	}
	if(menu_1 == 1)			//设置高温报警
	{
		if(key_can == 2)
		{
			s_temp ++ ;		//高温报警值加1 
			if(s_temp > 99)
				s_temp = 99;
		}
		if(key_can == 3)
		{
			s_temp -- ;		//高温报警值减1 
			if(s_temp <= 10)
				s_temp = 10 ;
		}
		dis_smg[0] = smg_du[s_temp % 10];	           //取个位显示
		dis_smg[1] = smg_du[s_temp / 10 % 10];  //取十位显示
		dis_smg[2] = 0x80;
		dis_smg[3] = 0x1b;	//显示c
		write_eeprom();			   //保存数据
	}	
	if(menu_1 == 2)			//设置烟物报警
	{
		if(key_can == 2)
		{
			s_dengji ++ ;	  //烟物报警值加1 
			if(s_dengji >= 9)
				s_dengji = 9;
		}
		if(key_can == 3)
		{
			s_dengji --;	  //烟物报警值减1 
			if(s_dengji <= 1)
				s_dengji = 1;
		}
		dis_smg[0] = smg_du[s_dengji % 10];	           //取个位显示
		dis_smg[1] = 0x80 ;  
		dis_smg[2] = 0x80;
		dis_smg[3] = 0xc7;	//显示q
		write_eeprom();			   //保存数据
	}	
}  

/****************报警函数***************/
void clock_h_l()
{
	static uchar value;
	if((dengji >= s_dengji) || (temperature >= s_temp) || (shoudong == 1))		//报警
	{
		value ++;
		if(value >= 2)
		{
			value = 10;
			beep = ~beep;	  //蜂鸣器报警
			if(dengji >= s_dengji)
			{
				ledr=~ledr;
			}
			if(temperature >= s_temp)
			{
				ledy=~ledy;
			}
			if(shoudong == 1)
			{
				ledy=~ledy;
				ledr=~ledr;
			}
		}
	}else 
	{
		if((dengji < s_dengji) && (temperature < s_temp) && (shoudong == 0))	  //取消报警
		{
			value = 0;
			beep = 1;		 //取消报警
			ledr=1;//取消红灯报警
			ledy=1;//取消黄灯报警
		}	
	}
}

/***************主函数*****************/
void main()
{
	beep = 0;				    //开机蜂鸣器叫一声
	delay_1ms(200);
	P0 = P1 = P2 = P3 = 0xff;   //初始化IO口为高电平
	temperature = read_temp();  //读取温度值
	init_eeprom();  //开始初始化保存的数据
	delay_1ms(650);				
	temperature = read_temp();  //读取温度值
	time_init(); //初始化定时器 		
	while(1)  
	{
		key();					//独立按键程序
		if(key_can < 10)
		{
			key_with();			//按键按下要执行的程序
		}
		if(flag_300ms == 1)
		{		
			flag_300ms = 0;
			clock_h_l();
			temperature = read_temp();  //读取温度值
			dengji = ad0832read(1,0);	
			dengji = dengji * 10 / 250;
			if(menu_1 == 0)
			{
				if(temperature >= 99)
					temperature = 99;
				dis_smg[3]=smg_du[dengji];	    //显示烟物报警等级
				dis_smg[2]= 0x80;	            // -		
				dis_smg[1]=smg_du[temperature/10%10];	//十位
				dis_smg[0]=smg_du[temperature%10];	    //个位	ADC0832为8位ADC,数值为0~255,我们将其分开放入l_tmpdate数组中显示
			}
		} 
		delay_1ms(1);
	}
}

/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{	
	static uchar value;
	TH0 = 0xf8;
	TL0 = 0x30;     // 2ms
	value ++;	 
	display();	  //数码管显示函数
	if(value % 150 == 0)
	{
		flag_300ms = 1;	   //300ms
		value = 0;
	}
}

 

Published 30 original articles · won praise 12 · views 1994

Guess you like

Origin blog.csdn.net/weixin_41017942/article/details/105294800