基于51单片机的智能教室灯光控制系统仿真

仿真图:

在这里插入图片描述

芯片/模块的特点:

DS1302特点:
高精度时间计数:DS1302能够提供高精度的实时时钟计数,可以记录年、月、日、星期、小时、分钟和秒等时间信息。它内部集成了晶体振荡器,提供稳定的时钟信号。

低功耗设计:DS1302采用低功耗设计,可以在低功耗模式下运行,有效延长电池寿命。即使在停电情况下,它也能保持时间数据,并通过外部连接电池继续提供计时功能。

串行接口:DS1302通过串行实时时钟接口(SPI)进行通信和控制。使用少数几个引脚,可以与主控器件进行数据交换和时钟同步。

容易集成:DS1302集成了时钟计数和RAM存储器功能,并具有简单的接口和命令,容易与各种微控制器和单片机集成。它不需要复杂的控制信号,可以通过简单的读写命令进行操作。

可编程控制功能:DS1302具有可编程的控制功能,可以设置闹钟、写保护等特殊功能。它还支持多种时间格式的选择,例如24小时制或12小时制。

温度补偿:DS1302内置温度补偿功能,可以校正温度对时钟频率的影响,提高时钟计数的准确性。

高稳定性和抗震动能力:DS1302具有高稳定性和抗震动能力,适用于各种工业和消费类应用场景。

DS18B20特点:

  1. 单总线接口:DS18B20使用单总线接口进行通信,只需要一个引脚就可以连接多个传感器,简化了电路设计和连接。
  2. 数字输出:DS18B20以数字形式输出温度值,不需要额外的模数转换器。它使用12位的分辨率来表示温度值,可以实现高精度的温度测量。
  3. 高精度:DS18B20可以提供从-55°C到+125°C的温度测量范围,并具有±0.5°C的温度精度。因此,在许多应用中,它可以提供可靠和准确的温度测量结果。
  4. 多功能性:除了测量温度,DS18B20还可以执行其他功能,如温度报警功能。它可以设置上下限温度阈值,并在温度超过或低于这些阈值时触发报警。
  5. 低功耗:DS18B20采用低功耗设计,工作电流极低,只需要很少的能量来进行温度测量和通信。
  6. 耐用性:DS18B20具有良好的耐用性和可靠性,其封装材料和结构设计使其适用于各种环境条件下的应用。

主程序:

#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

uchar time_data[7];
uchar code write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};       //数据的地址
uchar code read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};

uchar code table1[]="C: 00|2000/00/00";
uchar code table2[]="T: 00|00:00:00 0";
uchar code table3[]="                ";			 //清屏内容
uchar code table4[]="  Set Real Time ";
uchar code table5[]="  Set Open Time ";
uchar code table6[]="   Start Time:  ";
uchar code table7[]="    00:00:00    ";
uchar code table8[]="    End Time:   ";
uchar code table9[]="Date: 2000/00/00";
uchar code table0[]="Time: 00:00:00 0";

bit Adjust;			  //调节标志位,=1表示进入调节模式,=0是正常模式
bit Auto_flg;		  //自动模式标志位,=1表示手动模式,=0是自动模式
sbit rs=P2^7;		  //LCD1602
// sbit rw=P1^1; 		  //LCD1602
sbit e=P2^6;		  //LCD1602
sbit sck=P2^0;		  //时钟端口
sbit io=P2^1;		  //时钟端口
sbit rst=P2^2;		  //时钟端口
sbit SELT =P1^6;	  //选择键
sbit ENTER=P1^7;	  //确认键
sbit UP   =P3^0;	  //加键
sbit DOWN =P3^1;	  //减键
sbit MODE =P3^2;	  //切换按键接口
sbit SWITCH=P3^3;	  //手动开关
sbit AUTO_LED=P2^4;	  //自动模式灯接口
sbit HAND_LED=P2^3;	  //手动灯接口
sbit LAMP1=P3^4;	  //灯接口
sbit LAMP2=P3^5;	  //灯接口
sbit LAMP3=P3^6;	  //灯接口
sbit LAMP4=P3^7;	  //灯接口
sbit LIGHT1=P1^0;	  //光线检测端口
sbit IN1=P1^1;
sbit OUT1=P1^2;
sbit DQ=P1^5;		  //温度数据口
uchar Select_num;	  //选择按键按下次数
uchar Enter_num;	  //确认按键按下次数
uchar Switch_num;	  //手动开关按键按下次数
float Year,Month,Day,Hour,Minute,Second;			//时间设置值
uchar Week;		
float Hour_H,Minute_H,Second_H;  					//设置开始时间
float Hour_L,Minute_L,Second_L;  					//设置结束时间
int Value1;											//人数
uchar IN1_flag=0;
uchar OUT1_flag=0;
uint Count;           //T0定时器中断计数次数
uchar Miao;

