代码部分有比较详细的注释,这里就不对每一个部分分别做介绍了。有问题欢迎在评论区留言。
#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);
}
}