基于单片机的带有日历功能的数字时钟
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,啧啧啧···
以上是关于基于单片机的带有日历功能的数字时钟的主要内容,如果未能解决你的问题,请参考以下文章