找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1889|回复: 0
打印 上一主题 下一主题
收起左侧

烟雾报警器码源 mq2和dht 11

[复制链接]
跳转到指定楼层
楼主
ID:389551 发表于 2018-8-26 22:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <reg52.h>
#include <eepom52.h>
#define uchar unsigned char
#define uint  unsigned int
#include <intrins.h>
unsigned  int  q;
//数码管段选定义0     1    2    3    4    5  6  7   8    9  
uchar code smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};  //断码

//数码管位选定义
uchar code smg_we[]={0x7f,0xbf,0xdf,0xef};
//uchar code smg_we[]={0xfe,0xfd,0xfb,0xf7};

uchar dis_smg[8]  = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};
uchar smg_i = 3;    //显示数码管的个位数

sbit SCL=P3^4;  //SCL定义为P1口的第3位脚,连接ADC0832SCL脚
sbit DO=P3^3;  //DO定义为P1口的第4位脚,连接脚
sbit CS=P3^2;  //CS定义为P14位脚,连接ADC0832CS脚



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


bit flag_300ms ;
uchar key_can;   //按键值的变量
uchar menu_1;        //菜单设计的变量
bit flag_lj_en;   //按键连加使能
bit flag_lj_3_en;  //按键连3次连加后使能加的数就越大了
  uchar key_time,flag_value;      //用做连加的中间变量
bit key_500ms  ;

uchar flag_clock;
uchar zd_break_en,zd_break_value;   //自动退出设置界面
uchar a_a;


/***********************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--);
}

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


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



/**************开机自检eepom初始化*****************/
void init_eepom()
{
        read_eepom();  //先读

if(a_a != 1)  //新的单片机初始单片机内问EEPOM  
{  
s_temp   = 50;  
s_dengji = 5;   
a_a = 1;   
write_eepom();
}
}


/***********************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的串行协议进行的
       //  1  0  0 通道
       //  1  1  1 通道
  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;  
        for(i=0;i<smg_i;i++)
{                  
        P2 = smg_we[i];     //位选
   P1 = dis_smg[i];   //段选
         delay_1ms(1);  
  P1 = 0xff;    //消隐
    P2 = 0xff;        //位选
     }
}


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


/****************按键处理数码管显示函数***************/



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)   
                                        {    dis_smg[0] = smg_du[temperature % 10];  //取温度的个位数显示
               dis_smg[1] = smg_du[temperature / 10 % 10]; //取温度的十位显示
               smg_i = 3;  
}  


if(menu_1 == 1)   
                {   


                        dis_smg[0] = smg_du[s_temp % 10];            //取个位显示
      dis_smg[1] = smg_du[s_temp / 10 % 10] ;  //取十位显示
      dis_smg[2] = 0xbf ;   
                        dis_smg[3] = smg_du[10]; //显示A   
                        smg_i = 4;   
}   
                        if(menu_1 == 2)   
                                {     
                                        dis_smg[0] = smg_du[s_dengji % 10];            //取个位显示
          dis_smg[1] = 0xbf ;      
                                        dis_smg[2] = 0xbf ;   
                                        dis_smg[3] = smg_du[11]; //显示B   
                                        smg_i = 4;  
}  
                                        }
                                       
                                        if(menu_1 == 0)  
                                                {  
                                                        if((key_can == 2) || (key_can == 3))   
                                                                shoudong = 0;          //取消手动报警
  }   
          if(menu_1 == 1)   //设置高温报警
              {     
                                                                if(key_can == 2)   
                                                                        {   if(flag_lj_3_en == 0)     
                                                                                s_temp ++ ;  //按键按下未松开自动加三次
     else        
                         s_temp += 10; //按键按下未松开自动加三次之后每次自动加10   
                 if(s_temp > 99)  
                         s_temp = 99;  
                 dis_smg[0] = smg_du[s_temp % 10];            //取个位显示
    dis_smg[1] = smg_du[s_temp / 10 % 10];        //取十位显示
    dis_smg[2] = 0xbf ;   
                 dis_smg[3] = smg_du[10]; //显示A   
                 }   
                 if(key_can == 3)  
                         {    if(flag_lj_3_en == 0)     
                                 s_temp .. ;  //按键按下未松开自动加三次
     else   
                         s_temp .= 10; //按键按下未松开自动减三次之后每次自动减10   
                 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] = 0xbf;   
                 dis_smg[3] = smg_du[10]; //显示A  
                 }  
}  
if(menu_1 == 2)   //设置低温报警
  {   
                if(key_can == 2)  
                        {   
                                if(flag_lj_3_en == 0)
                 s_dengji ++ ;     
                                else     
                                        s_dengji ++ ;   
                                if(s_dengji >= 9)  
                                        s_dengji = 9;   
                                dis_smg[0] = smg_du[s_dengji % 10];            //取个位显示
        dis_smg[1] = 0xbf ;     
                                dis_smg[2] = 0xbf ;   
                                dis_smg[3] = smg_du[11]; //显示B  
                                }   
                                if(key_can == 3)  
                                        {  
                                                if(flag_lj_3_en == 0)   
                                                        s_dengji .. ;     
                                                else     
                                                        s_dengji ..;   
                                                if(s_dengji <= 1)   
                                                        s_dengji = 1;   
                                                dis_smg[0] = smg_du[s_dengji % 10];            //取个位显示
             dis_smg[1] = 0xbf ;   
                                                dis_smg[2] = 0xbf;
                                                dis_smg[3] = smg_du[11]; //显示B  
                                                }
}
}   






