找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2939|回复: 3
收起左侧

《51单片机制作的火灾声光报警提示器》资料齐全(资料仅供交流学习、请勿用于商业)

[复制链接]
ID:449590 发表于 2018-12-25 22:37 | 显示全部楼层 |阅读模式
本帖最后由 清风兑酒 于 2018-12-25 22:38 编辑

《51单片机制作的火灾声光报警提示器》资料齐全(资料仅供交流学习、请勿用于商业
有原理图,PCB,源程序和论文

                                 摘要
随着现代家庭用火、用电量的增加,家庭火灾发生的频率越来越高。火灾报警器也随之被广泛应用于各种场合。
本课题所研究的无线多功能火灾报警器采用STC89C51为核心控制器,利用气体传感器MQ-2、ADC0832模数转换器、DS18B20温度传感器等实现基本功能。通过这些传感器和芯片,当环境中可燃气体浓度或温度等发生变化时系统会发出相应的灯光报警信号和声音报警信号,以此来实现火灾报警,智能化提示。
                                                       Abstract
Along with the modern home withfire, electricity consumption increases, the frequency of homefires is getting higher and higher. Smoke detectors have also beenwidelyused in various occasions.

Wireless multifunctionalfire alarm in the paper uses STC89C51 as thecore controller,the realization of the basic functionsof the gas sensor MQ-2, ADC0809 converter etc..Throughthese sensors and chips, when environmental smokeconcentration or combustible gas concentration changes thesystem sends out corresponding light alarm signal and thesound alarm signal, in order to achieve smoke alarm, whenthe smoke reaches a certain range, the system can alsodrive the relay, the relay can drive a load, such as aventilation fan, alarm signal lamp, fire hydrant water tapswitchetc.. Implementation of intelligent alarm control.


PCB
QQ截图20181225222612.png
QQ截图20181225222645.png

资料
QQ截图20181225222709.png
代码分享
#include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include "intrins.h"                                                                                          

#define     u8                          unsigned char
#define     u16                   unsigned int
#define     uchar                          unsigned char
#define     uint                   unsigned int

uchar yushe_wendu=50;                                //温度预设值
uchar yushe_yanwu=45;                                //烟雾预设值
uint wendu;                                                                 //温度值全局变量
uchar yanwu;                                                                 //用于读取ADC数据

//运行模式  
uchar Mode=0;                                                                 //=1是设置温度阀值  =2是设置烟雾阀值        =0是正常监控模式
//管脚声明
sbit Led_Reg                 =P2^2;                                 //红灯
sbit Led_Yellow  =P2^4;                                 //黄灯
sbit Buzzer             =P2^0;                                 //蜂鸣器
sbit Fan                      =P3^3;                                 //


/********************************************************************
* 名称 : delay_1ms()
* 功能 : 延时1ms函数
* 输入 : q
* 输出 : 无
***********************************************************************/
void delay_ms(uint q)
{
        uint i,j;
        for(i=0;i<q;i++)
                for(j=0;j<110;j++);
}
/***********************************************************************************************************
LCD1602相关函数
***********************************************************************************************************/

//LCD管脚声明 (RW引脚实物直接接地,因为本设计只用到液晶的写操作,RW引脚一直是低电平)
sbit LCDRS = P2^7;
sbit LCDEN = P2^6;
sbit D0                 = P0^0;
sbit D1                 = P0^1;
sbit D2                 = P0^2;
sbit D3                 = P0^3;
sbit D4                 = P0^4;
sbit D5                 = P0^5;
sbit D6                 = P0^6;
sbit D7                 = P0^7;



//LCD延时
void LCDdelay(uint z)                  //该延时大约100us(不精确,液晶操作的延时不要求很精确)
{
  uint x,y;
  for(x=z;x>0;x--)
    for(y=10;y>0;y--);
}
void LCD_WriteData(u8 dat)         
{
        if(dat&0x01)D0=1;else D0=0;
        if(dat&0x02)D1=1;else D1=0;
        if(dat&0x04)D2=1;else D2=0;
        if(dat&0x08)D3=1;else D3=0;
        if(dat&0x10)D4=1;else D4=0;
        if(dat&0x20)D5=1;else D5=0;
        if(dat&0x40)D6=1;else D6=0;
        if(dat&0x80)D7=1;else D7=0;
}
//写命令
void write_com(uchar com)
{
  LCDRS=0;                                 
        LCD_WriteData(com);
//  DAT=com;
  LCDdelay(5);
  LCDEN=1;
  LCDdelay(5);
  LCDEN=0;
}
//写数据
void write_data(uchar date)
{
  LCDRS=1;
        LCD_WriteData(date);
//  DAT=date;
  LCDdelay(5);
  LCDEN=1;
  LCDdelay(5);
  LCDEN=0;
}

/*------------------------------------------------
              选择写入位置
------------------------------------------------*/
void SelectPosition(unsigned char x,unsigned char y)
{     
        if (x == 0)
        {     
                write_com(0x80 + y);     //表示第一行
        }
        else
        {      
                write_com(0xC0 + y);      //表示第二行
        }        
}
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
{     
        SelectPosition(x,y) ;
        while (*s)
        {     
                write_data( *s);     
                s ++;     
        }
}
//========================================================================
// 函数: void LCD_Write_Char(u8 x,u8 y,u16 s,u8 l)
// 应用: LCD_Write_Char(0,1,366,4) ;
// 描述: 在第0行第一个字节位置显示366的后4位,显示结果为 0366
// 参数: x:行,y:列,s:要显示的字,l:显示的位数
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注: 最大显示65535
//========================================================================
void LCD_Write_Char(u8 x,u8 y,u16 s,u8 l)
{     
        SelectPosition(x,y) ;

        if(l>=5)
                write_data(0x30+s/10000%10);        //万位
        if(l>=4)
                write_data(0x30+s/1000%10);                //千位
        if(l>=3)
                write_data(0x30+s/100%10);                //百位
        if(l>=2)
                write_data(0x30+s/10%10);                        //十位
        if(l>=1)
                write_data(0x30+s%10);                //个位

}
/*1602指令简介
  write_com(0x38);//屏幕初始化
  write_com(0x0c);//打开显示 无光标 无光标闪烁
  write_com(0x0d);//打开显示 阴影闪烁
  write_com(0x0d);//打开显示 阴影闪烁
*/
//1602初始化
void Init1602()
{
  uchar i=0;
  write_com(0x38);//屏幕初始化
  write_com(0x0c);//打开显示 无光标 无光标闪烁
  write_com(0x06);//当读或写一个字符是指针后一一位
  write_com(0x01);//清屏

}

void Display_1602(yushe_wendu,yushe_yanwu,c,temp)
{
        //显示预设温度
        LCD_Write_Char(0,6,yushe_wendu,2) ;

        //显示预设烟雾
        LCD_Write_Char(0,13,yushe_yanwu,3) ;

        //时时温度
        LCD_Write_Char(1,6,c/10,2) ;
        write_data('.');
        LCD_Write_Char(1,9,c%10,1) ;

        //时时烟雾
        LCD_Write_Char(1,13,temp,3) ;
}



/***********************************************************************************************************
ADC0832相关函数
***********************************************************************************************************/
sbit ADCS         =P1^5; //ADC0832 片选
sbit ADCLK  =P1^2; //ADC0832 时钟
sbit ADDI         =P1^3; //ADC0832 数据输入                /*因为单片机的管脚是双向的,且ADC0832的数据输入输出不同时进行,
sbit ADDO         =P1^3; //ADC0832 数据输出                /*为节省单片机引脚,简化电路所以输入输出连接在同一个引脚上



//========================================================================
// 函数: unsigned int Adc0832(unsigned char channel)
// 应用:                 temp=Adc0832(0);
// 描述: 读取0通道的AD值
// 参数: channel:通道0和通道1选择
// 返回: 选取通道的AD值
// 版本: VER1.0
// 日期: 2015-05-29
// 备注:
//========================================================================
unsigned int Adc0832(unsigned char channel)
{
        uchar i=0;
        uchar j;
        uint dat=0;
        uchar ndat=0;
        uchar  Vot=0;

        if(channel==0)channel=2;
        if(channel==1)channel=3;
        ADDI=1;
        _nop_();
        _nop_();
        ADCS=0;//拉低CS端
        _nop_();
        _nop_();
        ADCLK=1;//拉高CLK端
        _nop_();
        _nop_();
        ADCLK=0;//拉低CLK端,形成下降沿1
        _nop_();
        _nop_();
        ADCLK=1;//拉高CLK端
        ADDI=channel&0x1;
        _nop_();
        _nop_();
        ADCLK=0;//拉低CLK端,形成下降沿2
        _nop_();
        _nop_();
        ADCLK=1;//拉高CLK端
        ADDI=(channel>>1)&0x1;
        _nop_();
        _nop_();
        ADCLK=0;//拉低CLK端,形成下降沿3
        ADDI=1;//控制命令结束
        _nop_();
        _nop_();
        dat=0;
        for(i=0;i<8;i++)
        {
                dat|=ADDO;//收数据
                ADCLK=1;
                _nop_();
                _nop_();
                ADCLK=0;//形成一次时钟脉冲
                _nop_();
                _nop_();
                dat<<=1;
                if(i==7)dat|=ADDO;
        }
        for(i=0;i<8;i++)
        {
                j=0;
                j=j|ADDO;//收数据
                ADCLK=1;
                _nop_();
                _nop_();
                ADCLK=0;//形成一次时钟脉冲
                _nop_();
                _nop_();
                j=j<<7;
                ndat=ndat|j;
                if(i<7)ndat>>=1;
        }
        ADCS=1;//拉低CS端
        ADCLK=0;//拉低CLK端
        ADDO=1;//拉高数据端,回到初始状态
        dat<<=8;
        dat|=ndat;

        return(dat);            //return ad data
}

/***********************************************************************************************************
DS18B20相关函数
***********************************************************************************************************/

sbit DQ = P1^0;                                 //ds18b20的数据引脚



/*****延时子程序:该延时主要用于ds18b20延时*****/
void Delay_DS18B20(int num)
{
  while(num--) ;
}
/*****初始化DS18B20*****/
void Init_DS18B20(void)
{
  unsigned char x=0;
  DQ = 1;         //DQ复位
  Delay_DS18B20(8);    //稍做延时
  DQ = 0;         //单片机将DQ拉低
  Delay_DS18B20(80);   //精确延时,大于480us
  DQ = 1;         //拉高总线
  Delay_DS18B20(14);
  x = DQ;           //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  Delay_DS18B20(20);
}
/*****读一个字节*****/
unsigned char ReadOneChar(void)
{
  unsigned char i=0;
  unsigned char dat = 0;
  for (i=8;i>0;i--)
  {
    DQ = 0;     // 给脉冲信号
    dat>>=1;
    DQ = 1;     // 给脉冲信号
    if(DQ)
    dat|=0x80;
    Delay_DS18B20(4);
  }
  return(dat);
}
/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
  unsigned char i=0;
  for (i=8; i>0; i--)
  {
    DQ = 0;
    DQ = dat&0x01;
    Delay_DS18B20(5);
    DQ = 1;
    dat>>=1;
  }
}
/*****读取温度*****/
unsigned int ReadTemperature(void)
{
  unsigned char a=0;
  unsigned char b=0;
  unsigned int t=0;
  float tt=0;
  Init_DS18B20();
  WriteOneChar(0xCC);  //跳过读序号列号的操作
  WriteOneChar(0x44);  //启动温度转换
  Init_DS18B20();
  WriteOneChar(0xCC);  //跳过读序号列号的操作
  WriteOneChar(0xBE);  //读取温度寄存器
  a=ReadOneChar();     //读低8位
  b=ReadOneChar();    //读高8位
  t=b;
  t<<=8;
  t=t|a;
  tt=t*0.0625;
  t= tt*10+0.5;     //放大10倍输出并四舍五入
  return(t);
}
//=====================================================================================
//=====================================================================================
//=====================================================================================


