基于AT89S52单片机的温湿度报警系统

     这是给深圳的一个客户做的一个项目,虽说是工业项目吧,但难度也是比毕业设计高一点吧。

原理图:

基于AT89S52单片机的温湿度报警系统_第1张图片

dht11.h

#ifndef __dht11_H
#define __dht11_H

#include

typedef unsigned char  U8;       /*    无符号8位整型变量  */
typedef signed   char  S8;       /*     有符号8位整型变量  */
typedef unsigned int   U16;      /*     无符号16位整型变量 */
typedef signed   int   S16;      /*    有符号16位整型变量 */
typedef unsigned long  U32;      /*    无符号32位整型变量 */
typedef signed   long  S32;      /*    有符号32位整型变量 */
typedef float          F32;      /*  单精度浮点数(32位长度) */
typedef double         F64;      /*  双精度浮点数(64位长度) */

extern U8  U8FLAG,k;
extern U8  U8count,U8temp;
extern U8  U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
extern U8  U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
extern U8  U8comdata;

sbit  P1_0  = P1^0 ;

void  Delay(U16 j);
void  Delay_10us(void);
void  COM(void);
void  RH(void);

#endif

dht11.c

#include "dht11.h"

 U8  U8FLAG,k;
 U8  U8count,U8temp;
 U8  U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;
 U8  U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
 U8  U8comdata;

 void Delay(U16 j)
  {    
      U8 i;
     for(;j>0;j--)
   {  
  for(i=0;i<27;i++);

   }
  }
 void  Delay_10us(void)
{
        U8 i;
        i--;
        i--;
        i--;
        i--;
        i--;
        i--;
}
 
void  COM(void)
{
    
     U8 i;
       for(i=0;i<8;i++)   
     {
  
         U8FLAG=2; 
     while((!P1_0)&&U8FLAG++);
   Delay_10us();
   Delay_10us();
  // Delay_10us();
     U8temp=0;
      if(P1_0)U8temp=1;
      U8FLAG=2;
   while((P1_0)&&U8FLAG++);
    
     //超时则跳出for循环   
      if(U8FLAG==1)break;
     //判断数据位是0还是1 
       
  // 如果高电平高过预定0高电平值则数据位为 1
     
     U8comdata<<=1;
        U8comdata|=U8temp;       
      }
}

 //--------------------------------
 //-----湿度读取子程序 ------------
 //--------------------------------
 //----以下变量均为全局变量--------
 //----温度高8位== U8T_data_H------
 //----温度低8位== U8T_data_L------
 //----湿度高8位== U8RH_data_H-----
 //----湿度低8位== U8RH_data_L-----
 //----校验 8位 == U8checkdata-----
 //----调用相关子程序如下----------
 //---- Delay();, Delay_10us();,COM();
 //--------------------------------

 void RH(void)
 {
   //主机拉低18ms
       P1_0=0;
    Delay(180);
    P1_0=1;
  //总线由上拉电阻拉高 主机延时20us
    Delay_10us();
    Delay_10us();
    Delay_10us();
    Delay_10us();
  //主机设为输入 判断从机响应信号
    P1_0=1;
  //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行  
    if(!P1_0)   //T !  
    {
    U8FLAG=2;
  //判断从机是否发出 80us 的低电平响应信号是否结束 
    while((!P1_0)&&U8FLAG++);
    U8FLAG=2;
  //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
    while((P1_0)&&U8FLAG++);
  //数据接收状态  
    COM();
    U8RH_data_H_temp=U8comdata;
    COM();
    U8RH_data_L_temp=U8comdata;
    COM();
    U8T_data_H_temp=U8comdata;
    COM();
    U8T_data_L_temp=U8comdata;
    COM();
    U8checkdata_temp=U8comdata;
    P1_0=1;
  //数据校验
 
    U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);
    if(U8temp==U8checkdata_temp)
    {
       U8RH_data_H=U8RH_data_H_temp;
       U8RH_data_L=U8RH_data_L_temp;
    U8T_data_H=U8T_data_H_temp;
       U8T_data_L=U8T_data_L_temp;
       U8checkdata=U8checkdata_temp;
    }
    }

 }
 

