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

2019-04-15 17:39发布

基于单片机的带有日历功能的数字时钟 功能: 1.年、月、日,以及24小时制时间显示,均可调 2.自动判断是否闰年以及闰月,理论上至2100年
//去年写的,感觉以后要经常打理自己的博客,与众多Coder分享交流,所以现在才拿出来,多多包含害羞 #include #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;//减
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,啧啧啧···