#include <reg51.h>
#include <intrins.h> //需要调用_nop_();延时函数
#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数据线引脚
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 //定时器中断服务函数
{
SPK=~SPK;
T_count ++;
if(T_count < 400) //叮 时长为400*700us
{
TH1=(8192-700)/32; //0.3ms实现 叮 的音
TL1=(8192-700)%32;
}
else if(T_count < 900) //咚 时长为400*1000us
{
TH1=(8192-900)/32; //1ms实现 咚 的音
TL1=(8192-900)%32;
}
else
{
TR1=0; //关闭本次呼叫呼叫
T_count=0; //时长计数清零
}
}
/**********************第二部分温度检测部分****************************/
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复位函数
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);
}
//读取一个字节的数据函数
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);
}
//写入一个字节的数据函数
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;
}
}
//读取实际温度函数
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(); //读出低字节
temp2=Ds18b20_Read(); //读出高字节
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); //显示小数点后一位
P1=~0x08; P2=~DSY_CODE[12]; Delay_2US(900); //显示温度C
}
/********************************第一部分控制*********************************/
//红外感应控制程序
void D_1bf()
{
if(door_call==0) //按下按键启动定时器
{
TR1=1; //启动计数,T1中断开始工作并发出叮咚声
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;
}
/****主函数**********/
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;
}
}
}
}
|