基于单片机的温度湿度采集系统

基于单片机的温度湿度采集系统

程序

/**************************************************************** 
***************************************************************/
#include <reg52.h>
#define uint unsigned int 
#define uchar unsigned char
#include <intrins.h>

typedef bit BOOL  ; 

sbit io = P1^1 ;//(口线定义)
sbit bee=P1^0;
sbit rs = P2^5 ; 
sbit rw = P2^6 ;
sbit ep = P2^7 ;
bit flag_300ms ;

sbit K1=P1^2;
sbit K2=P1^3;
sbit K3=P1^4;

uchar yemian=0;//(定义变量)
uchar flat=1;
uchar data_byte;
uchar RH,RL,TH,TL;
uchar WenDu,ShiDu;//报警的温度和湿度
#include "eeprom52.h"


/****************************延时程序****************************/
void delay(uchar ms)
{
    
           // 延时子程序
	 uchar i ;
	 while(ms--)
	 {
    
    
	  	for(i = 0 ; i<250;i++) ;
	 }
}

void delay1()//延时10us
{
    
    
	uchar i;
	i--;
	i--;
	i--;
	i--;
	i--;
	i--;
}
void longdelay(uchar s) //长延时
{
    
    
	 while(s--)
	 {
    
    
	  	delay(20) ;
	 }
}



/******************把数据保存到单片机内部eeprom中******************/
void write_eeprom()
{
    
    
	SectorErase(0x2000);
 	byte_write(0x2000, WenDu);
	byte_write(0x2001, ShiDu);
	byte_write(0x2060, a_a);	
}

/******************把数据从单片机内部eeprom中读出来*****************/
void read_eeprom()
{
    
    
	WenDu   = byte_read(0x2000);
  ShiDu = byte_read(0x2001);
	a_a      = byte_read(0x2060);
}

/**************开机自检eeprom初始化*****************/
void init_eeprom()
{
    
    
	read_eeprom();		//先读
	if(a_a != 2)		//新的单片机初始单片机内问eeprom
	{
    
    
	WenDu   = 30;
	ShiDu   = 80;
		a_a = 2;
		write_eeprom();
	}	
}



/********************报警程序部分*******************/
void warn()  //报警函数
{
    
    
	
  if(TH>=WenDu)  //检测的温度高于设定温度报警值
		                             
     {
    
     
      bee=0; //报警
			
     }      
		 
	if(RH>=ShiDu)  //检测的湿度高于设定的湿度值
		                             
     {
    
     
      bee=0; //报警
     }      

		 
	if( TH<WenDu  &&  RH<ShiDu )	 
    {
    
    
		  bee=1; //停止报警
		}
		 
  
}

/************************LCD模块******************************************/

BOOL lcd_bz()//测试LCD忙碌状态
{
    
          
	 BOOL result ;
	 rs = 0 ;
	 rw = 1 ;
	 ep = 1 ;
	 result = (BOOL)(P0 & 0x80) ;
	 ep = 0 ;
	 return result ; 
}

void write_cmd(uchar cmd)// 写指令
{
    
           
 	while(lcd_bz()) ;
	rs = 0 ;
	rw = 0 ;
	ep = 0 ;
	P0 = cmd ;
	ep = 1 ;
	ep = 0 ;  
}

void write_addr(uchar addr)//写地址
{
    
           
 	write_cmd(addr|0x80) ;
}

void write_byte(uchar dat)//写字节
{
    
          
 	while(lcd_bz()) ;
  	rs = 1 ;
  	rw = 0 ;
  	ep = 0 ;
  	P0 = dat ;
  	ep = 1 ;
  	ep = 0 ; 
}

void lcd_init()// 初始化
{
    
           
	 write_cmd(0x38) ; 
	 delay(1);
	 write_cmd(0x08) ;  
	 delay(1);
	 write_cmd(0x01) ; 
	 delay(1);
	 write_cmd(0x06) ;
	 delay(1);
	 write_cmd(0x0c) ; 
	 delay(1);
}

void display(uchar addr, uchar q)//在某一地址上显示一字节
{
    
     	 
	 delay(1) ;
	 write_addr(addr) ;
   write_byte(q) ;
	 delay(1) ;
	 
}

/*********************** DHT11测试模块***************************************/

