基于51单片机+DS1302万年历+LCD1602显示+按键播报时间+温控风扇+按键控灯

Posted 皮卡丘吉尔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于51单片机+DS1302万年历+LCD1602显示+按键播报时间+温控风扇+按键控灯相关的知识,希望对你有一定的参考价值。

基于51单片机万年历


前段时间做了一个 基于51单片机的万年历加温度控制风扇以及按键播报时间。在这里做一下笔记。

准备硬件

1:51单片机(我这里用的是STC89C52)
2:语音播报模块(我这里用的是SYN6288)
3:DS1302时钟模块
4:DS18B20温度模块
5:LCD1602显示屏
6:L298N电机驱动
7:蜂鸣器
8:电机
9:按键 5个
10:灯

功能介绍

功能
1:修改时间
2:修改日期(软件自动校正日期)
3:闹钟模式
4:温度控制风扇速度
5:调节灯亮度
6:播报时间

主界面设置
下面是大概的流程图 位置不够没画全。。。

由于代码较多,这里就不全部贴出来了。

修改时间

当我们进入到修改时间的界面,我们屏幕得显示出刚按下的时间,然后我们得让
1: LCD1602显示时间
2:按键的操作
按键 1:让时 / 分 /秒+1 或者按下按键2 让时 / 分 /秒 -1,然后通过按键3 来切换我到底是 调整时 / 分 /秒
3:按键4按下 退出
4:提示是否保存时间(1:保存,4:不保存)
如果保存我们再写入到DS1302这样就完成了修改时间的功能

/*时间数值 加 函数*/
unsigned char time_add(unsigned char cursor)

	unsigned char hour_high,hour_low;
	unsigned char min_high, min_low;
	unsigned char sec_high, sec_low;
	switch(cursor)
	
		case 0: //修改 时++
			hour_high = temp[2] >> 4;
			hour_low  = temp[2] & 0x0f;
			hour_low = hour_low++;
			if(hour_low == 4 && hour_high == 2) //如果等于24时 变00
			
				hour_low = 0;
				hour_high = 0;	
			
			else if(hour_low == 10)
			
				hour_low = 0;
				if(hour_high == 2)
					hour_high = 0;
				else
					hour_high = hour_high + 1;	
			
			hour_high = hour_high << 4;
			hour_high = hour_high | hour_low;
			temp[2] = hour_high;
							
			lcd_display_byte(5,0,(temp[2]>>4) + 0x30);
			lcd_display_byte(6,0,(temp[2]&0x0f) + 0x30);
			write_com(0x86);
			break;
		
		case 1://修改 分++	
			min_high  = temp[1] >> 4;
			min_low   = temp[1] & 0x0f;
			
			min_low++;
			if(min_low == 10)
			
				min_high++;
				min_low = 0;
				if(min_high == 6 && min_low == 0)
				
					min_high = 0;
					min_low = 0;
				
			
			min_high = min_high << 4;
			min_high = min_high | min_low;
			temp[1] =  min_high;
			lcd_display_byte(8,0,(temp[1]>>4) + 0x30);
			lcd_display_byte(9,0,(temp[1]&0x0f) + 0x30);
			write_com(0x89);
			break;
	
		case 2://修改 秒++
			sec_high  = temp[0] >> 4;
			sec_low   = temp[0] & 0x0f;
			sec_low++;
			if(sec_low == 10)
			
				sec_low = 0;
				sec_high++;
				if(sec_high == 6 && sec_low == 0)
				
					sec_low = 0;
					sec_high = 0;	
				
			
			sec_high = sec_high << 4;
			sec_high = sec_high | sec_low;
			temp[0] =  sec_high;
			
			lcd_display_byte(11,0,(temp[0]>>4) + 0x30);
			lcd_display_byte(12,0,(temp[0]&0x0f) + 0x30);
			write_com(0x8c);
			break;	
		default :
			break;
		
	return cursor;				

修改日期(并且校正星期)

当我们进入到修改日期的界面,我们屏幕得显示出刚按下的日期,然后我们得让
1: LCD1602显示日期
2:按键的操作
按键 1:让年/月/日+1 或者按下按键2 让年/月/日 -1,然后通过按键3 来切换我到底是 调整年/月/日
3:按键4按下 退出
4:提示是否保存日期(1:保存,4:不保存)
5:星期的自动调整
星期 = (月份对应的数字+日期数字) / 7 余数:则是星期几 0位周日
如果保存我们再写入到DS1302这样就完成了修改日期的功能

