把前天设计的时钟的功能补全了一些,贴上来,
#include
#define uchar unsigned char
sbit rd=P2^6;
sbit wr=P2^5;
sbit lcde=P2^7;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k4=P1^3;
sbit k8=P1^7;
uchar code table1[]='2011-11-05';
uchar code table2[]='00:00:00';
uchar code table3[][3]={{'MON'},{'TUE'},{'WED'},{'THU'},{'FRI'},{'SAT'},{'SUN'}}; //定义了二维数组存放星期
uchar t,s1num;
char shi,fen,miao,week,nian;
uchar yue=1,ri=1;
void delay(uchar z) //延迟zms函数
{
uchar x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com) //液晶写指令操作
{
rd=0;
wr=0;
delay(5);
lcde=1;
P0=com;
lcde=0;
}
void write_date(uchar date) //液晶写数据操作
{
rd=1;
wr=0;
delay(5);
lcde=1;
P0=date;
lcde=0;
}
void write_sfm(uchar add,uchar date) //更新时分秒
{
uchar shi,ge;
shi=date/10;
ge=date;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void write_week(uchar i) //更新星期
{
uchar j;
write_com(0x80+0x0b);
for(j=0;j<3;j++)
{
write_date(table3[i][j]);
}
}
void write_riqi(uchar add,uchar riqi) //更新年月日
{
uchar shi,ge;
shi=riqi/10;
ge=riqi;
write_com(0x80+0x00+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void init() //初始化函数
{
uchar i,j;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80+0x00);
for(i=0;i<10;i++)
write_date(table1[i]);
write_com(0x80+0x00+0x0b);
for(j=0;j<3;j++)
write_date(table3[week][j]);
write_com(0x80+0x46);
for(i=0;i<8;i++)
write_date(table2[i]);
TMOD=0x01; //定时器0工作方式1
TH0=(65536-50000)/256; //设定定时器初值
TL0=(65536-50000)%6; //12M晶振时50ms数为50000
EA=1;
ET0=1;
TR0=1;
}
void keyscan() //键盘扫描函数
{
if(k1==0) //按下k1键确定调时分秒
{
delay(5);
if(k1==0)
{
s1num++;
while(!k1)
;
delay(5);
while(!k1);
if(s1num==1)
{
TR0=0; //暂停计时器
write_com(0x80+0x4d); //光标在秒的位置闪烁
write_com(0x0f);
}
if(s1num==2) //光标在分的位置
{
TR0=0;
write_com(0x80+0x4a);
write_com(0x0f);
}
if(s1num==3) //光标在小时的位置
{
TR0=0;
write_com(0x80+0x47);
write_com(0x0f);
}
if(s1num==4) //光标在星期的位置
{
TR0=0;
write_com(0x80+0x0d);
write_com(0x0f);
}
if(s1num==5) //光标在日的位置
{
TR0=0;
write_com(0x80+0x09);
write_com(0x0f);
}
if(s1num==6) //光标在月的位置
{
TR0=0;
write_com(0x80+0x06);
write_com(0x0f);
}
if(s1num==7) //光标在年的位置
{
TR0=0;
write_com(0x80+0x03);
write_com(0x0f);
}
if(s1num==8) //按下第8下时接着走时
{
s1num=0;
write_com(0x0c);
TR0=1;
}
}
}
if(s1num!=0)
{
if(s1num==1)
{
if(k2==0) //按k2键秒加1
{
delay(5);
if(k2==0)
{
while(!k2);
delay(5);
while(!k2);
miao++;
if(miao==60)
miao=0;
write_sfm(0x0c,miao);
write_com(0x80+0x4d);
}
}
}
if(s1num==2)
{
if(k2==0) //分加1
{
delay(5);
if(k2==0)
{
while(!k2);
delay(5);
while(!k2);
fen++;
if(fen==60)
fen=0;
write_sfm(0x09,fen);
write_com(0x80+0x4a);
}
}
}
if(s1num==3)
{
if(k2==0) //时加1
{
delay(5);
if(k2==0)
{
while(!k2);
delay(5);
while(!k2);
shi++;
if(shi==24)
shi=0;
write_sfm(0x06,shi);
write_com(0x80+0x47);
}
}
}
if(s1num==4)
{
if(k2==0) //星期加1
{
delay(5);
if(k2==0)
{
while(!k2);
delay(5);
while(!k2);
week++;
if(week==7)
week=0;
write_week(week);
write_com(0x80+0x0d);
}
}
}
if(s1num==5)
{
if(k2==0) //日加1
{
delay(5);
if(k2==0)
{
while(!k2);
delay(5);
while(!k2);
ri++;
if(ri==31)
ri=1;
write_riqi(0x08,ri);
write_com(0x80+0x09);
}
}
}
if(s1num==6)
{
if(k2==0) //月加1
{
delay(5);
if(k2==0)
{
while(!k2);
delay(5);
while(!k2);
yue++;
if(yue==12)
yue=1;
write_riqi(0x05,yue);
write_com(0x80+0x06);
}
}
}
if(s1num==7)
{
if(k2==0) //年加1
{
delay(5);
if(k2==0)
{
while(!k2);
delay(5);
while(!k2);
nian++;
if(nian==100)
nian=0;
write_riqi(0x02,nian);
write_com(0x80+0x03);
}
}
}
if(k4==0) //判断k4是否被按下
{
delay(5);
if(k4==0)
{
while(!k4);
delay(5);
while(!k4);
if(s1num==1)
{
miao--; //秒减1
if(miao==-1)
miao=59;
write_sfm(0x0c,miao);
write_com(0x80+0x4d);
}
if(s1num==2)
{
fen--; //分减1
if(fen==-1)
fen=59;
write_sfm(0x09,fen);
write_com(0x80+0x4a);
}
if(s1num==3)
{
shi--; //时减1
if(shi==-1)
shi=23;
write_sfm(0x06,shi);
write_com(0x80+0x47);
}
if(s1num==4)
{
week--; //星期减1
if(week==-1)
week=6;
write_week(week);
write_com(0x80+0x0d);
}
if(s1num==5)
{
ri--; //日减1
if(ri==0)
ri=30;
write_riqi(0x08,ri);
write_com(0x80+0x09);
}
if(s1num==6)
{
yue--; //月减1
if(yue==0)
yue=12;
write_riqi(0x05,yue);
write_com(0x80+0x06);
}
if(s1num==7)
{
nian--; //年减1
if(nian==-1)
nian=99;
write_riqi(0x02,nian);
write_com(0x80+0x03);
}
}
}
}
if(k8==0) // 按下k8退出调时
{
delay(5);
if(k8==0)
{
while(!k8);
delay(5);
while(!k8);
s1num=0;
write_com(0x0c);
TR0=1;
}
}
}
void main()
{
init();
while(1)
{
keyscan();
}
}
void timer0() interrupt 1 //中断服务程序
{
TH0=(65536-50000)/256; //设定定时器初值
TL0=(65536-50000)%6; //12M晶振时50ms数为50000
t++;
if(t==20) //定时器中断20次为1秒
{
t=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
ri++;
week++;
if(week==7)
week=0;
write_week(week); //刷新星期
if(ri==31)
{
ri=1;
yue++;
if(yue==13)
{
yue=1;
nian++;
if(nian==100)
nian=0;
write_riqi(0x02,nian); //刷新年
}
write_riqi(0x05,yue); //刷新月
}
write_riqi(0x08,ri); //刷新日
}
write_sfm(0x06,shi); //刷新时
}
write_sfm(0x09,fen); //刷新分
}
write_sfm(0x0c,miao); //刷新秒
}
}
// 还可以加上整点报时和断电记忆的功能,还可以加上24小时和12小时制转换功能,还可以加上秒表功能,原理都是一样的,但由于51单片机内存有限,只有
//4k,所以没加
//由于单片机晶振不是严格的12MHz,所以要想时钟精确的话还要进行中断时间的调整//其中年只能改变后两位,即从2000到2099年,其实也可实现全调,原理是一样的,但没这个必要