/****************独立按键处理函数************************/
void key()
{
         static uchar key_new = 0,key_old = 0,key_value = 0;  
         if(key_new == 0)     
                 {         //按键松开的时候做松手检测
   if((P2 & 0x0f) == 0x0f)   
                 key_value ++;


  else     
                key_value = 0;  
        if(key_value >= 5)  
                {    write_eepom();  
                        key_value = 0;  
                        key_time = 0;  
                        key_new = 1;  
                        flag_lj_en = 0;  //关闭连加使能       
                        flag_lj_3_en = 0; //关闭3秒后使能       
                        flag_value = 0;  //清零
   }  
}


else  
         {   
                 if((P2 & 0x0f) != 0x0f)
                         key_value ++;  //按键按下的时候
   else   
                 key_value = 0;   
         if(key_value >= 5)  
                 {    key_value = 0;   
                         key_new = 0;   
                         flag_lj_en = 1;     //连加使能
    zd_break_en = 1;    //自动退出设置界使能
    zd_break_value = 0; //自动退出设置界变量清零
   }   
}
         key_can = 20;  
         if(key_500ms == 1)
                 {   key_500ms = 0;   
                         zd_break_en = 1; //自动退出设置界使能


  zd_break_value = 0; //自动退出设置界变量清零
   key_new = 0;   
                         key_old = 1;  
                         }  
                         if((key_new == 0) && (key_old == 1))
                                 {   switch(P2 & 0x0f)   
                                         {    case 0x0e: key_can = 4;
                                                 break;    //得到k1键值
    case 0x0d:
                        key_can = 3; break;    //得到                                                 k2键值
    case 0x0b: key_can = 2; break;    //得到键值
    case 0x07: key_can = 1; break;    //得到k4键值
               
   }
}     
key_old = key_new;  
}


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

  value = 0;
                 beep = 1;  
                 }
                 }
                 }  
                 void main()
                 {  
                         static uchar value;
                         temperature = read_temp();  //读取温度值

                         init_eepom();         //读数据

                         time_init();    //初始化定时器

                         delay_1ms(650);   
                         while(1)  
                                 {  
                                         key();     //独立按键程序

                                         if(key_can < 10)  
                                                 {   
                                                         key_with();   //按键按下要执行的程序

}  
temperature = read_temp();  //读取温度值

if(flag_300ms == 1)  
         {      
                 flag_300ms = 0;   
                 clock_h_l();   
                 dengji = ad0832read(1,0);
                 dengji = dengji * 10 / 250;  
                 huoyan = ad0832read(1,1);     
                 huoyan = 10 . huoyan * 10 / 250;   
                 if(menu_1 == 0)   
                         {   
                                 if(temperature >= 99)
temperature = 99;


if(value > 20)   
   value = 0;         
if(huoyan < 2)   
         {      
                 smg_i = 4;
     dis_smg[3]=smg_du[dengji];     //显示烟物报警等级
      dis_smg[2]= 0xbf;             // .      
                 dis_smg[1]=smg_du[temperature/10%10]; //十位
      dis_smg[0]=smg_du[temperature%10];     //个位 ADC0832为8位ADC,数值为0~255,我们将其分开放入l_tmpdate数组中显示
     }
                 else     
                         {   
                                 shoudong = 1;   
                                 smg_i = 4;      
                                 dis_smg[3]=0x89;  //H;        
                                 dis_smg[2]=0x89;  //H;               
                                 dis_smg[1]=0x89;  //H;      
                                 dis_smg[0]=0x89;  //H;     
                                 }   
}   
if(zd_break_en == 1) //自动退出设置界面程序
    {     zd_break_value ++;  //每300ms加一次
     if(zd_break_value > 100)   //30秒后自动退出设置界面
     {     
                         menu_1 = 0;         
                         smg_i = 3;   
                         zd_break_en = 0;
                         zd_break_value = 0;   
  }  

}  
}   
display();   //数码管显示函数



}
}



/*************定时器0中断服务程序***************/
void time0_int()
interrupt 1
{   
        static uchar value;
        TH0 = 0x3c;
        TL0 = 0xb0;     // 50ms  value ++;   
        if(value % 6 == 0)  
                {   flag_300ms = 1;    //300ms  
                        value = 0;  }
                        if(flag_lj_en == 1)    //按下按键使能
  {  
                key_time ++;
                if(key_time >= 10) //500ms
                        {    key_time = 0;   
                                key_500ms = 1; //500ms   
                                flag_value ++;   
                                if(flag_value > 3)   
                                        {     flag_value = 10;   
                                                flag_lj_3_en = 1; //3次后1.5秒连加大些
    }   

}

}

}
















分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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