仿真图1:
A. 由数码管作为显示器,三个按键可以设置时间。
仿真图2:
A 由数码管作为显示器,可通过开关设置年月日星期等时间;
#include
#define uchar unsigned char
uchar code tab[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};
//共阳极数码管显示"0~9","灭"和"-"的字段码
//uchar code tab[]={0x3f,0x06,05b,0x4f,0x66,0x6d,07d,0x07,0x7f,0x6f,0x00,0x40};//共阴数码管
uchar code wetab[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位选
uchar data dis[8]={0x00,0x00,0x0b,0x00,0x00,0x0b,0x00,0x00};
//显示数据缓冲区,时十、个位、分十、个位、秒十、个位初始为0,0x0b为"-"编码
uchar data timedat[3]={0x00,0x00,0x00}; //分别为秒、分和小时的计数值(记录K1和K2次数)
uchar data ms50=0x00, num=0x00, n1=0x00, n2=0x00;
//定义定时次数变量,调整模式变量,按加1键次数变量,按减1键次数变量
sbit key0=P1^0 ; //调整键--模式
sbit key1=P1^1 ; //加1键
sbit key2=P1^2 ; //减1键
//---------------------------------------
void delay1ms( unsigned int z ) //定义延时1ms函数
{ unsigned int x, y ;
for ( x=z; x>0; x-- )
for ( y=120; y>0 ; y-- ) ;
}
//---------------------------------------
//按键处理函数。如果没有按键则时钟正常走时。当按K0键1次→暂停走时进入调小时状态;再按K0键1次→进入调分钟状态;再按K0键1次→回到正常走时状态。对于K1和K2键,如果正常走时下→按K1K2键不起作用;如果进入调时或者调分状态→按K1键可对时或分加1操作,小时加到24则回0,分钟加到60则回0。按K2键可对时或分减1操作,小时减到负则回23,分钟减到负则回59。
void keyscan( void )
{ EA=0; //关中断
if(timedat[0]==0&timedat[1]==0&timedat[2]==7) {P1=0xff;}
if (key0==0) { delay1ms(10); while (key0==0);
num++; TR0=0; ET0=0; // 调整键K0每按1次--模式变量num加1
if (num>=3) {num=0; ET0=1; TR0=1; } // 启动T0校时
}
if (num!=0) //模式变量不等于0
{ if (key1==0) // K1键确实按下
{ delay1ms(10); while (key1==0); timedat[num]++; //记录按键K1按下次数
if (num==2) n1=24; else n1=60; //模式变量等于小时2--则回迟到一天或60分钟
if (timedat[num]>=n1) { timedat[num]=0; } }
}
if (num!=0)
{ if (key2==0)
{ delay1ms(10); while (key2==0); timedat[num]--; //记录按键K2按下次数
if (num==2) n2=23;else n2=59;
if (timedat[num]<=0) {timedat[num]=n2; } }
}
EA=1;
}
//---------------------------------------
//数码管显示函数。时间显示先秒个位计算显示→秒十位计算显示→再分个位计算显示→分十位显示→再时个位计算显示→时十位显示。
void display( void )
{ uchar k;
if(timedat[0]==0&timedat[1]==0&timedat[2]==7) {P1=0xff;}
dis[0]=timedat[0]%10; dis[1]=timedat[0]/10; //秒
dis[3]=timedat[1]%10; dis[4]=timedat[1]/10; //分
dis[6]=timedat[2]%10; dis[7]=timedat[2]/10; //时
for ( k=0; k<8; k++ )
{ P0=tab[ dis[k] ]; P2=wetab[k]; delay1ms(1); P2=0x00; }
}
//---------------------------------------
//主函数,时间显示先秒个位计算显示,然后是秒十位计算显示;再就是分个位计算显示,然后是分十位显示;再就是时个位计算显示,然后是时十位显示。定时器中断先检测1秒是否到→1秒如果到则秒单元加1;1秒如果没到就检测1分钟是否到→1分钟如果到则分单元加1;如果没到就检测1小时是否到→1小时如果到则时单元加1;如果没到→则显示时间。
void main( void )
{ TMOD=0x01; //T0定时50ms,方式1
EA=1; ET0=1; TR0=1; //开中断,允许T0中断,启动T0
TH0=0x3c; TL0=0xb0;
while (1)
{ display( ) ;
keyscan( ) ;
}
}
//定时器/计数器T0中断服务函数。定时器中断先检测1秒是否到→1秒如果到则秒单元加1;1秒如果没到就检测1分钟是否到→1分钟如果到则分单元加1;如果没到就检测1小时是否到→1小时如果到则时单元加1;如果没到→则显示时间。
void timer0(void) interrupt 1
{ ET0=0; TR0=0; //不许T0中断也不启动
TH0=0x3c; TL0=0xb0;
TR0=1; //启动T0
ms50++;
P1=0xf7;
if(timedat[0]==0&timedat[1]==0&timedat[2]==7) {P1=0xff;}
if (ms50==20) { ms50=0x00; timedat[0]++; //变量m回0,且秒加1
if (timedat[0]==60) { timedat[0]=0;timedat[1]++; //秒到60后回0,且分加1
if (timedat[1]==60) { timedat[1]=0;timedat[2]++; //分到60后回0,且时加1
if (timedat[2]==24) { timedat[2]=0; } } } //时到24后回0
}
ET0=1; //允许T0中断
}
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define ture 1
#define fault 0
sbit SET=P1^7;
void delay(uchar k) ;
uchar monthday(uchar a,uchar b);
void display() ;
uchar code dayofmonth[]={31,28,31,30,31,30,31,31,30,31,30,31};
uchar code scan[]={0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,
0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf8,0xf9,0xfa,0xfb,0xfc,0xfd};
//扫描的译码信号
uchar i;
uchar code table[]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0xA7,0xFF,0xEF,0xC0};
uchar buffer[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uchar shuju=0;
uchar state=0;
uchar qxiang;
typedef struct
{
uchar year[2];
uchar month;
uchar day;
uchar week;
}date;
typedef struct
{
uchar hour;
uchar minute;
uchar second;
}time;
uchar count=0;
date today={{9,20},4,20,1};
time now={11,8,10};
void main()
{
TMOD=0x01;
TL0=(65536-1000)%256;
TH0=(65536-1000)/256;
IE=0x82; //EA=1;ET0=1总中断允许和定时器中断允许
TCON=0x10; //定时器启动计数
while(1)
{
P1=0xff;
shuju=P1&0xff;
qxiang=shuju&0x80;
switch(qxiang)
{
case(0x80):switch(shuju)
{
case(0xfe) : //秒调整
{
EA=1;
EX0=1; //IE=0x83; //EA=1;ET0=1;EX0=0总中断允许,定时器中断允许,外中断允许
IT0=1; //TCON=0x11; //TR0=1;IT0=1;定时器启动,外中断为负边沿触发
}break;
case(0xfd) : //分调整
{
EA=1;
EX0=1; // IE=0x83;
IT0=1; //TCON=0x11;
}break;
case(0xfb) : //时调整
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0xf7) : //星期调整
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0xef) : //日调整
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0xdf): //月调整
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0xbf): //年调整
{
EA=1;
EX0=1;
IT0=1;
}break;
default: //时钟正常计时
{
EA=1;
TR0=1;
EX0=0;
}break;
}break;
case(0x00) :switch(shuju)
{
case(0x7e):
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0x7d):
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0x7b):
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0x77):
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0x6f):
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0x5f):
{
EA=1;
EX0=1;
IT0=1;
}break;
case(0x3f):
{
EA=1;
EX0=1;
IT0=1;
}break;
default: //时钟正常计时
{
EA=1;
TR0=1;
EX0=0;
}break;
}break;
}
}
}
void inter0() interrupt 0 using 0
{
uchar result,z;
result=shuju;
switch(qxiang)
{
case(0x80): switch(result)
{
case(0xfe) : // if(result==0xfe) //秒调整 +
{
now.second++;
if(now.second>=60)
{
now.second=0;
}
display();
}break;
case(0xfd) : //if(result==0xfd) //分调整 +
{
now.minute++;
if(now.minute>=60)
{
now.minute=0;
}
display();
}break;
case(0xfb) : //if(result==0xfb) //时调整 +
{
now.hour++;
if(now.hour>=24)
{
now.hour=0;
}
display();
}break;
case(0xf7) : // if(result==0xf7) //星期调整 +
{
today.week++;
if(today.week>=8)
{
today.week=1;
}
display();
}break;
case(0xef) : //if(result==0xef) //日期调整 +
{
today.day++;
z = monthday( today.year[1] , today.year[0] );
if((z==1)&&(today.month==2))
{
if(today.day>=30)
today.day=1;
}
else if (today.day>dayofmonth[today.month-1])
today.day=1;
display();
}break;
case(0xdf) : //if(result==0xdf) //月调整 +
{
today.month++;
if(today.month>=13)
{
today.month=1;
}
display();
} break;
case(0xbf) : //if(result==0xbf) //年调整 +
{
today.year[0]=today.year[0]+1;
if(today.year[0]>=100)
{
today.year[0]=0;
today.year[1]=today.year[1]+1;
if(today.year[1]>=100)
{
today.year[1]=0;
}
}
display();
}break;
default: //时钟正常计时
{
EA=1;
TR0=1;
EX0=0;
}break;
}break;
case(0x00): switch(result)
{
case(0x7e): //if(result==0x7f) //秒调整—
{
if(now.second>0)
now.second=now.second-1;
else now.second=59;
display();
}break;
case(0x7d): //if(result==0x7d) //分调整—
{
if(now.minute>0)
now.minute=now.minute-1;
else now.minute=59;
display();
} break;
case(0x7b) : //if(result==0x7b) // 时调整-
{
if(now.hour>0)
now.hour=now.hour-1;
else now.hour=23 ;
display();
}break;
case(0x77) : //if(result==0x77) // 周调整—
{
if(today.week>1)
today.week=today.week-1;
else today.week=7;
display();
}break;
附:http://www.jh-tec.cn/archives/7127