找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机烟雾传感器proteus仿真+程序+PCB原理图

[复制链接]
跳转到指定楼层
楼主
利用ADC0832对烟雾传感器进行仿真并报警

烟雾探测元件清单


仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)



单片机源程序如下:
#include<reg52.h>       //包含单片机寄存器的头文件
#include <intrins.h>    //包含_nop_()函数定义的头文件
#define uchar unsigned char
#define uint unsigned int
uchar a,q,t,t1;
long int s1,d0,b,c,d,s,e1,biao,biao1,biao2,a1;
uchar code qw[]={1,1,1};
uchar qs[5]={0,0,0,9,0,};
uchar key_buffer[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};//2013-01-03
sbit clk=P1^1;         //时钟
sbit cs=P1^0;          //片选端
sbit d1=P1^2;          //起始信号输入与端口选择及数据输出端
sbit rs=P2^5;          //将rS位定义为P2.5引脚
sbit e=P2^7;           //将e位定义为P2.7引脚
sbit rw=P2^6;          //将rw位定义为P2.6引脚
sbit k1=P1^4;
sbit k2=P1^5;
sbit k3=P1^6;
sbit k4=P1^7;
sbit D1=P2^0;          //正常指示灯(绿灯)
sbit D2=P2^1;          //警情指示灯(红灯)
sbit beep=P2^2;//蜂鸣器
uchar code tad[]="value:00000ppm";
uchar code tad1[]="Alarm:09000ppm";
/*****************************************************
函数功能:延时若干毫秒
入口参数:x

***************************************************/
void delay(uchar x)
{
        uint a,b;
        for(a=x;a>0;a--)
                for(b=90;b>0;b--);
}
uchar du()//读AD转换数据
{
        uchar i,k,j;
        cs=0;                //片选有效
        for(j=0;j<3;j++)   //通道选择
        {
                clk=1;
                d1=qw[j];
                for(q=0;q<2;q++)          _nop_();
                clk=0;
                for(q=0;q<2;q++)        _nop_();        
        }
        for(i=0;i<8;i++)
        {
                clk=1;
                for(q=0;q<2;q++)  _nop_();
                clk=0;
                for(q=0;q<2;q++) _nop_();
                k=(k<<1)|d1;
        }
        cs=1;
        for(q=0;q<28;q++)        _nop_();//延时
    return k;  //返回AD0832转换值
}
/*****************************************************
        液晶显示器LED1602

******************************************************/
void write_date(uchar date)
{
        rs=1;
        P0=date;
        delay(5);
        e=1;
        delay(5);
        e=0;        
}
void write_com(uchar com)
{
        rs=0;
        P0=com;
        delay(5);
        e=1;
        delay(5);
        e=0;        
}
void init()
{
        uchar num;
        e=0;
        write_com(0x38);
        write_com(0x0c);
        write_com(0x06);
        write_com(0x01);
        write_com(0x80);
        for(num=0;num<14;num++)
                {
                        write_date(tad[num]);
                                delay(2);
                        }
                write_com(0x80+0x40);        
        for(num=0;num<14;num++)
                        {
                        write_date(tad1[num]);
                                delay(2);
                        }
}
void write_sfm(uint date)//向1602送显示
{
        uint wan,pian,bai,shi,ge;
        wan=date/10000;
        pian=date%10000/1000;
        bai=date%10000%1000/100;
        shi=date%10000%1000%100/10;
        ge=date%10000%1000%100%10;
        write_com(0x80+6);
        write_date(0x30+wan);
        write_date(0x30+pian);
        write_date(0x30+bai);
        write_date(0x30+shi);
        write_date(0x30+ge);
}
void zh()//AD数据处理
{
                a=du();        
                b=(a/51);//整数
                s=(a%51);
                s1=(s*10);//整形为两个字节
                c=(s1/51);//小数1               
                d=(s1%51);
                d0=(d*10);//整形
                e1=(d0/51);//小数2
                b=b*100;
                c=c*10;
                a1=(b+c+e1);//a1必须定义为长整型
                delay(10);
                if(a1>140)
                {
                        a1=a1-140;
                        if(a1>=0)
                        {
                        a1=(a1*1000)/36;
                        write_sfm(a1);
                                        }
                        }
                else
                        write_sfm(0);
}
/*****************************************************

函数功能:报警子程序

*****************************************************/
void zx()//控制
{
        long int sa;
        sa=((qs[3]*1000)+(qs[2]*100)+(qs[1]*10)+qs[0]);        //报警设定值
        if(a1>sa) //烟雾检测值大于设定值
        {
                D2=0;        //报警红灯亮
                D1=1;         //正常指示绿灯灭
                biao2=1; //蜂鸣器报警标志置1
        }
        else
        {
                D1=0;        //正常指示绿灯亮
                D2=1;         //报警红灯灭
                biao2=0; //蜂鸣器报警标志清0
                beep=1;         //蜂鸣器不响
        }        
}
/*****************************************************
函数功能:按键识别

******************************************************/         
void key_scan()//按键识别
{
        uchar i;
        static uchar key_value,key_state=0;
        P1=0xf0;//设置P1口高4位为输入口
        
        if((P1&0xf0)!=0xf0)//有键按下
        {        
                delay(2);        //延时消抖                 
                key_state =P1&0xf0;
                if(key_state!=0xf0)        //再判有键按下
                {        
                        switch(key_state)
                        {
                                case 0xe0:                //S1按下
                                         key_value=1;        
                                         break;
                                case 0xd0://S2按下
                                        key_value=2;        
                                         break;
                                case 0xb0: //S3按下
                                        key_value=3;        
                                         break;
                                case 0x70: //S4按下
                                        key_value=4;        
                                         break;
                        }
                        for(i=0;i<7;i++) //按键队列FIFO处理
                                {
                                        key_buffer[ i]=key_buffer[i+1];
                                }
                                key_buffer[7]=key_value; //最新按键值存入缓冲队列                                 
                }
                while((P1&0xf0)!=0xf0);         //等待按键释放
        }
}  
/*****************************************************
函数功能:按键处理

******************************************************/         
void key_do()  // 按键处理
{
        uchar d,i;
        while((key_buffer[0]!=0xff)||(key_buffer[1]!=0xff)||(key_buffer[2]!=0xff)||(key_buffer[3]!=0xff)||(key_buffer[4]!=0xff)||
              (key_buffer[5]!=0xff)||(key_buffer[6]!=0xff)||(key_buffer[7]!=0xff))//有键按下
                {        
                        switch(key_buffer[0])
                        {
                                case 1:                //S1按下
                                         biao++;
                                         t1=1;
                                         TR1=0;
                                         if(biao==5)
                                         {
                                                TR1=1;
                                                biao=0;
                                                write_com(0x0c);//关闭光标闪烁
                                          }
                                         biao1=0;        
                                         break;
                                case 2://S2按下
                                                 if(biao==1)
                                                {
                                                        if(biao1==0)
                                                        {
                                                                write_com(0x80+0x40+10);//定位光标闪烁的位置
                                                                write_com(0x0f); //打开光标闪烁
                                                        }                                                                                                
                                                        d=qs[0];
                                                        d++;
                                                        if(d==10)        d=0;                                                                                 
                                                        write_com(0x80+0x40+10);
                                                        write_date(0x30+d);//送显示
                                                        write_com(0x80+0x40+10);//重新定位光标闪烁的位置                                                                                
                                                        qs[0]=d;
                                                        //biao1=1;
                                                }
                                                if(biao==2)
                                                {
                                                        if(biao1==0)
                                                                write_com(0x80+0x40+9);//定位光标闪烁的位置               
                                                        d=qs[1];
                                                        d++;
                                                        if(d==10)        d=0;                                                                                 
                                                        write_com(0x80+0x40+9);
                                                        write_date(0x30+d);//送显示
                                                        write_com(0x80+0x40+9);//重新定位光标闪烁的位置                                                                                
                                                        qs[1]=d;
                                                        //biao1=1;
                                                }
                                                if(biao==3)
                                                {
                                                        if(biao1==0)
                                                                write_com(0x80+0x40+8);//定位光标闪烁的位置               
                                                        d=qs[2];
                                                        d++;
                                                        if(d==10)        d=0;                                                                                 
                                                        write_com(0x80+0x40+8);
                                                        write_date(0x30+d);//送显示
                                                        write_com(0x80+0x40+8);//重新定位光标闪烁的位置                                                                                
                                                        qs[2]=d;                                                         
                                                }
                                                if(biao==4)
                                                {
                                                        if(biao1==0)
                                                                write_com(0x80+0x40+7);//定位光标闪烁的位置               
                                                        d=qs[3];
                                                        d++;
                                                        if(d==10)        d=0;                                                                                 
                                                        write_com(0x80+0x40+7);
                                                        write_date(0x30+d);//送显示
                                                        write_com(0x80+0x40+7);//重新定位光标闪烁的位置                                                                                
                                                        qs[3]=d;                                                         
                                                }
                                         biao1=1;
                                         break;

                                case 3: //S3按下
                                                if(biao==1)
                                                {
                                                        if(biao1==0)
                                                        {
                                                                write_com(0x80+0x40+10);//定位光标闪烁的位置
                                                                write_com(0x0f); //打开光标闪烁
                                                        }                                                                                                
                                                        d=qs[0];
                                                        d--;
                                                        if(d==-1)        d=9;                                                                                 
                                                        write_com(0x80+0x40+10);
                                                        write_date(0x30+d);//送显示
                                                        write_com(0x80+0x40+10);//重新定位光标闪烁的位置                                                                                
                                                        qs[0]=d;
                                                //        biao1=1;
                                                }
                                           if(biao==2)
                                                {
                                                        if(biao1==0)
                                                                write_com(0x80+0x40+9);//定位光标闪烁的位置               
                                                        d=qs[1];
                                                        d--;
                                                        if(d==-1)        d=9;                                                                                 
                                                        write_com(0x80+0x40+9);
                                                        write_date(0x30+d);//送显示
                                                        write_com(0x80+0x40+9);//重新定位光标闪烁的位置                                                                                
                                                        qs[1]=d;
                                                }
                                                if(biao==3)
                                                {
                                                        if(biao1==0)
                                                                write_com(0x80+0x40+8);//定位光标闪烁的位置               
                                                        d=qs[2];
                                                        d--;
                                                        if(d==-1)        d=9;                                                                                 
                                                        write_com(0x80+0x40+8);
                                                        write_date(0x30+d);//送显示
                                                        write_com(0x80+0x40+8);//重新定位光标闪烁的位置                                                                                
                                                        qs[2]=d;                                                         
                                                }
                                                if(biao==4)
                                                {
                                                        if(biao1==0)
                                                                write_com(0x80+0x40+7);//定位光标闪烁的位置               
                                                        d=qs[3];
                                                        d--;                                          
                                                        if(d==-1)        d=9;                                                                                 
                                                        write_com(0x80+0x40+7);
                                                        write_date(0x30+d);//送显示
                                                        write_com(0x80+0x40+7);//重新定位光标闪烁的位置                                                                                
                                                        qs[3]=d;                                                         
                                                }                                          
                                                biao1=1;
                                                 break;
                                case 4: //S4按下
                                                TR1=1;
                                                biao=0;
                                                write_com(0x0c);//关闭光标闪烁        
                                                 break;
                                default: break;
                        }

                        for(i=0;i<7;i++) //按键队列FIFO处理
                                {
                                        key_buffer[ i]=key_buffer[i+1];
                                }
                                key_buffer[7]=0xff; //缓冲队列单元恢复无键按下标志                                 
                }
}  


