基于51单片机教室红外计数灯光控制—可蓝牙控制

基于51单片机智能教室灯光

(仿真+程序+原理图+PCB+设计报告)

功能介绍

具体功能:

本系统由STC89C52单片机+时钟芯片DS1302+液晶屏LCD1602+光敏电阻+红外对管+LED灯模块+按键模块+蓝牙模块构成

具体功能:

1.四个LED模拟教室灯光;

2.使用两个红外对管检测人进出教室,并统计;

3.LCD1602实时显示日期时间和统计的人数及光照强度;

4.按键设定定时时间段,在这时间段内开启自动照明功能;

5.光敏电阻检测光线,光线暗则打开自动照明;

6.人数<10:亮1个;10≤人数<20:亮2个;20≤人数<30:亮3个;30≤人数:全亮;

7.可以切换手动模式,手动开灯、手动调节亮度;

8.可以无线蓝牙按键控制

添加图片注释,不超过 140 字(可选)

程序

cs 复制代码
#include<reg52.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[]="L: - |2000/00/00";
uchar code table2[]="R:   |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";
uchar value[]="C:000 L: \r\n";

bit Adjust;			  //调节标志位,=1表示进入调节模式,=0是正常模式
bit Auto_flg;		  //自动模式标志位,=1表示手动模式,=0是自动模式
bit Timer;
bit SELT_flg;
bit ENTER_flg;
bit UP_flg;
bit DOWN_flg;	  								
/***微信公众号:木子单片机********/
sbit rs=P1^0;		  //LCD1602
sbit rw=P1^1; 		  //LCD1602
sbit e=P1^2;		  //LCD1602
sbit sck=P2^5;		  //时钟端口
sbit io=P2^6;		  //时钟端口
sbit rst=P2^7;		  //时钟端口
sbit SELT =P1^6;	  //设置键
sbit ENTER=P1^7;	  //确认键
sbit UP   =P2^4;	  //加键
sbit DOWN =P2^3;	  //减键
sbit AUTO_LED=P1^3;	  //自动模式灯接口
sbit HAND_LED=P1^5;	  //手动灯接口
sbit LAMP1=P3^4;	  //灯接口
sbit LAMP2=P3^5;	  //灯接口
sbit LAMP3=P3^6;	  //灯接口
sbit LAMP4=P3^7;	  //灯接口
sbit CS   =P2^0;								//ADC0832
sbit Clk  =P2^2;						    	//ADC0832
sbit DATI =P2^1;								//ADC0832
sbit DATO =P2^1;								//ADC0832

uchar Select_num;	  //设置按键按下次数
uchar Enter_num;	  //确认按键按下次数
uchar Switch_num;	  //手动开关按键按下次数
char Year,Month,Day;
float Hour,Minute,Second;			//时间设置值
char 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;
uint Count1;           //T1定时器中断计数次数
uchar dat=0x00;           						//AD值
uchar CH;       								//通道变量
char num;			   							//PWM中断次数
char pwm;			   							//脉宽参数 0-10 开机默认中间值
char Light;										//光线强度

uchar xdata UART0_Data[32];
uchar UART0_Len=1;

void read_rtc();

/***********************************************液晶屏LCD1602**********************************************************************/
void delay1(uint z)			  		//延时0.1ms函数
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=3;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;	
	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);						//要写的地址
	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 Write_Data(uchar add,uint date)  //把数据写到对应的位置 为3位数
{
	uchar bai,shi,ge;
	bai=date/100;
	shi=date%100/10;
	ge=date%10;
	write_com(0x80+add);
	write_date(0x30+bai);
	write_date(0x30+shi);				   
	write_date(0x30+ge);				    
}
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++;
	} 
}

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);  //显示周  0表示星期天,1表示星期一......6表示星期六 芯片读出的数据表示1为一周的第一天星期天,故做减一处理
	Date_dispaly(0x80+5,time_data[0]);		 //显示年
					   //	Year/10*16+Year%10
	Year=time_data[0]/16*10+time_data[0]%16;
	Week=time_data[1]/16*10+time_data[1]%16-1;
	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;
	
}

/*******************************************时钟芯片DS1302*****************************************************/
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进制
	}
}

