51单片机利用液晶制作一个时钟

 代码部分有比较详细的注释,这里就不对每一个部分分别做介绍了。有问题欢迎在评论区留言。

#include <REGX52.H>
sbit dula=P2^6;//声明U1锁存器的锁存端
sbit wela=P2^7;//声明U2锁存器的锁存端
sbit rs=P3^5;//lcd数据命令选择端,0写数据,1写命令
sbit lcden=P3^4;//控制LCD的使用
sbit s1=P3^0;//s9
sbit s2=P3^1;//s13
sbit s3=P3^2;//s17
sbit rd=P3^7;//置低电平后分离出第4列四个独立按键
unsigned char count,s1num;
char hour,min,sec,months,weeks,days,comparemonth,m;
unsigned int years;
unsigned char code table1[]="  2022-02-28 MON";
unsigned char code table2[]="    00:00:00";
int code month[12]={31,28,31,30,31,30,31,31,30,31,30,31};//每个月天数  第二月有两种情况 运用时闰年判断下后处理
char code *week[7]={"SUN","MON","TUE","WED","THU","FRI","SAT"};       //每周一天英文缩写  从星期天开始
void delay(unsigned int n)//延时函数,单位为毫秒
{
	unsigned char i, j;
	while(n--)
	{
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}
void write_com(unsigned char com)//写指令
{
	rs=0;
	lcden=0;
	P0=com;
	delay(5);
	lcden=1;
	delay(5);
	lcden=0;
}
void write_date(unsigned char date)//初始化时写数据写数据
{
	rs=1;
	lcden=0;
	P0=date;
	delay(5);
	lcden=1;
	delay(5);
	lcden=0;
}

void init()//初始化显示时间和日期
{
	unsigned char num;
	dula=0;
	wela=0;
	lcden=0;
	write_com(0x38);
	write_com(0x0c);//开显示 不显示光标
	write_com(0x06);//写一个字符后地址指针加1
	write_com(0x01);//显示清零
	write_com(0x80);//控制写入第一行
	for(num=0;num<17;num++)
	{
		write_date(table1[num]);
		delay(5);
	}
	write_com(0x80+0x40);//控制写入第二行
	for(num=0;num<12;num++)
	{
		write_date(table2[num]);
		delay(5);
	}
	TMOD=0x01;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	EA=1;
	ET0=1;
	TR0=1;
}

void write_time(unsigned char line,unsigned char add, unsigned char date)//修改时写数据
{
	unsigned char shi,ge;//十位与个位
	shi=date/10;
	ge=date%10;
	write_com(0x80+(line-1)*0x40+add);	//根据行数和add参数定位写数据位置				
	write_date(0x30+shi); 		//输出十位字符
  write_date(0x30+ge);     //输出个位字符
}

void calweek()//计算周几的函数
{
	char i; //显示字符串 for 循环用
	if(months==1 || months==2)      //如果是1 2月份,要看成前一年的13 14月
	{
		m=months+12;
		years--;
	}
	else m=months;
	weeks=(days+2*m+3*(m+1)/5+years+years/4-years/100+years/400+1)%7;       //基姆拉尔森公式算星期几
	write_com(0x80+13);
	for(i=0;i<3;i++)              //for循环写入字符串每一个字符
		{			
			write_date(week[weeks][i]);
			delay(5);
		}
}

void day_add()
{
	comparemonth=month[months-1];
	if(months==2)           //闰年二月29天
	{
		if(years%4==0)
			comparemonth=29;
	}	
	days++;
	if(days>comparemonth)        //days超过当月天数 回归1日 月份加一
	{
		days=1;
		months++;
		if(months>12)								//加一年
		{
			months=1;
			years++;
			if(years%100==0)								//加一个世纪
			{
				write_time(1,3,years/100);      //年份后两位进位仅前两位更新
			}
			write_time(1,5,years%100);       //年份后两位没进位,只要更新后两位
		}
		write_time(1,8,months);     //更新月份
	}
	write_time(1,11,days);             //更新天数
	calweek();                //计算周几      
}

void keyscan_time()
{
	rd=0;
	if(s1==0)//按下s9
	{
		delay(5);
		if(s1==0)
		{
			s1num++;
			while(!s1);
			if(s1num==1)//光标移动到秒位
			{
				TR0=0;
				write_com(0x80+0x40+11);
				write_com(0x0f);
			}
		}
			switch (s1num)
		{
			case 2: write_com(0x80+0x40+8); 				 				//分
							write_com(0x0f);	
							break;
			case 3: write_com(0x80+0x40+5);     						//时
							write_com(0x0f);	
							break;
			case 4: write_com(0x80+11);          					 //天
							write_com(0x0f);	
							break;
			case 5: write_com(0x80+8);        						 //月
							write_com(0x0f);	
							break;				
			case 6: write_com(0x80+5);     							 //年
							write_com(0x0f);	
							break;				
			case 7: s1num=0;  
							write_com(0x0c);//光标不闪烁	
							TR0=1;
							break;
		}
	}
	if(s1num!=0)
		{
			if(s2==0)
			{
				delay(5);
				if(s2==0)//按下s9,实现对时钟的调节(数值增大)
				{
					while(!s2);
					if(s1num==1)//对秒进行修改
					{
						sec++;
						if(sec==60)
							sec=0;
						write_time(2,10,sec);
						write_com(0x80+0x40+11);
					}
					
					if(s1num==2)//对分钟进行修改
					{
						min++;
						if(min==60)
							min=0;
						write_time(2,7,min);
						write_com(0x80+0x40+8);
					}
					
					if(s1num==3)//对小时进行修改
					{
						hour++;
						if(hour==24)
							hour=0;
						write_time(2,4,hour);
						write_com(0x80+0x40+5);
					}
					comparemonth=month[months-1];
					if(months==2)    	{  	if(years%4==0)	comparemonth=29;	}	 //闰年二月29天
					if(s1num==4)//对天的修改
					{	
						days++;
						if(days>comparemonth)  days=1;
						write_time(1,10,days);
						write_com(0x80+11);
					}
					
					if(s1num==5)//对月的修改
					{
						months++;
						if(months>12)  		months=1;
						write_time(1,7,months); 
						write_com(0x80+8);
					}
					
					if(s1num==6)//对年的修改
					{
						years++;
						if(years%100==0)
						{
							write_time(1,2,years/100);  //年份后两位进位就增加年份前两位更新
							write_com(0x80+3);
						}else{
							write_time(1,4,years%100);       //年份后两位没进位,只要更新后两位
							write_com(0x80+5);
						}
						}
					calweek();                       //计算周几并更新		
				}
			}
			if(s3==0)//按下s17,实现对时钟的调节(数值减小)
			{
				delay(5);
				if(s3==0)
				{
					while(!s3);
					if(s1num==1)
					{
						sec--;
						if(sec==-1)
							sec=59;
						write_time(2,10,sec);
						write_com(0x80+0x40+11);
					}
					if(s1num==2)
					{
						min--;
						if(min==-1)
							min=59;
						write_time(2,7,min);
						write_com(0x80+0x40+8);
					}
					if(s1num==3)
					{
						hour--;
						if(hour==-1)
							hour=23;
						write_time(2,4,hour);
						write_com(0x80+0x40+5);
					}
					comparemonth=month[months-1];  //comparemonth除了2月不确定,其他每月天数都是数组中的数字
					if(months==2)    	{  	if(years%4==0)	comparemonth=29;	}	 //闰年二月29天
					if(s1num==4)
					{
						days--;
						if(days==0)  days=comparemonth;
						write_time(1,10,days);             //更新天数
						write_com(0x80+11);
					}
					if(s1num==5)
					{
						if(months==0) 		months=12;	
						write_time(1,7,months);     //更新月份
						write_com(0x80+8);
					}
					if(s1num==6)
					{
						if(years%100==0)
						{
							write_time(1,2,years/100);  //年份后两位进位就增加年份前两位更新
							write_com(0x80+3);
						}else
						{
							write_time(1,4,years%100);       //年份后两位没进位,只要更新后两位
							write_com(0x80+5);
						}
						}
					calweek();                       //计算周几并更新		
				}
			}
		}
}
void main()
{
	init();
	while(1)
	{
		keyscan_time();
	}
}

void timer0()interrupt 1//中断函数
{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	count++;
	if(count==18)
	{
		count=0;
		sec++;
		if(sec==60)
		{
			sec=0;
			min++;
			if(min==60)
			{
				min=0;
				hour++;
				if(hour==24)
				{
					hour=0;
					day_add();
				}
				write_time(2,4,hour);
			}
			write_time(2,7,min);
		}
		write_time(2,10,sec);
	}
}

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值