基于单片机的带有日历功能的数字时钟

Posted _TFboy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于单片机的带有日历功能的数字时钟相关的知识,希望对你有一定的参考价值。

基于单片机的带有日历功能的数字时钟

功能:

1.年、月、日,以及24小时制时间显示,均可调

2.自动判断是否闰年以及闰月,理论上至2100年


//去年写的,感觉以后要经常打理自己的博客,与众多Coder分享交流,所以现在才拿出来,多多包含

#include<reg51.h>
#define uint unsigned int 
#define uchar unsigned char
#define LCD1602_DATAPINS P0
	
uchar code table[]=" 2016-01-01 SUN";
uchar code table1[]="    23:59:54";
uchar count=0;
uchar shi=23,fen=59,miao=54,nian=16,yue=1,ri=1;
uchar k1_num=0;//k1/k2/k3按下的次数

//按键
sbit k1=P1^1;//功能键
sbit k2=P1^2;//加
sbit k3=P1^3;//减
<pre name="code" class="cpp">void Delay1us(uint a);

void LCD1602_WriteCom(uchar com);/*LCD1602写入8位命令子函数*/
	
void LCD1602_WriteData(uchar dat); /*LCD1602写入8位数据子函数*/
		
void LCD1602_Init();/*LCD1602初始化子程序*/						  


void Delay1us(uint a)

	uint b,c;
	for(c=a;c>0;c--)
		for(b=110;b>0;b--);


void LCD1602_WriteCom(uchar com)	  //写入命令

	LCD1602_E=0;
	LCD1602_RS=0;
	LCD1602_RW=0;
	LCD1602_DATAPINS=com;
	Delay1us(10);
	LCD1602_E=1;
	Delay1us(10);
	LCD1602_E=0;


		   
void LCD1602_WriteData(uchar dat)			//写入数据

	LCD1602_E=0;
	LCD1602_RS=1;
	LCD1602_RW=0;
	LCD1602_DATAPINS=dat;
	Delay1us(10);
	LCD1602_E=1;
	Delay1us(10);
	LCD1602_E=0;



void LCD1602_Init()			 //LCD初始化子程序

	uint num;
 	LCD1602_WriteCom(0x38);  //开显示
	LCD1602_WriteCom(0x0c);  //开显示不显示光标
	LCD1602_WriteCom(0x06);  //写一个指针加1
	LCD1602_WriteCom(0x01);  //清屏
	LCD1602_WriteCom(0x80);  //设置数据指针起点
	for (num=0;num<15;num++)
	
		  LCD1602_WriteData(table[num]);
		  Delay1us(10);
	
	LCD1602_WriteCom(0x80+0x40);
	for (num=0;num<11;num++)
	
		  LCD1602_WriteData(table1[num]);
		  	Delay1us(10);
	
	TMOD=0X01;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	EA=1;//总中断
	ET0=1;
	TR0=1;


void LCD1602_WriteSFM(uchar add,uchar dat)

	  uchar shi,ge;
	  shi=dat/10;
	  ge=dat%10;
	  LCD1602_WriteCom(0x80+0x40+add);
	  LCD1602_WriteData(0x30+shi);//根据字符手册,写十位
	  LCD1602_WriteData(0x30+ge);//根据字符手册,写个位


void LCD1602_WriteNYR(uchar add,uchar dat)

	  uchar shi,ge;
	  shi=dat/10;
	  ge=dat%10;
	  LCD1602_WriteCom(0x80+add);
	  LCD1602_WriteData(0x30+shi);//根据字符手册,写十位
	  LCD1602_WriteData(0x30+ge);//根据字符手册,写个位