ds1302.h

#ifndef __DS1302_H
#define __DS1302_H

#include

#define uchar unsigned char
#define uint  unsigned int

void Delay_1ms(uint i);
void W_byte(uchar dat);
uchar R_byte(void);
void Rest_ds1302();
void Clear_wp();
void Set_wp();
uchar Dectobcd(uchar dec);
void W_ds1302(uchar add,uchar dat);
uchar R_ds1302(uchar add);

#endif

 

ds1302.c

#include "ds1302.h"

/**********DS1302定义**********/
sbit D_sclk=P1^1;
sbit D_io  =P1^2;
sbit D_rest=P1^3;


/********************************************************************
* 名称 : Delay_1ms()
* 功能 : 延时子程序,延时时间为 1ms * x
* 输入 : x (延时一毫秒的个数)
* 输出 : 无
***********************************************************************/
void Delay_1ms(uint i)//1ms延时
{
 uchar x,j;
 for(j=0;j  for(x=0;x<=148;x++); 
}

/********************写入一个字节数据*************************/
void W_byte(uchar dat)
{
 uchar i;
 D_sclk=0;
 for(i=0;i<8;i++)
 {
  D_io=(bit)(dat&0x01);
  D_sclk=1;
  dat>>=1;
  D_sclk=0;  
 }
}

/*******************读取一个字节数据*********************/
uchar R_byte()
{
 uchar i,dat=0;
 for(i=0;i<8;i++)
 {
  dat>>=1;
  if(D_io)
   dat|=0x80;
  D_sclk=1;
  D_sclk=0;
 }
 return dat;
}

/***************复位DS1302****************/
void Rest_ds1302()
{
 D_rest=0;
 D_sclk=0;
 D_rest=1;  
}
/***************清除DS1302保护****************/
void Clear_wp()
{
 Rest_ds1302();
 D_rest=1;
 W_byte(0x8e);
 W_byte(0x00);/***写入0清除保护***/
 D_io=0;
 D_rest=0; 
}

/***************写入DS1302保护****************/
void Set_wp()
{
 Rest_ds1302();
 D_rest=1;
 W_byte(0x8e);
 W_byte(0x80);/***写入0x80写入保护***/
 D_io=0;
 D_rest=0; 
}

/***********************DEC码转换为BCD码****************/
uchar Dectobcd(uchar dec)
{
 uchar bcd;
 bcd = 0;
 while(dec >= 10)
 {             
  dec -= 10;                        
  bcd++;
 }
 bcd <<= 4;
 bcd |= dec;
 return bcd;
}


/********************向DS1302写入数据****************************/
void W_ds1302(uchar add,uchar dat)
{
 Rest_ds1302();
 D_rest=1;
 W_byte(add);
 W_byte(dat);
 D_io=0;
 D_rest=0;  
}

/********************从DS1302读取数据*************************/
uchar R_ds1302(uchar add)
{
 uchar dat=0;
 Rest_ds1302();
 D_rest=1;
 W_byte(add);
 dat=R_byte();
 D_io=0;
 D_rest=0;
 return dat;  
}

 1602.h

#ifndef __lcd1602_H
#define __lcd1602_H

#include
#include

#define uchar unsigned char
#define uint  unsigned int

sbit  RS=  P2^7;
sbit  RW=  P2^6;
sbit  EN=  P2^5;
sbit  BUSY=P0^7;

void _delay_ms(uint ms_number);
void _delay_us(uint us_number);
void W_dat(uchar dat);
void W_cmd(uchar cmd);
void Write_dat(uchar cmd,uchar dat);
void Init_LCD1602(void);
void Display_set(uchar add,uchar sec,uchar min,uchar hour,uchar day,uchar month,uchar week,uchar year);
void Display_num(uchar add,uchar num);
void Display_s(uchar add,uchar *dat);


#endif

 1602.c

#include "lcd1602.h"

/*--------------------ms延时函数-----------------------*/
void _delay_ms(uint ms_number) // ms延时函数 (AT89C51 @ 11.0592MHz)
{
 unsigned int i;
 unsigned char j;
 for(i=0;i  {
  for(j=0;j<200;j++);
  for(j=0;j<102;j++);
 }
}
 void _delay_us(uint us_number)//延时时间为 1us * x 晶振是11.0592M 
 {
  unsigned int i;
  for(i = 0; i < us_number ; i++)
  _nop_();
 }
/**********************等待函数*********************/
void Wait (void) 
{
 RS=1;
 do
 {
  RS=0;
  RW=1;
  EN=0;
  _nop_();
  EN=1;

 } while(BUSY==1);
 EN=0;

}

/**************************写数据*************************/
void W_dat(uchar dat) 
{
 Wait(); 
 _delay_ms(5);
 
 
 RS=1;
 RW=0;
 EN=1;
 P0= dat;
 _nop_();
 EN=0;
}

/**************************写命令*************************/
void  W_cmd(uchar cmd)
{
 Wait();
 _delay_ms(5);


 RS=0;
 RW=0;
 EN=1;
 P0=cmd;
 _nop_();
 EN=0;
}

/***********************往固定地址写数据函数*********************/
void Write_dat(uchar cmd,uchar dat)

 W_cmd(cmd);
 W_dat(dat);
}

/**********************LCD1602初始化***************************/
void Init_LCD1602(void)
{
    _delay_ms(15);
 W_cmd(0x38);//16*2显示,5*7点阵,8位数据接口
 _delay_ms(5);
 W_cmd(0x38);//16*2显示,5*7点阵,8位数据接口
 _delay_ms(5);
 W_cmd(0x38);//16*2显示,5*7点阵,8位数据接口
 W_cmd(0x08); //关闭显示
 W_cmd(0x01);//清屏
 W_cmd(0x0C);//显示器开,光标关,光标不允许闪烁
 W_cmd(0x06);//文字不动,光标自动右移
     
}

/**************************显示数字**************************/
void Display_num(uchar add,uchar num)
{
 Write_dat(add,num/10+'0');
 Write_dat(add+1,num%10+'0');   
}

/**************************显示数字**************************/
void Display_set(uchar add,uchar sec,uchar min,uchar hour,uchar day,uchar month,uchar week,uchar year)

    Write_dat(add,sec/10+'0');
 Write_dat(add+1,sec%10+'0'); 
 
 Write_dat(add+2,min/10+'0');
 Write_dat(add+3,min%10+'0');

 Write_dat(add+4,hour/10+'0');
 Write_dat(add+5,hour%10+'0');
 
 Write_dat(add+7,day/10+'0');
 Write_dat(add+8,day%10+'0'); 
 
 Write_dat(add+9,month/10+'0');
 Write_dat(add+10,month%10+'0');

 Write_dat(add+11,week/10+'0');
 Write_dat(add+12,week%10+'0');

 Write_dat(add+14,year/10+'0');
 Write_dat(add+15,year%10+'0');

}