void init1()
{
        biao=0;
        biao1=0;biao2=0;beep=1;
        cs=1;
        clk=0;
        d1=0;
        rw=0;
        EA=1;
        ET1=1;
        TMOD=0x10;
        TH1=(65536-50000)/256;
        TL1=(65535-50000)%256;
        TR1=1;
        t1=0;
        D1=0;
        init();
}
/*****************************************************
函数功能:主函数
***************************************************/
main()
{
        init1();
        while(1)
        {
                if(biao==0)         //若打开报警功能
                        zx();        //调报警函数
                key_scan();
                key_do();//调按键处理函数,进行报警值设定
                if(t1==0) //定时时间到0.2s
                {
                        zh();  //调数据转换, 启动AD转换
                        t1=1;  //关闭数据转换和AD转换
                }
        }        
}
void as() interrupt 3          //定时器T1中断函数 ,定时启动数据转换和AD转换,并根据情况进行蜂鸣器报警
{
        TH1=(65536-50000)/256;//重赋初值
        TL1=(65535-50000)%256;
        t++;  //时间计数加1
        if(t==4) //50ms*4=0.2s,0.2s时间到
        {
                t=0;   //时间计数清0
                t1=!t1;         //启动数据转换和AD转换
                if(biao2==1)
                        beep=!beep;         //蜂鸣器报警
        }
}

程序问题还很多,大家能帮我修改一下吗?仿真图屏幕没有反应: 烟雾探测报警器.7z (269.35 KB, 下载次数: 164)
可以参考这个可用:http://www.51hei.com/bbs/dpj-80294-1.html

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:862725 发表于 2020-12-18 12:57 | 只看该作者
仿真之后没有反应是怎么回事?同求大家指导
回复

使用道具 举报

板凳
ID:440028 发表于 2022-1-5 14:37 | 只看该作者
好多都是没反应的,同求
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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