int temperature;									//全局变量 温度

void read_rtc();

/**************************************************LCD1602显示*******************************************************************/
void delay1(uint z)			  //延时函数
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=10;y>0;y--);
}

void write_com(uchar com)			 //写指令函数
{
	//rw=0;
	delay1(5);
	rs=0;
	delay1(5);
	e=1;
	delay1(5);
	P0=com;
	delay1(5);
	e=0;
	delay1(5);	
}

void write_date(uchar date)			//写数据函数
{									
	//rw=0;
	delay1(5);
	rs=1;
	delay1(5);
	e=1;
	delay1(5);
	P0=date;
	delay1(5);
	e=0;
	delay1(5);	
}

void init()						    //初始化函数
{	
	uchar num;
	Year=17;
	Month=1;
	Day=1;
	Hour=15;
	Minute=30;
	Second=50;
	Week=1;
	Hour_H=22;
	Minute_H=0;
	Second_H=0;
	Hour_L=18;
	Minute_L=0;
	Second_L=0;
	e=0;						    // 时序表e初始为0
	write_com(0x38);		        //设置16*2显示,5*7点阵,8位数据接口
	write_com(0x0c);				//设置光标
	write_com(0x06);				//光标自动加1,光标输入方式
	write_com(0x01);				//清屏
	write_com(0x80);				//设置初始显示位置
	for(num=0;num<16;num++)
	{
		write_date(table1[num]);
		delay1(5);
	}
	write_com(0x80+0x40);
	for(num=0;num<16;num++)
	{
		write_date(table2[num]);
		delay1(5);
	}					  
}

void SetTime_dispaly(uchar add,uchar dat)	 //第一个:参数的地址,第二个:参数的内容
{
	uchar shi,ge;
	shi=dat/10;							//把十位提取出来
	ge=dat%10;							//把个位提取出来
	write_com(add);			   	 		//要写的地址
	write_date(0x30+shi);				//十位的内容   1602字符库
	write_date(0x30+ge);				//个位的内容   1602字符库
}

void Week_dispaly(uchar add,uchar dat)	//第一个:参数的地址,第二个:参数的内容
{
	write_com(add);						//要写的地址
	if (dat == 0)
    {
        write_date(0x30+7);				//十位的内容   1602字符库
    }
    else
    {
        write_date(0x30+dat);				//十位的内容   1602字符库
    }
    
}
void Date_dispaly(uchar add,uchar dat)	 //第一个:参数的地址,第二个:参数的内容
{
	uchar shi,ge;
	shi=dat/16;							//把十位提取出来
	ge=dat%16;							//把个位提取出来
	write_com(add+3);			   	 	//要写的地址
	write_date(0x30+shi);				//十位的内容   1602字符库
	write_date(0x30+ge);				//个位的内容   1602字符库				   
}

void LCD_Clean(uchar i)					//液晶屏清除显示
{
	uchar num;
	if(i==1)
	{
		write_com(0x80);				//设置初始显示位置
		for(num=0;num<16;num++)			//显示第一行内容
		{
			write_date(table3[num]);
			delay1(1);
		}
	}
	if(i==2)
	{
		write_com(0x80+0x40);
		for(num=0;num<16;num++)			//显示第二行内容
		{
			write_date(table3[num]);
			delay1(1);
		}
	}
}