/**************************显示字符串**************************/
void Display_s(uchar add,uchar *dat)
{
 uchar j=add;
 while(*dat!='\0')
 {
  Write_dat(j,*dat);
  j++;
  dat++; 
 }
}

main.c

#include "lcd1602.h"
#include "ds1302.h"
#include "dht11.h"

/**********按键定义**********/
sbit Key_en    =P2^0;
sbit Key_up    =P2^1;         //还是关闭报警开关
sbit Key_down  =P2^2;
sbit Key_switch=P2^3;

/**********蜂鸣器定义**********/
sbit Beep=P3^5;

/**********指示灯定义**********/
sbit Led=P3^4;

/**************秒分时,日月周,年***********/
char time[7]={16,23,9,6,8,7,13};
uchar sign=0, flag=0;
//uchar a=0;


/******************函数声明********************/
void Set_time(uchar  *timedate);
void Read_time(uchar *timedate);
void Key_scan();
void Beep_play();


/****************设定时间******************/
void Set_time(uchar  *timedate)
{ uchar i,temp=0;
 for(i=0;i<7;i++)
 {
  temp=timedate[i]/10;
  timedate[i]=timedate[i]%10;
  timedate[i]=timedate[i]+temp*16;
 }

 Clear_wp();
 temp=0X80;  // 0x80写命令
 for(i=0;i<7;i++)
 {
  W_ds1302(temp,timedate[i]);
  temp=temp+2;
 }
 Set_wp();
}