/*****校准温度*****/
u16 check_wendu(void)
{
        u16 c;
        c=ReadTemperature()-5;                          //获取温度值并减去DS18B20的温漂误差
        if(c<1) c=0;
        if(c>=999) c=999;
        return c;
}


/***********************************************************************************************************
按键检测相关函数
***********************************************************************************************************/
//按键
sbit Key1=P1^6;                                 //设置键
sbit Key2=P1^7;                                 //加按键
sbit Key3=P3^2;                                 //减按键



#define KEY_SET                 1                //设置
#define KEY_ADD                        2                //加
#define KEY_MINUS                3                //减


//========================================================================
// 函数: u8 Key_Scan()
// 应用: temp=u8 Key_Scan();
// 描述: 按键扫描并返回按下的键值
// 参数: NONE
// 返回: 按下的键值
// 版本: VER1.0
// 日期: 2015-05-29
// 备注: 该函数带松手检测,按下键返回一次键值后返回0,直至第二次按键按下
//========================================================================
u8 Key_Scan()
{         
        static u8 key_up=1;//按键按松开标志
        if(key_up&&(Key1==0||Key2==0||Key3==0))
        {
                delay_ms(10);//去抖动
                key_up=0;
                if(Key1==0)                        return 1;
                else if(Key2==0)return 2;
                else if(Key3==0)return 3;
        }
        else if(Key1==1&&Key2==1&&Key3==1)
                key_up=1;            
         return 0;// 无按键按下
}



