C语言数字时钟设计.docx
《C语言数字时钟设计.docx》由会员分享,可在线阅读,更多相关《C语言数字时钟设计.docx(14页珍藏版)》请在冰豆网上搜索。
C语言数字时钟设计
#include
#include
#defineucharunsignedchar
#definePAXBYTE[0x0fefc]
#definePBXBYTE[0x0fefd]
#definePCXBYTE[0x0fefe]
#defineCTLXBYTE[0x0feff]
codeunsignedcharpan[]={0x0e7,10,0x0eb,3,0x0ed,2,0x0ee,1,//键盘
0x0d7,11,0x0db,6,0x0dd,5,0x0de,4,
0x0b7,12,0x0bb,9,0x0bd,8,0x0be,7,
0x77,13,0x7b,14,0x7d,0,0x7e,15};
unsignedcharbuf[]={0,0,0,0,0,0,0,0},now,old=0xff;
codecharled[]={0x0c0,0x0f9,0x0a4,0x0b0,0x99,0x92,0x82,0x0f8,0x80,0x90,0x0bf,
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x078,0x00,0x10,0x88,0x0c8,0x8e};//字段码0~9,-,0.~9.,n,f
chartime[8]={0,0,0,0,0,0,0,0};//用于放时间
chardate[8]={0,0,0,0,0,0,0,0};//用于放日期
intshow_state;
codeintMAX=150;//用于设置时,无键按下的最多时间
unsignedcharclock_hour=6,clock_minute=30;//设置闹钟的时间
charms50,mx50,hour=5,minute=59,second=55;
intyear=2008;
unsignedcharmonth=10,day=1
;
//XXXXXXXXXXXXXXXX延时1毫秒XXXXXXXXXXXXXXXX//
voiddelay(void)
{ucharm;
for(m=0;m<150;m++);
}
//XXXXXXXXXXXXXXXXLED显示子程序1XXXXXXXXXXXXXXXXX//
voidscan1()
{
unsignedcharm,tc=0x80;
intj;
for(m=0;m<8;m++)
{
PA=0x00;
PB=tc;tc>>=1;
for(j=0;j<1000;j++)delay();
PB=0x00;
for(j=0;j<100;j++)delay();
}
}
//XXXXXXXXXXXLED显示XXXXXXXXXXX//
voidscan2(unsignedcharx[],chara){unsignedcharm,tb,tc=0x80;
for(m=0;m<8;m++)
{
tb=x[m];
PA=led[tb];
if(m==a)
{
PB=0x00;//灭
}
else
{PB=tc;}//亮
tc>>=1;
delay();
}
}
voidtime1()//时间存放数组
{
time[7]=second%10;
time[6]=second/10;
time[5]=10;
time[4]=minute%10;
time[3]=minute/10;
time[2]=10;
time[1]=hour%10;
time[0]=hour/10;
}
voiddate1()//日期存放数组
{
date[7]=day%10;
date[6]=day/10;
date[5]=month%10+11;
date[4]=month/10;
date[3]=year%10+11;
date[2]=year%100/10;
date[1]=year%1000/100;
date[0]=year/1000;
}
//XXXXXXXXXXXX判断闰年程序XXXXXXXXXXXXXXXXXXX//
charrunnian()
{
if((year%400==0)||(year%4==0&&year%100!
=0))
{
return1;
}
return0;
}
voidtimechange(void)interrupt1using2//定时器0中断程序
{intm;
unsignedcharxday;
TF0=0;
TH0=0x4B;
TL0=0x0ff;//0.05s
TR0=1;
ms50++;
if(ms50>=20)//50毫秒中断20次为1秒
{
{ms50=0;second++;}
if(second>=60)
{second=0;minute++;}
if(minute>=60)
{minute=0;hour++;}
if(hour>=24)
{hour=0;day++;}
if(month==1,3,5,7,8,10,12)
{xday=31;}
if(month==4,6,9,11)
{xday=30;}
if(month==2){if(runnian()==1){xday=29;}else{xday=28;}}//判断闰年
if(day>xday)
{month++;day=1;}
if(month>12)
{year++;month=1;}
}
//XXXXXXXXXXXXXXXXXXX计算星期几XXXXXXXXXXXXXXXXXXX//
charweek()
{unsignedchary,w;
y=month;
if(y==1||y==2)y=y+12;
w=(day+1+2*y+3*(y+1)/5+year+year/4-year/100+year/400)%7;//基姆拉尔森计算公式
returnw;
}
//XXXXXXXXXXXXXXXXXXX显示星期几XXXXXXXXXXXXXXXXXXX//
voidshow_week()
{
charn,w,key;
show_state=0;
w=week();
for(n=0;n<8;n++)
time[n]=w;
while
(1)
{
show_state++;
if(show_state==MAX)break;
key=jian(time);
if(key==13)
break;
scan(time);
}
}
//闹钟响
if(hour==clock_hour&&minute==clock_minute)
{P3=P3&0x0fb;
for(m=0;m<5;m++)delay();
P3=P3|0x04;
}
}
//XXXXXXXXXXXXXXXX键盘子程序XXXXXXXXXXXXXXXXXX//
unsignedcharjianpan()
{
unsignedcharm,row,line,k_value;
PC=0xf0;
if(PC&0xf0==0xf0)return0x0ff;//无键按下
line=0x0FE;
for(m=0;m<4;m++)
{PC=line;//输出扫描信号
row=PC;//读键盘口
if((row&0xf0)!
=0xf0)
break;
line=(line<<1)+1;//下一行
}
if(m==4)return0xff;
k_value=(row&0xf0)|(line&0x0f);//给各键赋键值
for(m=0;m<32;m=m+2)
{
if(pan[m]==k_value)
returnpan[m+1];
}
return0x0ff;
}
unsignedcharjian(unsignedchara[])
{//读键盘5次,每次间隔10ms,判断键值是否有变,起到消抖动作用
unsignedcharjj[5]={0,0,0,0,0};
charn;
for(n=0;n<5;n++)
{h[n]=jianpan();scan(a);}
if((h[0]==h[1])&&(h[1]==h[2])&&(h[2]==h[3])&&(h[3]==h[4]))
{
now=jj[0];
if(now!
=old)//键值前后不等
{
old=now;
returnnow;
}
return0xff;
}
else
return0xff;
}
//XXXXXXXXXXXXXXXXXXX设置时间XXXXXXXXXXXXXXXXXXX//
voidset_time()
{
unsignedcharm=0,key=0xff,team=0,j;
show_state=0;
time[6]=10;//--用于区别时间设置与时间显示
time[7]=10;
while
(1)
{
show_state++;
if(show_state==MAX){team=1;break;}//5s无按键自动退出
for(j=0;j<12;j++)
scan2(time,m);
key=jian(time);//获取键值
if(key!
=0x0ff)
{show_state=0;
if(key==13&&(time[0]*10+time[1])<24&&(time[3]*10+time[4])<60)//确定,退出
break;
elseif(key==15){team=1;break;}//取消,退出
elseif(key<=9)
{
if(m==0&&key<=2)//控制时、分钟的个位和及十位输入的有效的键值
{time[m]=key;m++;}
elseif(m==1&&time[0]<2&&key<=9)
{time[m]=key;m++;}
elseif(m==1&&key<=3)
{time[m]=key;m++;}
elseif(m==3&&key<=5)
{time[m]=key;m++;}
elseif(m==4)
{time[m]=key;m++;}
m=m%5;
}
}
elseif(m==2)
m++;
}
if(team==0)
{
hour=time[0]*10+time[1];
minute=time[3]*10+time[4];
}
}
//XXXXXXXXXXXXXXXXXXX设置日期XXXXXXXXXXXXXXXXXXX//
voidset_date()
{
unsignedcharm=0,key,j,team=0;
inty=year;
show_state=0;
date1();
date[6]=0;
date[7]=1;
while
(1)
{
show_state++;
if(show_state==MAX){team=1;break;}//5s无按键自动退出
for(j=0;j<12;j++)
scan2(date,m);
key=jian(date);
if(key!
=0x0ff)
{show_state=0;
if(key==13&&(date[4]*10+date[5]-11)<13&&(date[4]*10+date[5]-11)>0)//确认退出
{break;}
elseif(key==15){team=1;break;}
{
if(m==3){date[m]=key+11;m++;}//年份的最后一位
elseif(m==4&&key<=1){date[m]=key;m++;}//月份的高位只能为0或1
elseif(m==5)
{
if(date[4]==1&&key<=2){date[m]=key+11;m++;}//如果月份高位大于0,那月份的低位只能小于3
else
{date[m]=key+11;m++;}
}
elseif(m==6&&key<=2&&date[4]==0&&date[5]==13){date[m]=key;m++;}//如果月份是2月,天数的高位要小于3
elseif(m==6&&key<=3&&date[4]!
=0&&date[5]!
=13){date[m]=key;m++;}//不是2月,天数的高位可以为3
elseif(m==7&&key<=9&&date[6]==2&&date[4]==0&&date[5]==13)//二月且天数高位为2
{
year=date[0]*1000+date[1]*100+date[2]*10+date[3]-11;
if(runnian()!
=1&&key<=8)//不是闰年,低位只能0-8
{date[m]=key;m++;}
elseif(runnian()==1)//是闰年,低位0-9
{date[m]=key;m++;}
year=y;
}
elseif(m==7&&key<=9&&date[6]==2){date[m]=key;m++;}//不是二月且天数的高位为2,天数的低位0-8
elseif(m==7&&key<=1&&date[6]==3)//天数的高位为3
{
y=date[4]*10+date[5]-11;
if((y==2||y==4,y==6||y==9||y==11)&&key==0)
{date[m]=key;m++;}//是2,4,6,9,11月,天数的低位只能为0,否则为1
else
{date[m]=key;m++;}
}
elseif((m==0||m==1||m==2)&&key<=9){date[m]=key;m++;}
m=m%8;
}
}
}
if(team==0)
{
year=date[0]*1000+date[1]*100+date[2]*10+date[3]-11;
month=date[4]*10+date[5]-11;
day=date[6]*10+date[7];
}
}
//XXXXXXXXXXXXXX开机自检子程序XXXXXXXXXXXXXXXX//
voidzijian()
{
intm,j;
scan1();//检查数码管
p_jiance();
for(j=0;j<3;j++)
{
P3=P3&0x0fb;
for(m=0;m<1000;m++)delay();
P3=P3|0x04;
for(m=0;m<1000;m++)
delay();
}
}
//XXXXXXXXXXXXLED显示子程序2XXXXXXXXXXXX//
voidscan(charbuf[])
{unsignedcharm,tb,tc=0x80;
for(m=0;m<8;m++)
{
tb=buf[m];
PA=led[tb];
PB=tc;
tc>>=1;//右移一位
delay();
}
}
//XXXXXXXXXXXXXXXXXXX指示灯检测XXXXXXXXXXXXXXXXXXX//
voidp_jiance()
{
unsignedcharteam,m;
intj;
team=0x80;
for(m=0;m<8;m++)
{
P1=~team;
team>>=1;
for(j=0;j<100;j++)
scan(time);
}
P1=0xff;
}
//XXXXXXXXXXXXXXXXXXX主程序XXXXXXXXXXXXXXXXXXX//
voidmain()
{
ucharj,key=0;
for(j=0;j<255;j++)
delay();
CTL=0x88;//设置8255工作方式
zijian();//开机自检
TMOD=0x01;
TH0=0x4B;
TL0=0x0ff;//0.05s
TR0=1;
IE=0x82;
ms50=0;//这两个为50毫秒计数
mx50=0;
for(j=0;j<255;j++)
scan(time);
while
(1)
{
if(key==10)//时间、日期显示切换
{
if(mx50>=100)
mx50=0;
elsemx50=101;
}
elseif(key==11)
set_time();//时间设置
elseif(key==12)
set_date();//日期设置
show_week();//显示星期
if(mx50<100)//5秒时间显示
{
time1();
key=jian(time);
}
else//5秒日期显示
{
date1();
key=jian(date);
if(mx50>=200)//重新计数
mx50=0;
}
}
}