void LCD_Display_String(unsigned char line,unsigned char *string)
{ 										//液晶屏显示内容,把要显示的内容写到对应的位置
	unsigned char i;
	unsigned char address=0;
	if(line==1)
	{
		address=0x80;	 				//0X80是第1行的第1个位置  ,0x81第2位
	}
	else if(line==2)
	{
		address=0x80+0x40;  			//0X80+0x40是第2行的第1个位置  ,0X80+0x40+1是第2行第2位
	}
	
	for(i=0;i<16;i++)
	{
		write_com(address);
		write_date(string[i]);
		address++;
	} 
}
/**********************************DS1302时钟***************************************/
void Time_Display(void)
{
	read_rtc();
	Date_dispaly(0x80+0x40+9,time_data[6]);  //显示秒
	Date_dispaly(0x80+0x40+6,time_data[5]);	 //显示分
	Date_dispaly(0x80+0x40+3,time_data[4]);	 //显示时
	Date_dispaly(0x80+11,time_data[3]);		 //显示日
	Date_dispaly(0x80+8,time_data[2]);		 //显示月
	Week_dispaly(0x80+0x40+15,time_data[1]-1); //显示周
	Date_dispaly(0x80+5,time_data[0]);		 //显示年
					   //	Year/10*16+Year%10
	Hour=time_data[4]/16*10+time_data[4]%16;;
	Minute=time_data[5]/16*10+time_data[5]%16;;
	Second=time_data[6]/16*10+time_data[6]%16;;
}


void write_ds1302_byte(uchar dat)
{
	uchar i;
	for(i=0;i<8;i++)
	{
		sck=0;
		io=dat&0x01;					   //准备数据,从最低位开始
		dat=dat>>1;
		sck=1;
	}
}

void write_ds1302(uchar add,uchar dat)
{
	rst=0;
	_nop_();  						//CPU原地踏步
	sck=0;
	_nop_();
	rst=1;
	_nop_();
	write_ds1302_byte(add);		    //传地址
	write_ds1302_byte(dat);		    //传数据
	rst=0;     						//不受其他影响
	_nop_();
	io=1;						   //释放
	sck=1;
}

uchar read_ds1302(uchar add)
{
	uchar i,value;
	rst=0;
	_nop_();  //CPU原地踏步
	sck=0;
	_nop_();
	rst=1;
	_nop_();
	write_ds1302_byte(add);
	for(i=0;i<8;i++)
	{
		value=value>>1;
		sck=0;
		if(io)
		value=value|0x80;
		sck=1;
	}
	rst=0;
	_nop_();
	sck=0;
	_nop_();
	sck=1;
	io=1;
	return value;
}

void set_rtc()			          //设置时间
{
	uchar i,j;
	for(i=0;i<7;i++)			 //转换BCD码
	{
		j=time_data[i]/10;
		time_data[i]=time_data[i]%10;
		time_data[i]=time_data[i]+j*16;
	}
	write_ds1302(0x8e,0x00);	  //去除写保护
	for(i=0;i<7;i++)
	{
		write_ds1302(write_add[i],time_data[i]);
	}
	write_ds1302(0x8e,0x80);      //加写保护
}

void read_rtc()
{
	uchar i;
	for(i=0;i<7;i++)
	{
		time_data[i]=read_ds1302(read_add[i]);	//最终读出来的数 16进制
	}
    Year=time_data[0]/16*10+time_data[0]%16;
	Month=time_data[2]/16*10+time_data[2]%16;
	Day=time_data[3]/16*10+time_data[3]%16;
	Hour=time_data[4]/16*10+time_data[4]%16;
	Minute=time_data[5]/16*10+time_data[5]%16;
	Second=time_data[6]/16*10+time_data[6]%16;
	Week=time_data[1]/16*10+time_data[1]%16-1;
    if (Week == 0)
    {
        Week = 7;
    }
}