void start()//开始信号
{
    
    
	io=1;
	delay1();
	io=0;
	delay(20);//>18ms
	io=1;
	delay1();//20-40us
	delay1();
	delay1();
	delay1();
	delay1();
}
uchar receive_byte()//接收一个字节
{
    
    
	uchar i,temp,count;
	for(i=0;i<8;i++)
	{
    
    
        temp=0;
		delay1();delay1();delay1();delay1();
		if(io==1)temp=1;
		count=2;
		while((io)&&count++);
		if(count==1)break;
		data_byte<<=1;	
		data_byte|=temp;
	}
	return data_byte;
}
void receive()//接收数据
{
    
    
	uchar T_H,T_L,R_H,R_L,check,num_check;
	uchar count;
	start();//开始信号
	io=1;
	if(!io)//读取DHT11响应信号
	{
    
    
	
	while((io)&&count++);
	R_H=receive_byte();
	R_L=receive_byte();
	T_H=receive_byte();
	T_L=receive_byte();
	check=receive_byte();
	io=0;//拉低延时50us
	delay1();delay1();delay1();delay1();delay1();
	io=1;
	num_check=R_H+R_L+T_H+T_L;
	if(num_check=check)
	{
    
    
		RH=R_H;
		RL=R_L;
		TH=T_H;
		TL=T_L;
		check=num_check;
	}
	}
}


void showw()   // 问候语函数
{
    
          
	   lcd_init(); //初始化
	    delay(10);
	
     display(0x05,'W');
     display(0x06,'e');
		 display(0x07,'l');
		 display(0x08,'c');
		 display(0x09,'o');
		 display(0x0a,'m');
     display(0x0b,'e');
	   delay(250); //短暂延时
	   delay(250);
	   delay(250);
	   

/*********************************/
/*
	   display(0x40,' ') ;
		 display(0x41,'h');
		 display(0x42,'e');
		
 */
}


/*************定时器0初始化程序***************/
void time_init()	  
{
    
    
	EA   = 1;	 	  //开总中断
	TMOD = 0X01;	  //定时器0、定时器1工作方式1
	ET0  = 1;		  //开定时器0中断 
	TR0  = 1;		  //允许定时器0定时
}



void key() //按键程序 选择菜单模式
{
    
    
     
	  if(!K1)
		   {
    
      
			  delay(20);
			    if(!K1)
		         {
    
       
							 while(!K1)
				           ;
							  yemian++;
							  flat++;
								if(yemian>=3) {
    
     yemian=0; } 
								
             }
		   }
 
	
	
}


shezhi()  //对里面的数值进行修改
{
    
    
    if(!K2)
		   {
    
      
			  delay(50);
			    if(!K2)
		         {
    
       
							 ;
							 
							 if(yemian==1)
							 {
    
    
							  WenDu+=1;
								if(WenDu>99) {
    
     WenDu=99; }  //湿度上限加
							 }
							 
							 if(yemian==2)
							 {
    
    
							  ShiDu+=1;
								if(ShiDu>99) {
    
     ShiDu=99; }  //湿度下限加
							 }
							 
								write_eeprom();       //保存数据		
             }
		   }
			 
			  if(!K3)
		   {
    
      
			    delay(50);
			     if(!K3)
		         {
    
       
							
				           ;
							   if(yemian==1)
							     {
    
    
							      WenDu-=1;          //湿度下限减
								    if(WenDu<1) {
    
    WenDu=1; } 
							     }
							 
							   if(yemian==2)
							     {
    
    
							      ShiDu-=1;         //湿度下限减
								    if(ShiDu<1) {
    
     ShiDu=1; } 
							     }
								write_eeprom();       //保存数据		
             }
		   }

}



/***************************主程序*********************************/
void main()
{
    
    
	 init_eeprom();      			//读eeprom数据
   time_init();				//初始化定时器 
   showw();    //显示问候语 和名字
  
	while(1)
	{
    
       
		
		   key();
		//====================yemian==0时 进入工作状态=================================
		 	if(yemian==0)  
			{
    
     
				if(flat==1)
				 {
    
    
           flat=0;
					 lcd_init(); //初始化
					 	 
					 display(0x00,'T') ;    //Temp
		       display(0x01,'e');
		       display(0x02,'m');
					 display(0x03,'p');
           display(0x04,':');
					 
					 display(0x08,0xdf); // 度
		       display(0x09,'C');
					 
					 
					 display(0x40,'H') ;    //Humi
		       display(0x41,'u');
		       display(0x42,'m');
					 display(0x43,'i');
           display(0x44,':');
					 
					 display(0x47,'%');
					 display(0x48,'R');
					 display(0x49,'H');
					 
					 display(0x0c,'T');
           display(0x0d,':');
           display(0x0e,WenDu/10+0x30);  //报警温度
		       display(0x0f,WenDu%10+0x30);
				   
					 display(0x4c,'H');
           display(0x4d,':');
				   display(0x4e,ShiDu/10+0x30);  //报警湿度
		       display(0x4f,ShiDu%10+0x30);
          
          }
			
			 if(flag_300ms == 1)
	    	 {
    
    		
			     flag_300ms = 0;
           receive();
					 
					 display(0x05,TH/10+0x30);  //温度显示
		       display(0x06,TH%10+0x30);
					 
           display(0x45,RH/10+0x30);  //湿度显示
		       display(0x46,RH%10+0x30);
					 
					
           warn();
		     }
			
	}		
			
	//====================yemian==1 温度设置===========================
				if(yemian==1)  //温度
		    	{
    
    
		         if(flat==1)
				     {
    
    
               flat=0;  
							  bee=1;
               lcd_init(); //初始化
							 display(0x06,'T');
							 display(0x07,'e');
							 display(0x08,'m');
							 display(0x09,'p');
             }
						 
						shezhi();
						display(0x47,WenDu/10+0x30);  //温度
		        display(0x48,WenDu%10+0x30);
		      }
			
		//====================yemian==1湿度设置==========================	
				if(yemian==2)   //湿度设置
			    {
    
    
		         if(flat==1)
				     {
    
    
               flat=0;  
							  bee=1;
               lcd_init(); //初始化
							 display(0x06,'H');
							 display(0x07,'u');
							 display(0x08,'m');
							 display(0x09,'i');
						 } 
						 shezhi();
						 display(0x47,ShiDu/10+0x30);  //湿度
		         display(0x48,ShiDu%10+0x30);
		      }
	}
}



