基于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、设计报告、流程图、实物图、元件清单等。具体内容如下,全网最全! !

点赞分享一起学习成长。