void main (void)
{
        u8 key;
        wendu=check_wendu();                  //初始化时调用温度读取函数 防止开机85°C
        Init1602();                          //调用初始化显示函数
        LCD_Write_String(0,0,"SET T:00   E:000");  //开机界面
        LCD_Write_String(1,0,"NOW T:00.0 E:000");  
        delay_ms(1000);
        wendu=check_wendu();                  //初始化时调用温度读取函数 防止开机85°C
        while (1)                                                //主循环
        {
                key=Key_Scan();                                        //按键扫描
                yanwu=Adc0832(0);                                //读取烟雾值
                wendu=check_wendu();          //读取温度值

                if(key==KEY_SET)
                {
                        Mode++;
                }

                switch(Mode)                                                //判断模式的值
                {
                        case 0:                                                                //监控模式
                        {
                                Display_1602(yushe_wendu,yushe_yanwu,wendu,yanwu);  //显示预设温度,预设烟雾,温度值,烟雾值
                                if(yanwu>=yushe_yanwu)          //烟雾值大于等于预设值时
                                {
                                        Led_Reg=0;                                          //烟雾指示灯亮
                                        Fan=0;
                                        Buzzer=0;                                                  //蜂鸣器报警
                                }
                                else                                                                                  //烟雾值小于预设值时
                                {
                                        Led_Reg=1;                                          //关掉报警灯
                                        Fan=1;
                                }
                                if(wendu>=(yushe_wendu*10))          //温度大于等于预设温度值时(为什么是大于预设值*10:因为我们要显示的温度是有小数点后一位,是一个3位数,25.9°C时实际读的数是259,所以判断预设值时将预设值*10)
                                {
                                        Buzzer=0;                                                  //打开蜂鸣器报警
                                        Led_Yellow=0;                                          //打开温度报警灯
                                }
                                else                                                                                  //温度值小于预设值时
                                {
                                        Led_Yellow=1;                                          //关闭报警灯
                                }
                                if((yanwu<yushe_yanwu)&&(wendu<(yushe_wendu*10)))          //当烟雾小于预设值并且温度也小于预设值时 (&&:逻辑与,左右两边的表达式都成立(都为真,也就是1)时,该if语句才成立)
                                {
                                        Buzzer=1;                                                  //停止报警
                                }
                                break;
                        }
                        case 1://预设温度模式
                        {
                                SelectPosition(0,5) ;                                        //指定位置
                           write_com(0x0d);                                                        //阴影闪烁
                                if(key==KEY_ADD)                                                        //加键按下
                                {
                                        yushe_wendu++;                                            //预设温度值(阀值)加1
                                        if(yushe_wendu>=99)                                         //当阀值加到大于等于99时
                                        yushe_wendu=99;                                                         //阀值固定为99
                                        LCD_Write_Char(0,6,yushe_wendu,2) ;//显示预设温度
                                }
                                if(key==KEY_MINUS)                                                 //减键按下
                                {
                                        if(yushe_wendu<=1)                                        //当温度上限值减小到1时
                                        yushe_wendu=1;                          //固定为1
                                        yushe_wendu--;                                                        //预设温度值减一,最小为0
                                        LCD_Write_Char(0,6,yushe_wendu,2) ;//显示预设温度
                                }
                                break;                                                                                          //执行后跳出switch
                        }
                        case 2:                                //预设烟雾模式
                        {
                                SelectPosition(0,12) ;                                //指定位置        
                           write_com(0x0d);                                                        //打开显示 无光标 光标闪烁
                                if(key==KEY_ADD)                                                        //加键按下
                                {
                                        if(yushe_yanwu>=255)        //当阀值加到大于等于255时
                                        yushe_yanwu=254;            //阀值固定为254
                                        yushe_yanwu++;                                            //预设烟雾值(阀值)加1,最大为255
                                        LCD_Write_Char(0,13,yushe_yanwu,3) ;//显示预设烟雾
                                }
                                if(key==KEY_MINUS)                                                //减键按下
                                {
                                        if(yushe_yanwu<=1)                                        //当烟雾上限值减小到1时
                                                yushe_yanwu=1;                  //固定为1
                                        yushe_yanwu--;                                                        //预设温度值减一,最小为0         
                                        LCD_Write_Char(0,13,yushe_yanwu,3) ;//显示预设烟雾
                                }
                                break;
                        }
                        default        :        
                        {
                                write_com(0x38);//屏幕初始化
                                write_com(0x0c);//打开显示 无光标 无光标闪烁
                                Mode=0;                        //恢复正常模式
                                break;
                        }
                }

        }

}
资料仅供交流学习、请勿用于商业

火灾报警器代码.rar

4.16 KB, 下载次数: 49, 下载积分: 黑币 -5

PCB+论文.rar

1.17 MB, 下载次数: 65, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:762192 发表于 2020-5-27 09:34 | 显示全部楼层
没有原程序么?
回复

使用道具 举报

ID:759918 发表于 2020-5-27 18:02 | 显示全部楼层

用keil编译一下不就好了
回复

使用道具 举报

ID:315554 发表于 2020-5-28 11:09 | 显示全部楼层
很好,谢谢分享,有显示屏设计很不错
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表