/*自动修正星期 函数*/
void revision_week()

	unsigned char num;
	unsigned char month;
	unsigned char day;
	unsigned char week;

	//星期 = (月份对应数字+日期数字) / 7 余数:则是星期几  0位周日

	month = ((temp[4]>>4)*10 + (temp[4]&0x0f));//将月份BCD码转为十进制
	day = ((temp[3]>>4)*10 + (temp[3]&0x0f));  //将日BCD码转为十进制 	
	switch(month)
	
		//月份对应数字
		case 5:	num = 5; break;
		case 6: num = 1; break;
		case 8:	num = 6; break;
		case 1:	case 10: num = 4; break;
		case 4: case 7:  num = 3; break;
		case 9:	case 12: num = 2; break;
		case 2:  case 3:  case 11: num = 0; break;	 
	
	week = (num+day)%7;
   	if(week == 0) 
		temp[5] = 0x07;
	else
		temp[5] = week;

 

闹钟模式

进入到闹钟模式,设置闹钟的时间 选择周几,选择响铃时长。
时间的设置 跟修改时间的设置一模一样,等设置完时间,我们调到设置星期,按键1是 切换周一到 周日,按键2是确认选择当前这个星期,按键3是取消选择当前这个星期。
按键4:是否保存? 不保存就退出了,如果保存继续跳转到选择闹钟时间的界面。这里就没啥了。然后保存退出。主界面OFF 变成 ON 表示开启了

/* 选择/取消星期几 响闹钟*/
/* 周几++   打开   关闭  退出  */  
void lcd_dispaly_chooseClockWeek()

	unsigned char s = 0;
	unsigned char week;
	LCD1602_CLS; //清屏
	lcd_display_str(0,0,"week:  2:ON3:OFF");
	lcd_display_str(0,1,"clock:");
	week = temp[5];	
	while(1)
	
		lcd_display_byte(5,0,(week & 0x0f) + 0x30); //显示当前星期
		for(s=0;s<7;s++)
		
			if((alarmClockWeek>>s)&0x01 == 1)
				lcd_display_byte(s+6,1,(s+1)+0x30);	
		
		write_com(0x85);
		menu = gather_key(); //采集哪个按键被按下函数	
		switch(menu) 
		
			case 1:
				week++;
				if(week >= 8)
					week = 1;			
				break;
			case 2:
				switch(week)
					  			
					case 1:	alarmClockWeek |= 0x01; lcd_display_byte(6,1,'1'); break;//0000 0001
					case 2:	alarmClockWeek |= 0x02; lcd_display_byte(7,1,'2'); break;//0000 0010
					case 3:	alarmClockWeek |= 0x04; lcd_display_byte(8,1,'3'); break;//0000 0100
					case 4:	alarmClockWeek |= 0x08; lcd_display_byte(9,1,'4'); break;//0000 1000
					case 5:	alarmClockWeek |= 0x10; lcd_display_byte(10,1,'5'); break;//0001 0000
					case 6:	alarmClockWeek |= 0x20; lcd_display_byte(11,1,'6'); break;//0010 0000
					case 7:	alarmClockWeek |= 0x40; lcd_display_byte(12,1,'7'); break;//0100 0000
				
				break;
			case 3:
				switch(week)
				
					case 1:	alarmClockWeek &= ~0x01; lcd_display_byte(6,1,' '); break;
					case 2:	alarmClockWeek &= ~0x02; lcd_display_byte(7,1,' '); break;
					case 3:	alarmClockWeek &= ~0x04; lcd_display_byte(8,1,' '); break;
					case 4:	alarmClockWeek &= ~0x08; lcd_display_byte(9,1,' '); break;
					case 5:	alarmClockWeek &= ~0x10; lcd_display_byte(10,1,' '); break;
					case 6:	alarmClockWeek &= ~0x20; lcd_display_byte(11,1,' '); break;
					case 7:	alarmClockWeek &= ~0x40; lcd_display_byte(12,1,' '); break;
				
				break;
			case 4:
				s = lcd_display_saveTimeOrDate_YesOrNo(3);//保存? 不:清空为0  保则不清空
				if(s)
				
					ALARM_CLOCK_OFF; //关闭闹钟
					//闹钟日期清空
					alarmClockWeek = 0;	
					LCD1602_CLS; //清屏
					return;				
				
				ALARM_CLOCK_ON;  //开启闹钟
				LCD1602_CLS; //清屏
				return;
		
				