/*************************************************按键****************************************************************/
void Keyscan(void)
{
	if(SELT==0)
	{
		delay1(2);
		if(SELT==0)
		{
			while(!SELT);
			Select_num++;					//选择键按下一次
			Adjust=1;						//进入调节模式			
		}
		if(Select_num==1)
		{
			LCD_Clean(1);
			LCD_Clean(2);
			LCD_Display_String(1,table4);
			LCD_Display_String(2,table5);
			write_com(0x80+0);				//写 >>
			write_date(0x3e);
			write_com(0x80+1);				//写 >>
			write_date(0x3e);
			Enter_num=0;
		}
		if(Select_num==2)
		{
			LCD_Clean(1);
			LCD_Clean(2);
			LCD_Display_String(1,table4);
			LCD_Display_String(2,table5);
			write_com(0x80+0x40+0);				//写 >>
			write_date(0x3e);
			write_com(0x80+0x40+1);				//写 >>
			write_date(0x3e);
			Enter_num=0;
		}
		if(Select_num==3)
		{
			LCD_Clean(1);
			LCD_Clean(2);
			LCD_Display_String(1,table1);
			LCD_Display_String(2,table2);
			Select_num=0;
			Enter_num=0;					
			Adjust=0;
		}
		write_com(0x0c);									//光标不再闪烁
		Enter_num=0;
	}
	
	if(ENTER==0)
	{
		delay1(2);
		if(ENTER==0)
		{
			while(!ENTER);
			Enter_num++;
		}
		if(Select_num==1)					//设置实时时间
		{
			if(Enter_num==1)
			{
				LCD_Clean(1);
				LCD_Clean(2);
				LCD_Display_String(1,table9);
				LCD_Display_String(2,table0);
				SetTime_dispaly(0x80+8,Year);
				SetTime_dispaly(0x80+11,Month);
				SetTime_dispaly(0x80+14,Day);
				SetTime_dispaly(0x80+0x40+6,Hour);
				SetTime_dispaly(0x80+0x40+9,Minute);
				SetTime_dispaly(0x80+0x40+12,Second);
				Week_dispaly(0x80+0x40+15,Week);
				write_com(0x80+8);			//光标闪烁地址,停留在年的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==2)
			{
				write_com(0x80+11);			//光标闪烁地址,停留在月的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==3)
			{
				write_com(0x80+14);			//光标闪烁地址,停留在日的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==4)
			{
				write_com(0x80+0x40+6);		//光标闪烁地址,停留在时的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==5)
			{
				write_com(0x80+0x40+9);		//光标闪烁地址,停留在分的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==6)
			{
				write_com(0x80+0x40+12);	//光标闪烁地址,停留在秒的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==7)
			{
				write_com(0x80+0x40+15);	//光标闪烁地址,停留在星期的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==8)
			{
				Enter_num=0;
				write_com(0x0c);			//光标不再闪烁
				LCD_Clean(1);
				LCD_Clean(2);
				LCD_Display_String(1,table1);
				LCD_Display_String(2,table2);
				time_data[0]=Year;///10*16+Year%10;
				time_data[1]=Week+1;///10*16+Week%10;
				time_data[2]=Month;///10*16+Month%10;
				time_data[3]=Day;///10*16+Day%10;
				time_data[4]=Hour;///10*16+Hour%10;
				time_data[5]=Minute;///10*16+Minute%10;
				time_data[6]=Second;///10*16+Second%10;
				set_rtc();					 //设置时间
				Select_num=0;
				Adjust=0;
			}
		}

		if(Select_num==2)					//设置开关锁时间
		{
			if(Enter_num==1)
			{
				LCD_Clean(1);
				LCD_Clean(2);
				LCD_Display_String(1,table6);
				LCD_Display_String(2,table7);
				SetTime_dispaly(0x80+0x40+4,Hour_L);
				SetTime_dispaly(0x80+0x40+7,Minute_L);
				SetTime_dispaly(0x80+0x40+10,Second_L);
				write_com(0x80+0x40+4);		//光标闪烁地址,停留在时的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==2)
			{
				write_com(0x80+0x40+7);		//光标闪烁地址,停留在分的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==3)
			{
				write_com(0x80+0x40+10);	//光标闪烁地址,停留在秒的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==4)
			{
				write_com(0x0c);			//光标不再闪烁
				LCD_Clean(1);
				LCD_Clean(2);
				LCD_Display_String(1,table8);
				LCD_Display_String(2,table7);	
				SetTime_dispaly(0x80+0x40+4,Hour_H);
				SetTime_dispaly(0x80+0x40+7,Minute_H);
				SetTime_dispaly(0x80+0x40+10,Second_H);
				write_com(0x80+0x40+4);		//光标闪烁地址,停留在时的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==5)
			{
				write_com(0x80+0x40+7);		//光标闪烁地址,停留在分的位置上					
				write_com(0x0f);			//光标闪烁
			}
			if(Enter_num==6)
			{
				write_com(0x80+0x40+10);	//光标闪烁地址,停留在秒的位置上					
				write_com(0x0f);			//光标闪烁
			}		
			if(Enter_num==7)
			{
				Enter_num=0;
				write_com(0x0c);			//光标不再闪烁
				LCD_Clean(1);
				LCD_Clean(2);
				LCD_Display_String(1,table1);
				LCD_Display_String(2,table2);
				Select_num=0;
				Adjust=0;
			}
		}

	}
	if(UP==0)
	{
		delay1(2);
		if(UP==0)
		{
			while(!UP);
			if(Select_num==1)
			{
				if(Enter_num==1)
				{
					Year++;
					if(Year>99)
					Year=0;
					SetTime_dispaly(0x80+8,Year);
					write_com(0x80+8);								
					write_com(0x0f);			
				}
				if(Enter_num==2)
				{
					Month++;
					if(Month>12)
					Month=1;
					SetTime_dispaly(0x80+11,Month);
					write_com(0x80+11);								
					write_com(0x0f);							  
				}
				if(Enter_num==3)
				{
					Day++;
					if(Day>31)
					Day=1;
					SetTime_dispaly(0x80+14,Day);
					write_com(0x80+14);								
					write_com(0x0f);
				}
				if(Enter_num==4)
				{
					Hour++;
					if(Hour>23)
					Hour=0;
					SetTime_dispaly(0x80+0x40+6,Hour);
					write_com(0x80+0x40+6);								
					write_com(0x0f);
				}
				if(Enter_num==5)
				{
					Minute++;
					if(Minute>59)
					Minute=0;
					SetTime_dispaly(0x80+0x40+9,Minute);
					write_com(0x80+0x40+9);								
					write_com(0x0f);
				}
				if(Enter_num==6)
				{
					Second++;
					if(Second>59)
					Second=0;
					SetTime_dispaly(0x80+0x40+12,Second);
					write_com(0x80+0x40+12);								
					write_com(0x0f);
				}
				if(Enter_num==7)
				{
					Week++;
					if(Week>7)
					Week=1;
					Week_dispaly(0x80+0x40+15,Week);
					write_com(0x80+0x40+15);								
					write_com(0x0f);
				}
			}
			if(Select_num==2)
			{				
				if(Enter_num==1)
				{
					Hour_L++;
					if(Hour_L>23)
					Hour_L=0;
					SetTime_dispaly(0x80+0x40+4,Hour_L);
					write_com(0x80+0x40+4);								
					write_com(0x0f);
				}
				if(Enter_num==2)
				{
					Minute_L++;
					if(Minute_L>59)
					Minute_L=0;
					SetTime_dispaly(0x80+0x40+7,Minute_L);
					write_com(0x80+0x40+7);								
					write_com(0x0f);
				}
				 
				if(Enter_num==3)
				{
					Second_L++;
					if(Second_L>59)
					Second_L=0;
					SetTime_dispaly(0x80+0x40+10,Second_L);
					write_com(0x80+0x40+10);								
					write_com(0x0f);
				}
				if(Enter_num==4)
				{
					Hour_H++;
					if(Hour_H>23)
					Hour_H=0;
					SetTime_dispaly(0x80+0x40+4,Hour_H);
					write_com(0x80+0x40+4);								
					write_com(0x0f);
				}
				if(Enter_num==5)
				{
					Minute_H++;
					if(Minute_H>59)
					Minute_H=0;
					SetTime_dispaly(0x80+0x40+7,Minute_H);
					write_com(0x80+0x40+7);								
					write_com(0x0f);
				}
				 
				if(Enter_num==6)
				{
					Second_H++;
					if(Second_H>59)
					Second_H=0;
					SetTime_dispaly(0x80+0x40+10,Second_H);
					write_com(0x80+0x40+10);								
					write_com(0x0f);
				}				
			}
		}
	}
	if(DOWN==0)
	{
		delay1(2);
		if(DOWN==0)
		{
			while(!DOWN);
			if(Select_num==1)
			{
				if(Enter_num==1)
				{
					Year--;
					if(Year<0)
					Year=99;
					SetTime_dispaly(0x80+8,Year);
					write_com(0x80+8);								
					write_com(0x0f);
				}
				if(Enter_num==2)
				{
					Month--;
					if(Month<1)
					Month=12;
					SetTime_dispaly(0x80+11,Month);
					write_com(0x80+11);								
					write_com(0x0f);
				}
				if(Enter_num==3)
				{
					Day--;
					if(Day<1)
					Day=31;
					SetTime_dispaly(0x80+14,Day);
					write_com(0x80+14);								
					write_com(0x0f);
				}
				if(Enter_num==4)
				{
					Hour--;
					if(Hour<0)
					Hour=23;
					SetTime_dispaly(0x80+0x40+6,Hour);
					write_com(0x80+0x40+6);								
					write_com(0x0f);
				}
				if(Enter_num==5)
				{
					Minute--;
					if(Minute<0)
					Minute=59;
					SetTime_dispaly(0x80+0x40+9,Minute);
					write_com(0x80+0x40+9);								
					write_com(0x0f);
				}
				if(Enter_num==6)
				{
					Second--;
					if(Second<0)
					Second=59;
					SetTime_dispaly(0x80+0x40+12,Second);
					write_com(0x80+0x40+12);								
					write_com(0x0f);
				}
				if(Enter_num==7)
				{
					Week--;
					if(Week<1)
					Week=7;
					Week_dispaly(0x80+0x40+15,Week);
					write_com(0x80+0x40+15);								
					write_com(0x0f);
				}		
			}

			if(Select_num==2)
			{
				if(Enter_num==1)
				{
					Hour_L--;
					if(Hour_L<0)
					Hour_L=23;
					SetTime_dispaly(0x80+0x40+4,Hour_L);
					write_com(0x80+0x40+4);								
					write_com(0x0f);
				}
				if(Enter_num==2)
				{
					Minute_L--;
					if(Minute_L<0)
					Minute_L=59;
					SetTime_dispaly(0x80+0x40+7,Minute_L);
					write_com(0x80+0x40+7);								
					write_com(0x0f);
				}
				if(Enter_num==3)
				{
					Second_L--;
					if(Second_L<0)
					Second_L=59;
					SetTime_dispaly(0x80+0x40+10,Second_L);
					write_com(0x80+0x40+10);								
					write_com(0x0f);
				}
				 
				if(Enter_num==4)
				{
					Hour_H--;
					if(Hour_H<0)
					Hour_H=23;
					SetTime_dispaly(0x80+0x40+4,Hour_H);
					write_com(0x80+0x40+4);								
					write_com(0x0f);
				}
				if(Enter_num==5)
				{
					Minute_H--;
					if(Minute_H<0)
					Minute_H=59;
					SetTime_dispaly(0x80+0x40+7,Minute_H);
					write_com(0x80+0x40+7);								
					write_com(0x0f);
				}
				if(Enter_num==6)
				{
					Second_H--;
					if(Second_H<0)
					Second_H=59;
					SetTime_dispaly(0x80+0x40+10,Second_H);
					write_com(0x80+0x40+10);								
					write_com(0x0f);
				}
			}
		}
	}

	if(MODE==0)							//切换按键按下
	{
		delay1(2);							//消抖
		if(MODE==0)
		{
			while(!MODE);					//按键释放
			Auto_flg=~Auto_flg;				//模式切换
			if(Auto_flg==0)					//自动模式
			{
				AUTO_LED=0;					//自动灯亮
				HAND_LED=1;
			}
			if(Auto_flg==1)					//手动模式
			{
				AUTO_LED=1;					
				HAND_LED=0;					//手动灯亮
				LAMP1=1;					//关灯
				LAMP2=1;
				LAMP3=1;
				LAMP4=1;
			}
		}
	}
	if(Auto_flg==1)							//手动模式
	{
		if(SWITCH==0)						//灯开关按键按下
		{
			delay1(2);						//消抖
			if(SWITCH==0)
			{
				while(!SWITCH);				//按键释放
				Switch_num++;				//按下次数增加
				if(Switch_num==1)			//按下一次,开一盏灯
				{
					LAMP1=0;
					LAMP2=1;
					LAMP3=1;
					LAMP4=1;
				}
				if(Switch_num==2)			//按下二次,开二盏灯
				{
					LAMP1=0;
					LAMP2=0;
					LAMP3=1;
					LAMP4=1;
				}
				if(Switch_num==3)			//按下3次,开3盏灯
				{
					LAMP1=0;
					LAMP2=0;
					LAMP3=0;
					LAMP4=1;
				}
				if(Switch_num==4)			//按下4次,开4盏灯
				{
					LAMP1=0;
					LAMP2=0;
					LAMP3=0;
					LAMP4=0;
				}
				if(Switch_num==5)			//按下5次,开0盏灯
				{
					LAMP1=1;
					LAMP2=1;
					LAMP3=1;
					LAMP4=1;
					Switch_num=0;			//次数清除
				}
			}
		}
	}
}

void Open(void)
{
	float Now;
	float Set_L,Set_H;
	Now=Hour+Minute/60+Second/3600;				  		//把实时时间化成小时为单位
	Set_L=Hour_L+Minute_L/60+Second_L/3600;		  		//把设置下限时间化成小时为单位
	Set_H=Hour_H+Minute_H/60+Second_H/3600;		  		//把设置上限时间化成小时为单位
	if(Auto_flg==0)										//自动模式
	{
		if((Now>=Set_L)&(Now<=Set_H))				  	//实时时间在上下限时间范围内
		{
			if(LIGHT1==0)							    //光线不足
			{
				if(Value1==0)
				{
					LAMP1=1;							//全灭
					LAMP2=1;
					LAMP3=1;
					LAMP4=1;
				}
				if((Value1>0)&(Value1<10))
				{
					LAMP1=0;							//亮一个灯
					LAMP2=1;
					LAMP3=1;
					LAMP4=1;
				}
				if((Value1>=10)&(Value1<20))
				{
					LAMP1=0;							//亮二个灯
					LAMP2=0;
					LAMP3=1;
					LAMP4=1;
				}
				if((Value1>=20)&(Value1<30))
				{
					LAMP1=0;							//亮三个灯
					LAMP2=0;
					LAMP3=0;
					LAMP4=1;
				}
				if(Value1>=30)
				{
					LAMP1=0;							//亮四个灯
					LAMP2=0;
					LAMP3=0;
					LAMP4=0;
				}
			}
			if(LIGHT1==1)							    //光线强烈
			{
				LAMP1=1;								//全灭
				LAMP2=1;
				LAMP3=1;
				LAMP4=1;
			}
		}
	
		if((Now<Set_L)|(Now>Set_H))					  	//实时时间不在范围内
		{
			LAMP1=1;									//全灭
			LAMP2=1;
			LAMP3=1;
			LAMP4=1;
		}
	}
} 

/*******************************************************************************************************/
void Count_Value(void)
{
	SetTime_dispaly(0x80+3,Value1);
	if(IN1==0)
	{
		delay1(1);
		if(IN1==0)
		{
			while(!IN1);
			if(OUT1_flag==0)
			{
				IN1_flag=1;
				TR0=1;					 //开启定时器 防止误触发
			}
			if(OUT1_flag==1)
			{
				
				Value1++;				 //人数增加
				if(Value1>=99)			 //如果人数计数到99,变为最大99
				Value1=99;
				OUT1_flag=0;			 //清零
				IN1_flag=0;
				TR0=0;					 //关闭定时器
				Count=0;
				Miao=0;
			}
		}
	}
	if(OUT1==0)
	{
		delay1(1);
		if(OUT1==0)
		{
			while(!OUT1);
			if(IN1_flag==0)
			{
				OUT1_flag=1;
				TR0=1;					 //开启定时器 防止误触发
			}
			if(IN1_flag==1)
			{
				Value1--;				//人数减少
				if(Value1<0)			//如果人数计数小于0,变为最小0
				Value1=0;
				IN1_flag=0;				//清零
				OUT1_flag=0;
				TR0=0;					 //关闭定时器
				Count=0;
				Miao=0;
			}
		}
	}
}
/****************************************温度************************************************************/
void delay(uint y)		   							//DS18B20延时函数(仿真用)
{
	while(y--);
} 

/*void delay(uint z)			  							//DS18B20延时函数(实物用)
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=1;y>0;y--);
}  
*/
void write_byte(uint dat)			//写一个字节
{
	uchar i;
	for(i=0;i<8;i++)		        //循环八次	  共有八位
	{
		DQ=0;						//写零
		DQ=dat&0x01;                //向总线写位数据,从最低位写起
		delay(4);
		DQ=1;						//写一
		dat>>=1;				    //下次写作准备,移位数据
	}
	delay(4);
}				     

uchar read_byte(void)				//读一个字节,返回值
{
	uchar i;
	uint value;
	for(i=0;i<8;i++)		        //循环八次	  共有八位
	{
		DQ=0;
		value>>=1;
		DQ=1;						//释放总线
		if(DQ)
		value|=0x80;			    //DQ=1,value取1
		delay(4);
	}
	return value;
}

void ds18b20_init()				    //初始化函数
{
	uint n;
	DQ=1;
	delay(8);					   
	DQ=0;
	delay(80);					    //低电平480——960us
	DQ=1;							//总线释放
	delay(8);					    //等待50——100us
	n=DQ;						    //读取复位状态
	delay(4);
}

int readtemperature()				//读整数部分
{	
    int a,b;						//高八位,低八位
	ds18b20_init();
	write_byte(0xcc);			    //跳过rom匹配,跳过读序列号的操作,可节省操作时间
	write_byte(0x44);			    //启动温度检测
	delay(300);					    //测温度
	ds18b20_init();				    //开始操作前需要复位
	write_byte(0xcc);				//跳过rom匹配
	write_byte(0xbe);			    //写读寄存器中温度值的命令
	a=read_byte();				    //low	  低位开始读取
	b=read_byte();				    //high	  高位开始读取
	b<<=8;							//把高位左移八位
	b=b|a;							//高八位与第八位进行或运算,得到总和
	if(b>=0)						//如果温度大于等于0
	{
		b=b*0.0625;					//直接乘以0.0625
		write_com(0x80+0x40+2);		//在LCD1602对应的位置不写内容
		write_date(0x20);
	}
    else							//温度小于0
	{	
		b=~b+1;						//取反码再加一
		b=b*0.0625;					//再运算
		write_com(0x80+0x40+2);		//在LCD1602对应的位置写一个负号
		write_date(0x2d);
	}
	return b;						//返回b,此时以表示温度
}
void temperature_dispaly(char add,char dat)	 		//温度显示函数:第一个:参数的地址,第二个:参数的内容
{
	uchar shi,ge;
	shi=dat/10;								 		//把温度的十位提取出来
	ge=dat%10;								 		//把温度的个位提取出来
	write_com(0x80+0x40+add);			   	 		//要写的地址
	write_date(0x30+shi);				   	 		//十位的内容   1602字符库
	write_date(0x30+ge);				     		//个位的内容	1602字符库
}
/*****************************************定时器初始化和主函数***********************************************************/
void T0_init(void)
{
	TMOD=0x11;				   	   //设置定时器0为工作方式1
	TH0=(65536-50000)/256;   	   //50MS定时
	TL0=(65536-50000)%256;
	EA=1;					   	   //开定时器T0的中断	总中断
	ET0=1;						   //允许T0中断
//	TR0=1;						   //开启定时器
}
void main()
{
	AUTO_LED=0;					 //默认自动模式
	temperature=readtemperature();
	init();						 //液晶初始化
	T0_init();					 //定时器初始化
    write_ds1302(0x80,0x00);
	delay1(8000);
	while(1)
	{
		if(Adjust==0)			 //非调节模式下显示时间人数和温度
		{	
			temperature=readtemperature();			//读取温度
			temperature_dispaly(3,temperature);		//显示温度
			Time_Display();		 //显示时间
			Open();		 		 //动作判断,根据光线和人数
			Count_Value();		 //计算人数
		}
		Keyscan();				 //扫描键盘
	}
}

设计文件:

链接:https://pan.baidu.com/s/1uIeXhiWFOx9MwoMyRY5k8A?pwd=b6gv

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值