/*************************************************按键****************************************************************/
void Keyscan(void)
{
	if((SELT==0)||(SELT_flg==1))
	{
		delay1(50);
		if(SELT==0)
		{
			while(!SELT);
		}
		SELT_flg=0;
		Select_num++;						//设置键按下一次
		Adjust=1;							//进入调节模式
		if(Select_num==1)
		{
			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_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_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)||(ENTER_flg==1))
	{
		delay1(50);
		if(ENTER==0)
		{
			while(!ENTER);
		}
		ENTER_flg=0;			
			
		Enter_num++;
		if(Select_num==0)					//模式切换
		{
			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;
				pwm=5;
			}
		}
		if(Select_num==1)					//设置实时时间
		{
			if(Enter_num==1)
			{
				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_Display_String(1,table1);
				LCD_Display_String(2,table2);
				Week++;                     //按键设置时,比如设置星期6,此时显示会被减一处理(void Time_Display(void)函数)显示5,此处加回去,保证设置多少就显示多少
				time_data[0]=Year;///10*16+Year%10;
				time_data[1]=Week;///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_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_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_Display_String(1,table1);
				LCD_Display_String(2,table2);
				Select_num=0;
				Adjust=0;
			}
		}

	}
	if((UP==0)||(UP_flg==1))
	{
		delay1(50);
		if(UP==0)
		{
			while(!UP);
		}
		UP_flg=0;
		if(Select_num==0)
		{
			if(Auto_flg==1)							//手动模式
			{
				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;			//次数清除
				}
			}
		}

		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>6)
				Week=0;
				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)||(DOWN_flg==1))
	{
		delay1(50);
		if(DOWN==0)
		{
			while(!DOWN);
		}
		DOWN_flg=0;
		if(Select_num==0)
		{
			if(Auto_flg==1)					//手动模式
			{
				pwm++;						//亮度变化
				if(pwm>9)
				pwm=0;
			}
		}

		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<0)
				Week=6;
				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);
			}
		}
	}	
}
****//完整资料
***//***微信公众号:木子单片机********/
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((Now>=Set_L)&(Now<=Set_H))				  		//实时时间在上下限时间范围内
	Timer=1;
	else
	Timer=0;		
} 
/*************************************ADC0832*****************************************/
uchar adc0832(uchar CH)					// AD转换子程序
{
	uchar i,test,adval;
	adval=0x00;
	test=0x00;
	Clk=0;       						//初始化
	DATI=1;
	_nop_();
	CS=0;
	_nop_();
	Clk=1;
	_nop_();
	if(CH==0x00)      					//通道选择
	{
		Clk=0;
		DATI=1;      //通道0的第一位
		_nop_();
		Clk=1;
		_nop_();
		Clk=0;
		DATI=0;      //通道0的第二位
		_nop_();
		Clk=1;
		_nop_();
	} 
	else
	{
		Clk=0;
		DATI=1;      //通道1的第一位
		_nop_();
		Clk=1;
		_nop_();
		Clk=0;
		DATI=1;      //通道1的第二位
		_nop_();
		Clk=1;
		_nop_();
	}
	Clk=0;
	DATI=1;
	for(i=0;i<8;i++)      //读取前8位的值
	{
		_nop_();
		adval<<=1;
		Clk=1;
		_nop_();
		Clk=0;
		if(DATO)
		adval|=0x01;
		else
		adval|=0x00;
	}
	for(i=0;i<8;i++)      //读取后8位的值
	{
		test>>=1;
		if(DATO)
		test|=0x80;
		else 
		test|=0x00;
		_nop_();
		Clk=1;
		_nop_();
		Clk=0;
	}
	if(adval == test)      //比较前8位与后8位的值,如果不相同舍去。若一直出现显示为零,请将该行去掉
	dat=test;
	
	_nop_();
	CS=1;        			//释放ADC0832
	DATO=1;
	Clk=1;
	return dat;
}
void Light_Check(void)
{
	dat=adc0832(CH);						//采集光线电压
	if((dat>=0)&(dat<20))					//根据采到的电压值给定光线强度,电压越高,光线强度越低
	{Light=9;}				   
	if((dat>=20)&(dat<40))
	{Light=8;}
	if((dat>=40)&(dat<60))
	{Light=7;}
	if((dat>=60)&(dat<80))
	{Light=6;}
	if((dat>=80)&(dat<100))
	{Light=5;}
	if((dat>=100)&(dat<120))
	{Light=4;}
	if((dat>=120)&(dat<140))
	{Light=3;}
	if((dat>=140)&(dat<160))
	{Light=2;}
	if((dat>=160)&(dat<180))
	{Light=1;}
	if((dat>=180)&(dat<=255))
	{Light=0;}

	if(Auto_flg==0)			   				//自动模式下
	{
		if((dat>=0)&(dat<20))					
		{pwm=0;}				   
		if((dat>=20)&(dat<40))
		{pwm=1;}
		if((dat>=40)&(dat<60))
		{pwm=2;}
		if((dat>=60)&(dat<80))
		{pwm=3;}
		if((dat>=80)&(dat<100))
		{pwm=4;}
		if((dat>=100)&(dat<120))
		{pwm=5;}
		if((dat>=120)&(dat<140))
		{pwm=6;}
		if((dat>=140)&(dat<160))
		{pwm=7;}
		if((dat>=160)&(dat<180))
		{pwm=8;}
		if((dat>=180)&(dat<=255))
		{pwm=9;}
	}
	Week_dispaly(0x80+2,Light);				//显示光线强度
	Week_dispaly(0x80+4,pwm);				//显示亮灯强度
}
/*****************************************人数统计**************************************************************/
void intinit(void)				 //外部中断0初始化
{	
	EA=1;					  	 //打开总中断
 	EX0=1;					  	 //中断允许位
	IT0=1;					  	 //外部中断0触发方式为下降沿触发
	EX1=1;					  	 //中断允许位
	IT1=1;					  	 //外部中断0触发方式为下降沿触发
}