/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{
    
    	
	static uchar value;
	TH0 = 0x3c;
	TL0 = 0xb0;     // 50ms
	 
	if(value % 6 == 0)
	{
    
    
		flag_300ms = 1;	   //300ms
		value = 0;
	}
}

头文件

#ifndef _EEPROM52_H_
#define _EEPROM52_H_
uchar a_a;

/********STC89C51扇区分布*******
第一扇区:1000H--11FF
第二扇区:1200H--13FF
第三扇区:1400H--15FF
第四扇区:1600H--17FF
第五扇区:1800H--19FF
第六扇区:1A00H--1BFF
第七扇区:1C00H--1DFF
第八扇区:1E00H--1FFF
*****************/

/********STC89C52扇区分布*******
第一扇区:2000H--21FF
第二扇区:2200H--23FF
第三扇区:2400H--25FF
第四扇区:2600H--27FF
第五扇区:2800H--29FF
第六扇区:2A00H--2BFF
第七扇区:2C00H--2DFF
第八扇区:2E00H--2FFF
*****************/


#define RdCommand 0x01 //定义ISP的操作命令
#define PrgCommand 0x02
#define EraseCommand 0x03 
#define Error 1
#define Ok 0
#define WaitTime 0x01 //定义CPU的等待时间
sfr ISP_DATA=0xe2;  //寄存器申明
sfr ISP_ADDRH=0xe3;
sfr ISP_ADDRL=0xe4;
sfr ISP_CMD=0xe5;
sfr ISP_TRIG=0xe6;
sfr ISP_CONTR=0xe7;

/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable(void)
{
    
    
	 EA = 0;       /* 关中断   */
	 ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
	 ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
	 
}
/* =============== 关闭 ISP,IAP 功能 ================== */
void ISP_IAP_disable(void)
{
    
    
	 ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
	 ISP_TRIG = 0x00;
	 EA   =   1;   /* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
void ISPgoon(void)
{
    
    
	 ISP_IAP_enable();   /* 打开 ISP,IAP 功能 */
	 ISP_TRIG = 0x46;  /* 触发ISP_IAP命令字节1 */
	 ISP_TRIG = 0xb9;  /* 触发ISP_IAP命令字节2 */
	 _nop_();
}
/* ==================== 字节读 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
    
    
	EA = 0;
	 ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */
	 ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
	 ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
	 ISP_CMD   = ISP_CMD | RdCommand; /* 写入读命令 */
	 ISPgoon();       /* 触发执行  */
	 ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
	 EA  = 1;
	 return (ISP_DATA);    /* 返回读到的数据 */
}
/* ================== 扇区擦除 ======================== */
void SectorErase(unsigned int sector_addr)
{
    
    
	 unsigned int iSectorAddr;
	 iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
	 ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
	 ISP_ADDRL = 0x00;
	 ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
	 ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
	 ISPgoon();       /* 触发执行  */
	 ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
}
/* ==================== 字节写 ======================== */
void byte_write(unsigned int byte_addr, unsigned char original_data)
{
    
    
	 EA  = 0;
//	 SectorErase(byte_addr);
	 ISP_ADDRH = (unsigned char)(byte_addr >> 8);  /* 取地址  */
	 ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
	 ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
	 ISP_CMD  = ISP_CMD | PrgCommand;  /* 写命令2 */
	 ISP_DATA = original_data;   /* 写入数据准备 */
	 ISPgoon();       /* 触发执行  */
	 ISP_IAP_disable();     /* 关闭IAP功能 */
	 EA =1;
}

#endif

原理图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_46742690/article/details/108914256