/*******************读取时间********************/
void Read_time(uchar *timedate)
{
 uchar i,temp=0;
 temp=0X81;                           // 0x81读命令
 for(i=0;i<7;i++)
 {
     timedate[i]=R_ds1302(temp);
  temp=temp+2;
 } 
 time[0]=time[0]&0x7f; 
 for(i=0;i<7;i++)
 {
  temp=timedate[i]/16;
  timedate[i]=timedate[i]%16;
  timedate[i]=timedate[i]+temp*10;
 }
}

/**********************使能关闭时钟************************/
void Key_scan()
{
    if(Key_en==0)
 {
  Delay_1ms(5);
  if(Key_en==0)
  {  
   while(!Key_en);
   sign=0x80|Dectobcd(time[0]);
   Clear_wp();
   W_ds1302(0x80,sign);/***时钟停止***/
   Set_wp();
   flag++; 
   W_cmd(0x0f);/****光标打开****/           //
  }           
  }
  /*************选择函数********************/
  if(!Key_switch)
  { 
     Delay_1ms(5);
  if(!Key_switch)
  while(!Key_switch);
   flag++;
  }
       /**********调节秒钟******************/
 if(flag==3)
 { 
  W_cmd(0xC0+0x01);                 /***标光标***/
  if(Key_up==0)
  {
   Delay_1ms(5);
   if(Key_up==0)
   {
    while(!Key_up);
    time[0]++;
    if(time[0]==60)
    time[0]=0;
    Clear_wp();
    W_ds1302(0x80,Dectobcd(0x80|time[0]));
    Set_wp();
   } 
  }
  if(Key_down==0)
  {
   Delay_1ms(5);
   if(Key_down==0)
   {
    while(!Key_down);
    time[0]--;
    if(time[0]==-1) time[0]=59;
    Clear_wp();
    W_ds1302(0x80,Dectobcd(0x80|time[0]));
    Set_wp();  
   } 
  }
  
 }
         /**********调节分钟******************/
 if(flag==2)
 { 
  W_cmd(0xC0+0x03);                 /***标光标***/
  if(Key_up==0)
  {
   Delay_1ms(5);
   if(Key_up==0)
   {
    while(!Key_up);
    time[1]++;
    if(time[1]==60)
    time[1]=0;
    Clear_wp();
    W_ds1302(0x82,Dectobcd(time[1]));
    Set_wp();
   } 
  }
  if(Key_down==0)
  {
   Delay_1ms(5);
   if(Key_down==0)
   {
    while(!Key_down);
    time[1]--;
    if(time[1]==-1) time[1]=59;
    Clear_wp();
    W_ds1302(0x82,Dectobcd(time[1]));
    Set_wp();  
   } 
  }
  
 }
    /***********调节小时***********/
 if(flag==1)
 {   
  W_cmd(0XC0+0x05);/***标光标***/
  if(Key_up==0)
  {
   Delay_1ms(5);
   if(Key_up==0)
   {
    while(!Key_up);
    time[2]++;
    if(time[2]==24) time[2]=1;
    Clear_wp();
    W_ds1302(0x84,Dectobcd(time[2]));
    Set_wp();  
   } 
  }


  if(Key_down==0)
  {
   Delay_1ms(5);
   if(Key_down==0)
   {
    while(!Key_down);
    time[2]--;
    if(time[2]==-1) time[2]=23;
    Clear_wp();
    W_ds1302(0x84,Dectobcd(time[2]));
    Set_wp();  
   } 
  } 
 }
  /***********调节天数***********/
 if(flag==4)
 {   
  W_cmd(0XC0+0X08);/***标光标***/
  if(Key_up==0)
  {
   Delay_1ms(5);
   if(Key_up==0)
   {
    while(!Key_up);
    time[3]++;
    if(time[3]==31) time[3]=1;
    Clear_wp();
    W_ds1302(0x86,Dectobcd(time[3]));
    Set_wp();  
   } 
  }
  if(Key_down==0)
  {
   Delay_1ms(5);
   if(Key_down==0)
   {
    while(!Key_down);
    time[3]--;
    if(time[3]==-1) time[3]=30;
    Clear_wp();
    W_ds1302(0x86,Dectobcd(time[3]));
    Set_wp();  
   } 
  } 
 }
  /***********调节月数***********/
 if(flag==5)
 {   
  W_cmd(0XC0+0X10);/***标光标***/
  if(Key_up==0)
  {
   Delay_1ms(5);
   if(Key_up==0)
   {
    while(!Key_up);
    time[4]++;
    if(time[4]==12) time[4]=1;
    Clear_wp();
    W_ds1302(0x88,Dectobcd(time[4]));
    Set_wp();  
   } 
  }
  if(Key_down==0)
  {
   Delay_1ms(5);
   if(Key_down==0)
   {
    while(!Key_down);
    time[4]--;
    if(time[4]==-1) time[4]=11;
    Clear_wp();
    W_ds1302(0x88,Dectobcd(time[4]));
    Set_wp();  
   } 
  } 
 }
  /***********调节周日数***********/
 if(flag==6)
 {   
  W_cmd(0XC0+0X12);/***标光标***/
  if(Key_up==0)
  {
   Delay_1ms(5);
   if(Key_up==0)
   {
    while(!Key_up);
    time[5]++;
    if(time[5]==7) time[5]=1;
    Clear_wp();
    W_ds1302(0x8A,Dectobcd(time[5]));
    Set_wp();  
   } 
  }
  if(Key_down==0)
  {
   Delay_1ms(5);
   if(Key_down==0)
   {
    while(!Key_down);
    time[5]--;
    if(time[5]==-1) time[5]=6;
    Clear_wp();
    W_ds1302(0x8A,Dectobcd(time[5]));
    Set_wp();  
   } 
  } 
 }
  /***********调节年********/
 if(flag==7)
 {   
  W_cmd(0XC0+0X15);/***标光标***/
  if(Key_up==0)
  {
   Delay_1ms(5);
   if(Key_up==0)
   {
    while(!Key_up);
    time[6]++;
    Clear_wp();
    W_ds1302(0x8C,Dectobcd(time[6]));
    Set_wp();  
   } 
  }
  if(Key_down==0)
  {
   Delay_1ms(5);
   if(Key_down==0)
   {
    while(!Key_down);
    time[6]--;
    Clear_wp();
    W_ds1302(0x8C,Dectobcd(time[6]));
    Set_wp();  
   } 
  } 
 }
   /****************使能打开时钟****************/
 if(flag>=8)
 {
  Clear_wp();
  W_ds1302(0x80,0);/***时钟开始***/
  Set_wp();
  flag=0;
  W_cmd(0X0C);/****光标关闭****/
  Delay_1ms(10);
  Init_LCD1602();
  Delay_1ms(10);
 }

}
/****************蜂鸣器、LED报警*********************/
void Beep_play()
{
 
   //if(a==0)
   if((U8RH_data_H >= 70) | (U8T_data_H >= 40))
   {
    Beep=0;
    Led=0;
   }
   //if((U8RH_data_H < 70) & (U8T_data_H < 40))
   //a=0;
   if(Key_up==0)
 {
  Delay_1ms(5);
  if(Key_up==0)
  {  
   Beep=1;
   Led=1;
//   a=1;
   while(!Key_up);   
   }
  }
  _delay_ms(10);

}  
void main()
{
 Init_LCD1602();
 Set_time(time); 
 while(1)
 { 
  Beep_play();
     RH();
  Read_time(time);
  Key_scan();
     Write_dat(0x80,'R');
     Write_dat(0x81,':');
     Display_num(0x82,U8RH_data_H);
     Write_dat(0x84,'%');
  Key_scan();
     Write_dat(0x86,'T');
     Write_dat(0x87,':');
  Key_scan();
     Display_num(0x88,U8T_data_H);
     Write_dat(0x8A,0xdf);
     Write_dat(0x8B,0x43);
     Display_set(0xC0,time[2],time[1],time[0],time[3],time[4],time[5],time[6]);
  Beep_play();        
 } 

}

实物图:

基于AT89S52单片机的温湿度报警系统_第2张图片

你可能感兴趣的:(单片机)