void int1 () interrupt 2   		//外红外对管
{	
	if(IN1_flag==0)
	{
		OUT1_flag=1;
		TR0=1;					 //开启定时器开始计时,如果3秒内只触发一个则清零,防止误触发
	}
	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 int0 () interrupt 0   		//内红外对管
{	
	if(OUT1_flag==0)
	{
		IN1_flag=1;
		TR0=1;					 //开启定时器开始计时,如果3秒内只触发一个则清零,防止误触发
	}
	if(OUT1_flag==1)
	{
		
		Value1++;				 //人数增加
		if(Value1>=999)			 //如果人数计数到999,变为最大999
		Value1=999;
		OUT1_flag=0;			 //清零
		IN1_flag=0;
		TR0=0;					 //关闭定时器
		Count=0;
		Miao=0;
	}
}

硬件设计

使用元器件:

单片机:STC89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

排阻:8*10K;瓷片电容:104;

插件电容:2.2uF/50V;

插件电容:100uF/16V;

LED灯;纽扣电池座;

开关;电源接口;瓷片电容:30;

蓝牙模块:HC-05;液晶屏:LCD1602;

红外接收管;红外发射管;

光敏电阻:100k;蓝白可调电阻:10K;

插件电阻:4.7K;插件电阻:510;

插件电阻:10K;插件电阻:100k;

插件电阻:100;按键:SW-PB;

万用板:9*15cm; 时钟芯片:DS1302;

模数转换器:ADC0832;运放:LM393;

晶振:32768Hz;晶振:11.0592M;

12M晶振;导线:若干;

添加图片注释,不超过 140 字(可选)

流程图:

添加图片注释,不超过 140 字(可选)

设计资料

01仿真图

本设计使用proteus7.8和proteus8.9两个版本设计,向下兼容,无需担心!具体如图!

添加图片注释,不超过 140 字(可选)

02原理图

本系统原理图采用Altium Designer19设计,具体如图!

添加图片注释,不超过 140 字(可选)

03程序

本设计使用keil5版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

04设计报告

一万两千字设计报告,具体如下!

添加图片注释,不超过 140 字(可选)

05设计资料

全部资料包括程序(含注释)、仿真源文件 、AD原理图、任务书、PCB、设计报告、流程图、实物图、元件清单等。具体内容如下,全网最全! !

点赞分享一起学习成长。

相关推荐
某zhuan29 分钟前
STM32中PB4引脚作普通GPIO使用的一个小问题
stm32·单片机·嵌入式硬件
蓝天居士2 小时前
PY32F040单片机介绍(2)
单片机·国产mcu
点灯小铭4 小时前
基于单片机的人体红外传感的步进电机调速自动门智能控制系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
一月千帆4 小时前
STM32 串口 Bootloader 固件升级方案实现
stm32·单片机·嵌入式硬件
czy87874754 小时前
用C语言实现代理模式
c语言·代理模式
朱嘉鼎5 小时前
GPIO引脚操作方法概述
单片机·嵌入式硬件
Yupureki5 小时前
从零开始的C++学习生活 13:红黑树全面解析
c语言·数据结构·c++·学习·visual studio
小+不通文墨7 小时前
GPIO口输入
stm32·单片机·嵌入式硬件
AAA小肥杨7 小时前
cmake使用教程
c语言·c++·cmake
zzywxc7878 小时前
解锁 Rust 开发新可能:从系统内核到 Web 前端的全栈革命
开发语言·前端·python·单片机·嵌入式硬件·rust·scikit-learn