本设计是使用两个红外对管来检测是否有人进入办公室并进行人数统计,人数最多统计到二位数99人,并实时将人数显示到液晶屏LCD上,液晶屏同时显示实时日期/时间/星期; 使用4个LED灯模拟办公室的照明灯,在符合条件开启时,人数为0时灯不亮,人数小于10人亮一个灯,10-20人亮二个灯,20-30人亮三个灯,大于30人则全亮四个灯; 系统分自动/手动模式,可以通过按键切换模式,并有LED指示当前所在模式; 在自动模式下,可以设定定时时间段,在定时时间段内,当办公室有人(人数大于0)的情况下,如果光线暗弱则自动打开照明灯,照明灯点亮个数根据人数而定,不在定时时间段或者办公室无人的情况下,关闭所有照明灯; 另外在手动模式下,可以通过手动开关控制照明灯的亮灭,人数统计部分仍然生效;
制作出来的实物图如下:
电路原理图如下:
元件清单:
元器件 型号 数量
单片机最小系统 stc89c52 1
液晶显示 LCD1602 1
红外模块 2
时钟芯片 DS1302 1
光敏电阻模块 1
按钮 5
led 6
电阻 300欧姆 2
数据线 1
程序流程图:
单片机源程序如下:
/*******************说明:************************** 将实时时钟数据通过LCD1602显示 #include <reg52.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int uchar dis_time_buf[16]={0}; //LCD1602引脚定义 //采用8位并行方式,DB0~DB7连接至LCDDATA0~LCDDATA7 sbit RS=P2^2; sbit RW=P2^1; sbit CS=P2^0; #define LCDDATA P0 //时钟DS1302引脚定义 sbit RST=P2^4; sbit IO=P2^5; sbit SCK=P2^6;
sbit guangmin = P1^3;//光敏传感器
sbit led1 = P3^3; //6个指示灯 sbit led2 = P3^2; sbit led3 = P1^7; sbit led4 = P1^0; sbit led5 = P1^4; sbit led6 = P1^5;
sbit K1=P3^5; //按键 sbit K2=P3^7; sbit K3=P3^4; sbit K4=P3^6; sbit K5=P1^6;
sbit Ir1=P1^1; //red Ir sbit Ir2=P1^2;
//DS1302地址定义 #define ds1302_sec_add 0x80 //秒数据地址 #define ds1302_min_add 0x82 //分数据地址 #define ds1302_hr_add 0x84 //时数据地址 #define ds1302_date_add 0x86 //日数据地址 #define ds1302_month_add 0x88 //月数据地址 #define ds1302_day_add 0x8a //星期数据地址 #define ds1302_year_add 0x8c //年数据地址 #define ds1302_control_add 0x8e //控制数据地址 #define ds1302_charger_add 0x90 #define ds1302_clkburst_add 0xbe
//flag uchar flag_led1_sta = 0; uchar flag_led2_sta = 0; uchar flag_led3_sta = 0; uchar flag_led4_sta = 0; uchar flag_led5_sta = 0;
uchar flag_person_cont = 0; uchar flag_person_cont_buf[3]=000; uint flag_per_add = 0; uint flag_per_cut = 0; uint flag_mode_choose = 1; uint flag_guang = 1; //初始时间定义 uchar time_buf[8] = {0x20,0x21,0x02,0x01,0x11,0x47,0x55,0x02};//初始时间2020年11月17号11:47:55 week:2 /*************************延时函数*********************************/ //功能:延时1毫秒 //入口参数:x //出口参数:无 //说明:当晶振为12M时,j<112;当晶振为11.0592M时,j<122 void Delay_xms(uint x) { uint i,j; for(i=0;i<x;i++) for(j=0;j<112;j++); } //功能:12us延时 //STC89C52为1T单片机,即1个时钟/机器周期,速度为AT89C52的12倍 void Delay_xus(uint t) { for(;t>0;t--) { _nop_(); } } //控制LCD写时序 void LCD_en_write(void) { CS=1; Delay_xus(20); CS=0; Delay_xus(20); }
//写指令函数 void Write_Instruction(uchar command) { RS=0; RW=0; CS=1; LCDDATA=command; LCD_en_write();//写入指令数据 }
//写数据函数 void Write_Data(uchar Wdata) { RS=1; RW=0; CS=1; LCDDATA=Wdata; LCD_en_write();//写入数据 }
//字符显示初始地址设置 void LCD_SET_XY(uchar X,uchar Y) { uchar address; if(Y==0) address=0x80+X;//Y=0,表示在第一行显示,地址基数为0x80 else address=0xc0+X;//Y非0时,表时在第二行显示,地址基数为0xC0 Write_Instruction(address);//写指令,设置显示初始地址 } //在第X行Y列开始显示Wdata所对应的单个字符 void LCD_write_char(uchar X,uchar Y,uchar Wdata) { LCD_SET_XY(X,Y);//写地址 Write_Data(Wdata);//写入当前字符并显示 } //清屏函数 void LCD_clear(void) { Write_Instruction(0x01); Delay_xms(5); } void led_init() { led1=1; led2=1; led3=1; led4=1; led5=0; led6=1; } //显示屏初始化函数 void LCD_init(void) { Write_Instruction(0x38); //8bit interface,2line,5*7dots Delay_xms(5); Write_Instruction(0x38); Delay_xms(5); Write_Instruction(0x38);
Write_Instruction(0x08); //关显示,不显光标,光标不闪烁 Write_Instruction(0x01); //清屏 Delay_xms(5);
Write_Instruction(0x04); //写一字符,整屏显示不移动 //Write_Instruction(0x05); //写一字符,整屏右移 //Write_Instruction(0x06); //写一字符,整屏显示不移动 //Write_Instruction(0x07); //写一字符,整屏左移 Delay_xms(5);
//Write_Instruction(0x0B); //关闭显示(不显示字符,只有背光亮) Write_Instruction(0x0C); //开显示,光标、闪烁都关闭 //Write_Instruction(0x0D); //开显示,不显示光标,但光标闪烁 //Write_Instruction(0x0E); //开显示,显示光标,但光标不闪烁 //Write_Instruction(0x0F); //开显示,光标、闪烁均显示 } //DS1302初始化函数 void ds1302_init(void) { RST=0; //RST脚置低 SCK=0; //SCK脚置低 } //向DS1302写入一字节数据 void ds1302_write_byte(uchar addr, uchar d) { uchar i; RST=1; //启动DS1302总线 //写入目标地址:addr addr = addr & 0xFE; //最低位置零,寄存器0位为0时写,为1时读 for (i = 0; i < 8; i ++) { if (addr & 0x01) { IO=1; } else { IO=0; } SCK=1; //产生时钟 SCK=0; addr = addr >> 1; } //写入数据:d for (i = 0; i < 8; i ++) { if (d & 0x01) { IO=1; } else { IO=0; } SCK=1; //产生时钟 SCK=0; d = d >> 1; } RST=0; //停止DS1302总线 }
//从DS1302读出一字节数据 uchar ds1302_read_byte(uchar addr) {
uchar i,temp; RST=1; //启动DS1302总线 //写入目标地址:addr addr = addr | 0x01; //最低位置高,寄存器0位为0时写,为1时读 for (i = 0; i < 8; i ++) { if (addr & 0x01) { IO=1; } else { IO=0; } SCK=1; SCK=0; addr = addr >> 1; } //输出数据:temp for (i = 0; i < 8; i ++) { temp = temp >> 1; if (IO) { temp |= 0x80; } else { temp &= 0x7F; } SCK=1; SCK=0; } RST=0; //停止DS1302总线 return temp; } //向DS302写入时钟数据 void ds1302_write_time(void) { ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护 ds1302_write_byte(ds1302_sec_add,0x80); //暂停时钟 ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电 ds1302_write_byte(ds1302_year_add,time_buf[1]); //年 ds1302_write_byte(ds1302_month_add,time_buf[2]); //月 ds1302_write_byte(ds1302_date_add,time_buf[3]); //日 ds1302_write_byte(ds1302_hr_add,time_buf[4]); //时 ds1302_write_byte(ds1302_min_add,time_buf[5]); //分 ds1302_write_byte(ds1302_sec_add,time_buf[6]); //秒 ds1302_write_byte(ds1302_day_add,time_buf[7]); //周 ds1302_write_byte(ds1302_control_add,0x80); //打开写保护 } //从DS302读出时钟数据 void ds1302_read_time(void) { time_buf[1]=ds1302_read_byte(ds1302_year_add); //年 time_buf[2]=ds1302_read_byte(ds1302_month_add); //月 time_buf[3]=ds1302_read_byte(ds1302_date_add); //日 time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时 time_buf[5]=ds1302_read_byte(ds1302_min_add); //分 time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7f;//秒,屏蔽秒的第7位,避免超出59 time_buf[7]=ds1302_read_byte(ds1302_day_add); //周 } void Display(void) {
LCD_write_char(1,0,dis_time_buf[0]+'0');
LCD_write_char(2,0,dis_time_buf[1]+'0');
.......限于篇幅余下代码请下载附件..............
全部资料51hei下载地址:
智能照明系统.7z
(2.67 MB, 下载次数: 119)
|