调节灯模式

/*修改灯亮度 函数*/
void modifLightMode()

	unsigned char s = 0;
	s = lcd_display_light_menu(); //显示修改灯亮度菜单
	if(s)
	
		write_com(CLEAR_SCREEN);//清屏
		exitFlag = 1;
		return;	
	
	lcd_display_str(0,0,"Light gear:");
	TR0 = 1;
	while(menu != 4)
	
		lcd_display_byte(11,0,light_gear+0x30);//显示灯档位
		menu = gather_key(); //检测是否有按键按下
		switch(menu)
		
			case 1:
				light_gear++;
				if(light_gear>=3)
				
					light_gear = 3;
					TR0 = 0;
					LED = 0;
				
				else if(light_gear == 0)
				
					TR0 = 0;
					LED = 1;
				
				else
				
					TR0 = 1;
					LED = 0;
				
				break;
			case 2:
				
				if(light_gear>=1)
				
					light_gear--;			
					
				else
				
					light_gear = 0;
				

				if(light_gear == 3)
				
					TR0 = 0;
					LED = 0;
				
				else if(light_gear == 0)
				
					TR0 = 0;
					LED = 1;
				
				else
				
					TR0 = 1;
					LED = 0;					
				
				break;

			case 4:
				exitFlag = 1;
				return;
			
			


调节风扇模式

/*修改风扇速度 函数*/
void modifFanMode()

	unsigned char s = 0;
	s = lcd_display_fan_menu(); //显示修改风扇速度菜单
	if(s)
	
		write_com(CLEAR_SCREEN);//清屏
		exitFlag = 1;
		return;	
	
	lcd_display_str(0,0,"Fan gear:");
	TR1 = 1;
	while(menu != 4)
	
		lcd_display_byte(9,0,fan_gear+0x30);//显示风扇档位
		menu = gather_key(); //检测是否有按键按下
		switch(menu)
		
			case 1:
				fan_gear++;
				if(fan_gear>=3)
				
					FAN = 1;
					TR1 = 0;
					fan_gear = 3;
				
				else if(fan_gear == 0)
				
					FAN = 0;
					TR1 = 0;
				
				else
				
					FAN = 1;
					TR1 = 1;	
				
				break;
			case 2:
				
				if(fan_gear>=1)
				
					fan_gear--;
				
				if(fan_gear == 0)
				
					FAN = 0;
					TR1 = 0;					
					fan_gear = 0;
				
				else if(fan_gear == 3)
				
					FAN = 1;
					TR1 = 0;										
				
				else
				
					TR1 = 1;
					FAN = 1;
				
				break;
			case 4:
				exitFlag = 1;
				return;
			
			


按键播报时间

这里我是用外部中断做。


/*SYN6288播报时间*/
void playTime(void)

	unsigned char syn6288_time[5] = '\\0';
	syn6288_time[0] = (time[2]>>4)+48; 	 //时
	syn6288_time[1] = (time[2]&0x0f)+48;
	syn6288_time[2] = ':';
	syn6288_time[3] = (time[1]>>4)+48;	 //分
	syn6288_time[4] = (time[1]&0x0f)+48;
	SYN_FrameInfo(0, "[v16][t5]当前时间");
	delay(2000);
	SYN_FrameInfo(0,syn6288_time);
	delay(2000);


void key_handler(vo

以上是关于基于51单片机+DS1302万年历+LCD1602显示+按键播报时间+温控风扇+按键控灯的主要内容,如果未能解决你的问题,请参考以下文章

基于51单片机+DS1302+ LCD1602显示时间Proteus仿真

基于51单片机+DS1302时钟模块+LCD1602显示

基于51单片机+DS1302时钟模块+LCD1602显示

基于51单片机+DS1302时钟模块+LCD1602显示

电子时钟万年历+51单片机+1602液晶屏+DS1302+DS18B20+按键

51单片机 LCD1602+DS1302实时时钟+Proteus仿真