void keyscan()

	//k1键指令
	if(k1==0)	
	
		Delay1us(10);
			if(k1==0)
				
				k1_num++;
				while(!k1);
				if(k1_num==1)
				
					TR0=0;
					LCD1602_WriteCom(0x80+0x40+11);
					LCD1602_WriteCom(0x0f);
				
			
			if(k1_num==2)
			
				LCD1602_WriteCom(0x80+0x40+8);
			
			if(k1_num==3)
			
				LCD1602_WriteCom(0x80+0x40+5);
			
			if(k1_num==4)//跳转到日
			
				LCD1602_WriteCom(0x80+10);
			
			if(k1_num==5)//跳转到月
			
				LCD1602_WriteCom(0x80+7);
			
			if(k1_num==6)//跳转到年
			
				LCD1602_WriteCom(0x80+4);
			
			if(k1_num==7)
			
				k1_num=0;
				LCD1602_WriteCom(0x0c);
				if (yue==4||yue==6||yue==9||yue==11)  //防止调时间出现某月的日期超过最大值
				
					if (ri>30)
					ri=30;
					LCD1602_WriteNYR(9,ri);
				
				else if (yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)
				
				  	if (ri>31)
					ri=31;
					LCD1602_WriteNYR(9,ri);
				
				else if (yue==2)
				
					if (nian%4==0)
					
						if (ri>29)
						ri=29;
					
					else 
					
						if (ri>28)
						ri=28;
					
					LCD1602_WriteNYR(9,ri);
				
				TR0=1;
			
	

		if(k1_num!=0)
		
			//k2键指令
			if(k2==0)
			
				Delay1us(5);
				if(k2==0)
				
					while(!k2);
					if(k1_num==1)
					
						miao++;
						if(miao==60)
						miao=0;
						LCD1602_WriteSFM(10,miao);
						LCD1602_WriteCom(0x80+0x40+11);	
					
					if(k1_num==2) //分
					
						fen++;
						if(fen==60)
						fen=0;
						LCD1602_WriteSFM(7,fen);
						LCD1602_WriteCom(0x80+0x40+8);
					
					if(k1_num==3)//时
					
						shi++;
						if(shi==24)
						shi=0;
						LCD1602_WriteSFM(4,shi);
						LCD1602_WriteCom(0x80+0x40+5);
					
					if(k1_num==4)//日
					
						ri++;
						if (yue==4||yue==6||yue==9||yue==11)
						
							if(ri==31)
							ri=1;						
						
						else if (yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)
						
							if (ri==32)
							ri=1;
						
						else if (yue==2)
						
							if (nian%4==0)//闰年
							
								if (ri==30)
								ri=1;
							
							else 
							
							   if (ri==29)
							   ri=1;
							
						
						LCD1602_WriteNYR(9,ri);
						LCD1602_WriteCom(0x80+10); //光标前移一位
					
					if(k1_num==5)//月
					
						yue++;
						if(yue==13)
						yue=1;
						LCD1602_WriteNYR(6,yue);
						LCD1602_WriteCom(0x80+7); //光标前移一位
					
					if(k1_num==6)//年
					
						nian++;
						if(nian==100)
						nian=0;
						LCD1602_WriteNYR(3,nian);
						LCD1602_WriteCom(0x80+4); //光标前移一位
					
				
			
			//k3键指令
			if(k3==0)
			
				Delay1us(10);
				if(k3==0)
				
					while(!k3);
					if(k1_num==1)
					
						miao--;
						if(miao==-1)
						miao=59;
						LCD1602_WriteSFM(10,miao);
						LCD1602_WriteCom(0x80+0x40+11);
					
					if(k1_num==2)
					
						fen--;
						if(fen==-1)
						fen=59;
						LCD1602_WriteSFM(7,fen);
						LCD1602_WriteCom(0x80+0x40+8);
					
					if(k1_num==3)
					
						shi--;
						if(shi==-1)
						shi=23;
						LCD1602_WriteSFM(4,shi);
						LCD1602_WriteCom(0x80+0x40+5);
					
					if(k1_num==4)//日
					
						ri--;
						if(ri==0)
						if (yue==4||yue==6||yue==9||yue==11)
						ri=30;
						else if (yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)
						ri=31;
						else if (yue==2)
						if (nian%4==0)
						ri=29;
						else
						ri=28;
						LCD1602_WriteNYR(9,ri);
						LCD1602_WriteCom(0x80+10); //光标前移一位
					
					if(k1_num==5)//月
					
						yue--;
						if(yue==0)
						yue=12;
						LCD1602_WriteNYR(6,yue);
						LCD1602_WriteCom(0x80+7); //光标前移一位
					
					if(k1_num==6)//年
					
						nian--;
						if(nian==-1)
						nian=99;
						LCD1602_WriteNYR(3,nian);
						LCD1602_WriteCom(0x80+4); //光标前移一位
					
				
			
		


void main()

	LCD1602_Init();
	while (1)
	 
		keyscan () ;
		if 	(count==20)//满一秒
		
			count=0;
			miao++;
			if (miao==60)
			
				miao=0;
				fen++;
				if (fen==60)
				
					fen=0;
					shi++;
					if (shi==24)
					
						shi=0;
						ri++;
						if (yue==4||yue==6||yue==9||yue==11)
						
								if (ri==31)
								
									ri=1;
									yue++;
									if (yue==13)
									
										yue=1;
										nian++;
										if (nian==100)
										nian=0;
										LCD1602_WriteNYR(3,nian);
									
									LCD1602_WriteNYR(6,yue);	
															
						
						else if (yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)
						
						
								if (ri==32)
								
									ri=1;
									yue++;
									if (yue==13)
									
										yue=1;
										nian++;
										if (nian==100)
										nian=0;
										LCD1602_WriteNYR(3,nian);
									
									LCD1602_WriteNYR(6,yue);	
														
						
						else if (yue==2)
						
								if (nian%4==0)//公元2000~2099之间的闰年
								
									if (ri==30)
									
										ri=1;
										yue++;
										if (yue==13)
										
											yue=1;
											nian++;
											if (nian==100)
											nian=0;
											LCD1602_WriteNYR(3,nian);
										
										LCD1602_WriteNYR(6,yue);	
									
								
								else 
								
									if (ri==29)
									
										ri=1;
										yue++;
										if (yue==13)
										
											yue=1;
											nian++;
											if (nian==100)
											nian=0;
											LCD1602_WriteNYR(3,nian);
										
										LCD1602_WriteNYR(6,yue);	
																	
															
						
						
						LCD1602_WriteNYR(9,ri);
					
					LCD1602_WriteSFM(4,shi);
				
				LCD1602_WriteSFM(7,fen);
			
			LCD1602_WriteSFM(10,miao);
				
	

void timer0() interrupt 1

  	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	count++;


PS:这编辑窗口有问题啊,提交好几次都转成html,啧啧啧···

以上是关于基于单片机的带有日历功能的数字时钟的主要内容,如果未能解决你的问题,请参考以下文章

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

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

基于8051单片机实现电子时钟+数字秒表设计

时钟和定时器

基于单片机的多功能时钟闹钟万年历控制系统设计

8051单片机Proteus仿真与开发实例-DS1302 RTC驱动仿真