#include <reg51.h>
#include <intrins.h> //需要調用_nop_();延時函數(shù)
#define uchar unsigned char
#define uint unsigned int
#define High_Temp 35 //定義空調適宜最高溫度為35度
#define Low_Temp 15 //定義空調適宜最低溫度為15度
/**********************第一部分門廳人員感應****************************/
sbit SPK = P3^4; //音頻輸出
sbit door_call = P1^5; //紅外感應按鈕
sbit LED = P3^3; //LED黃燈輸出
uint T_count = 0; //全局整形變量控制 叮咚 聲響時長。
/**********************第二部分對溫度的檢測與控制****************************/
sbit DQ = P3^0; //18B20數(shù)據(jù)線引腳
sbit Speaker=P3^1; //蜂鳴器的定義
sbit KongTiao=P3^2; //電機的定義
sbit RTGY=P1^4; //空調人體感應的定義
/**********************第三部分天燃氣檢測 ****************************/
sbit TRQ = P1^6; //天然氣感應按鈕
sbit up=P3^5; //自動開窗
sbit down=P3^6; //自動關窗
//初始化程序
void initA ()
{
TMOD=0x00; //T1方式定時器
TH1=(8192-700)/32; //700us定時/初值高8位放TH1
TL1=(8192-700)%32; //初值低5位放TL1
IE=0x88; //打開T1中斷
}
//T1中斷控制叮咚聲響程序
void Timer1() interrupt 3 //定時器中斷服務函數(shù)
{
SPK=~SPK;
T_count ++;
if(T_count < 400) //叮 時長為400*700us
{
TH1=(8192-700)/32; //0.3ms實現(xiàn) 叮 的音
TL1=(8192-700)%32;
}
else if(T_count < 900) //咚 時長為400*1000us
{
TH1=(8192-900)/32; //1ms實現(xiàn) 咚 的音
TL1=(8192-900)%32;
}
else
{
TR1=0; //關閉本次呼叫呼叫
T_count=0; //時長計數(shù)清零
}
}
/**********************第二部分溫度檢測部分****************************/
uchar bw,sw,gw; //溫度的百 十 個位。
uchar code DSY_CODE[]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,
0x82,0xf8,0x80,0x90,0xbf,0xff,0xC6};
void Delay_2US(uint us) //微秒延時,延時2*50us
{
while(--us);
}
void Delay_50Us(uint t) //微秒延時,延時t*50us
{
uchar j;
while(t--)
for(j=19;j>0;j--);
}
//DS18B20復位函數(shù)
void reset()
{
uchar x=0;
DQ=1; //復位DQ
Delay_2US(8);
DQ=0; //將DQ拉低
Delay_2US(80);//精確延時 >480us <960us
DQ=1; //將DQ拉高
Delay_2US(14); //延時15~60us后,接收脈沖
x=DQ; //DQ 若為0則初始化成功,否則失敗
Delay_2US(20);
}
//讀取一個字節(jié)的數(shù)據(jù)函數(shù)
uchar Ds18b20_Read(void)
{
uchar i=0;
uchar dat=0;
for(i=8;i>0;i--)
{
DQ=0;
dat>>=1; //右移一位
DQ=1;
_nop_();
if(DQ)dat=dat|0x80;
Delay_2US(20);
}
return(dat);
}
//寫入一個字節(jié)的數(shù)據(jù)函數(shù)
void Ds18b20_Write(uchar dat)
{
uchar i=0;
for(i=8;i>0;i--)
{
DQ=0;
_nop_();
DQ=dat&0x01;
Delay_2US(20);
DQ=1;
dat>>=1;
}
}
//讀取實際溫度函數(shù)
uchar Ds18b20_Read_Temperature(void)
{
uchar temp1,temp;
int temp2;
reset();
Ds18b20_Write(0xCC); //跳過ROM
Ds18b20_Write(0x44); //啟動DS18B20進行溫度轉換
Delay_2US(200);
reset();
Ds18b20_Write(0xCC); //跳過ROM
Ds18b20_Write(0xBE); //讀DS18B20內部暫存器命令
Delay_2US(200);
temp1=Ds18b20_Read(); //讀出低字節(jié)
temp2=Ds18b20_Read(); //讀出高字節(jié)
temp=(temp1|(temp2<<8))>>4;
return temp;
}
/*****轉換成十進制溫度并顯示*********/
void Change_Display(uchar i)
{
uchar temp=i;
if((temp&0xc0)==0xc0)
{
temp=~temp+1;
bw=10;
sw=(temp/10==0)?11:temp/10;
gw=temp%10;
}
else
{
bw=(temp/100==0)?11:1;
if(bw!=1)
sw=(temp/10==0)?11:temp/10;
else sw=(temp-100)/10;
gw=temp%10;
}
P1=~0x01; P2=~DSY_CODE[bw]; Delay_2US(900); //顯示十位
P1=~0x02; P2=~DSY_CODE[sw]; Delay_2US(900); //顯示個位
P1=~0x04; P2=(~DSY_CODE[gw]+0x80); Delay_2US(900); //顯示小數(shù)點后一位
P1=~0x08; P2=~DSY_CODE[12]; Delay_2US(900); //顯示溫度C
}
/********************************第一部分控制*********************************/
//紅外感應控制程序
void D_1bf()
{
if(door_call==0) //按下按鍵啟動定時器
{
TR1=1; //啟動計數(shù),T1中斷開始工作并發(fā)出叮咚聲
while(!door_call);//等鍵釋放
LED=~LED;
Delay_50Us(8000);
LED=1;
}
}
/********************************第三部分窗戶的開關控制*********************************/
//開窗
void pwm1()
{
uchar i;
for(i=0;i<10;i++)
{
down=0;//確保窗戶不閉合
up=1;
Delay_2US(10);
up=0;
Delay_2US(10);
}
up=0;
}
/****主函數(shù)**********/
void main()
{
uchar i;
initA (); //第一部分初始化
while(1)
{
i=Ds18b20_Read_Temperature(); //讀取溫度
Change_Display(i); //顯示溫度
//對串口的初始化定義
KongTiao=1;
RTGY=1;
TRQ=1;
LED=1;
Speaker=1;
//判斷是否有人進門
if(!door_call) D_1bf(); //第一部分判斷程序調用
//判斷天然氣是否泄漏
if(!TRQ)
{
Speaker=0; //蜂鳴器報警
pwm1();
}
//判斷當前溫度是否超值,是否需要啟動空調
if(RTGY==0 & i!=0)
{
if(i>High_Temp||i<Low_Temp) //蜂鳴器報警判斷電路
{
Speaker=0; //蜂鳴器報警
KongTiao=0;
}
}
}
}
|