利用ADC0832對煙霧傳感器進行仿真并報警
煙霧探測元件清單
51hei.png (10.65 KB, 下載次數: 62)
下載附件
2020-5-21 20:18 上傳
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
proteus圖.png (69.87 KB, 下載次數: 64)
下載附件
2020-5-21 18:49 上傳
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
51hei.png (17.92 KB, 下載次數: 55)
下載附件
2020-5-21 20:19 上傳
51hei.png (64.26 KB, 下載次數: 56)
下載附件
2020-5-21 20:20 上傳
單片機源程序如下:
#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)
2020-5-21 20:20 上傳
點擊文件名下載附件
可以參考這個可用:http://www.zg4o1577.cn/bbs/dpj-80294-1.html
|