#include<reg51.h>unsigned char DispBuf[6]; //时间显示缓冲区unsigned char Disdate[6]; //日期显示缓冲区unsigned char DisSec[6]; //秒表缓冲区struct //设定时间结构体{unsigned char Hour;unsigned char Min;unsigned char Sec;}Time;struct //设定日期结构体{unsigned char Year;unsigned char Month;unsigned char Days;}Date;struct //设定毫秒结构体{unsigned char Minite;unsigned char Second;unsigned char MilliSec;}Millisecond;unsigned char point=0;unsigned char point1=0;unsigned char point2=0;unsigned char Daymount;unsigned char Daymount1;unsigned char T0_Int_Times=0; //中断次数计数变量unsigned char Flash_flag=0; //闪烁标志,每半秒闪烁unsigned char Flash_flag1=0; //闪烁标志,每半秒闪烁unsigned char DisPlay_Back=0; //显示缓冲区更新备份,如果显示缓冲区更新则跟闪烁标志不一致unsigned char DisPlay_Back1=0; //显示缓冲区更新备份,如果显示缓冲区更新则跟闪烁标志不一致unsigned char i,j; unsigned char SetMillisecond; //启动秒表code unsigned char LEDCode[]={0x01,0xd7,0x22,0x82,0xc4,0x88,0x08,0xc1,0x00,0x80}; //数码管显示代码code unsigned char ErrorLEDCode[]={0x01,0xe7,0x12,0x82,0xc4,0x88,0x08,0xc1,0x00,0x80};//绘制错误图纸的数码管显示代码void DisPlayBuf(); void ChangeToDispCode(); void ChangeToDispCode1(); void changedate(); // 调日期void displaydate(); // 显示日期void makedays(); //确定每个月的日期void runSec();void delay(unsigned int i); //函数声名sbit P1_0=P1^0;sbit P1_1=P1^1;sbit P1_2=P1^2;//***************************************************// Init 初始化代码// 设定50ms中断一次,注:在Fosc=6M情况下//****************************************************void Init(void){Date.Year=10;Date.Month=12;Date.Days=25;Time.Hour=12;Time.Min=0;Time.Sec=0;TMOD=0x01;TH0=(65536-5000)/256;TL0=(65536-5000)%256;TR0=1;ET0=1;EA=1;}/******************************延时子程序*********************************************/void delay(unsigned int i){char j;for(i; i > 0; i--)for(j = 200; j > 0; j--);}//*******************************************// 主程序//*******************************************main(){Init(); //初始化for(;;){if(DisPlay_Back!=Flash_flag) //是否显示?{DisPlay_Back=Flash_flag; //显示过后要半秒后再显示ChangeToDispCode(); //转化时间为可显示代码if(Flash_flag) //更新双点闪烁{DispBuf[2]=DispBuf[2]|0x10; //双点熄灭DispBuf[4]=DispBuf[4]|0x20;}else{DispBuf[2]=DispBuf[2]&0xef; //点亮双点DispBuf[4]=DispBuf[4]&0xdf;};if(Flash_flag & point==1) //更新小时{DispBuf[0]=DispBuf[0]|0xff; //小时熄灭DispBuf[1]=DispBuf[1]|0xff;}else{DispBuf[0]=DispBuf[0]&0xff; //小时点亮DispBuf[1]=DispBuf[1]&0xff;};if(Flash_flag & point==2) //更新分钟{DispBuf[2]=DispBuf[2]|0xff; //分钟熄灭DispBuf[3]=DispBuf[3]|0xff;}else{DispBuf[2]=DispBuf[2]&0xff; //分钟点亮DispBuf[3]=DispBuf[3]&0xff;};if(Flash_flag & point==3) //更新秒钟{DispBuf[4]=DispBuf[4]|0xff; //秒钟熄灭DispBuf[5]=DispBuf[5]|0xff;}else{DispBuf[4]=DispBuf[4]&0xff; //秒钟点亮DispBuf[5]=DispBuf[5]&0xff;};DisPlayBuf();//显示}if((P1&0x07)!=0x7) //按键处理模块模块{delay(250);if((P1&0x07)!=0x7){if(P1_2==0){point=(point+1)%5;}else if (P1_1==0){switch(point){case 0: Millisecond.Minite=0;Millisecond.Second=0;liSec=0;SetMillisecond++;runSec();break;case 1:Time.Hour=( Time.Hour+1)%24;break;case 2:Time.Min=( Time.Min+1)%60;break;case 3:Time.Sec=( Time.Sec+1)%60;break;};}else if (P1_0==0){switch(point){case 0:ChangeToDispCode1();Disdate[2]=Disdate[2]&0xef; //点亮双点Disdate[4]=Disdate[4]&0xdf;displaydate();delay(2000);break;case 1:Time.Hour=( Time.Hour+24-1)%24;break;case 2:Time.Min=( Time.Min+60-1)%60;break;case 3:Time.Sec=( Time.Sec+60-1)%60;break;case 4:changedate();break;};};};};makedays();}}//***************************************************** // 把时间显示缓冲区的内容发到74HC164//***************************************************** void DisPlayBuf(void){unsigned char i;for(i=0;i<6;i++){SBUF=DispBuf[i];while(TI==0); //等待发送完毕TI=0; //把发送完标志清掉以备下次再用};}//***************************************************** // 把日期显示缓冲区的内容发到74HC164//***************************************************** void displaydate(void){unsigned char i;for(i=0;i<6;i++){SBUF=Disdate[i];while(TI==0); //等待发送完毕TI=0; //把发送完标志清掉以备下次再用};}//***************************************************** // 把秒表技术显示缓冲区的内容发到74HC164//***************************************************** void displaySec(void){unsigned char i;for(i=0;i<6;i++){SBUF=DisSec[i];while(TI==0); //等待发送完毕TI=0; //把发送完标志清掉以备下次再用};}//*******************************************// 把时间转换为可以显示的代码//*******************************************void ChangeToDispCode(void){DispBuf[0]=LEDCode[Time.Hour/10];DispBuf[1]=LEDCode[Time.Hour%10];DispBuf[2]=LEDCode[Time.Min/10];DispBuf[3]=LEDCode[Time.Min%10];DispBuf[4]=ErrorLEDCode[Time.Sec/10];DispBuf[5]=LEDCode[Time.Sec%10];}//*******************************************// 把日期转化为现实的数//*******************************************void ChangeToDispCode1(void){Disdate[0]=LEDCode[Date.Year/10];Disdate[1]=LEDCode[Date.Year%10];Disdate[2]=LEDCode[Date.Month/10];Disdate[3]=LEDCode[Date.Month%10];Disdate[4]=ErrorLEDCode[ Date.Days/10];Disdate[5]=LEDCode[Date.Days%10];}//*******************************************// 秒表功能//*******************************************void ChangeToDispCode2(void){DisSec[0]=LEDCode[Millisecond.Minite/10];DisSec[1]=LEDCode[Millisecond.Minite%10];DisSec[2]=LEDCode[Millisecond.Second/10];DisSec[3]=LEDCode[Millisecond.Second%10];DisSec[4]=ErrorLEDCode[ liSec/10];DisSec[5]=LEDCode[liSec%10];}//******************************************************// 定时器中断//******************************************************void T0_Int(void) interrupt 1 using 1{TH0=(65536-5000)/256; //定时器装填TL0=(65536-5000)%256;if(SetMillisecond!=0){liSec++;if(liSec>=100){liSec=0;Millisecond.Second++;if(Millisecond.Second>=60){Millisecond.Second=0;Millisecond.Minite++;if(Millisecond.Minite>=60)Millisecond.Minite=0;}}}T0_Int_Times++; //中断次数加if(T0_Int_Times>=50) //每半秒更新闪烁标志{Flash_flag =1;Flash_flag1 =1;}else{Flash_flag =0;Flash_flag1 =0;};if(T0_Int_Times>=100) //如果中断10次为1秒的时间开始更新时、分、秒{T0_Int_Times=0;Time.Sec++;if(Time.Sec>=60){Time.Sec=0;Time.Min++;if(Time.Min>=60){Time.Min=0;Time.Hour=(Time.Hour+1)%24;if(Time.Hour>=24){Time.Hour=0;Date.Days++;if( Date.Days >Daymount){Date.Days=1;Date.Month++;if(Date.Month>12)Date.Month=1;Date.Year++;};};};};}}//**************************************************************** //******************************调节日期*************************** //***************************************************************** void changedate(void){while(1){if(DisPlay_Back1!=Flash_flag1) //是否显示?{DisPlay_Back1=Flash_flag1; //显示过后要半秒后再显示ChangeToDispCode1(); //转化时间为可显示代码if(Flash_flag1) //更新双点闪烁{Disdate[2]=Disdate[2]|0x10; //双点熄灭Disdate[4]=Disdate[4]|0x20;}else{Disdate[2]=Disdate[2]&0xef; //点亮双点Disdate[4]=Disdate[4]&0xdf;};if(Flash_flag1& point1==1) //更新年{Disdate[0]=Disdate[0]|0xff; //年熄灭Disdate[1]=Disdate[1]|0xff;}else{Disdate[0]=Disdate[0]&0xff; //年点亮Disdate[1]=Disdate[1]&0xff;};if(Flash_flag1 & point1==2) //更新月{Disdate[2]=Disdate[2]|0xff; //月熄灭Disdate[3]=Disdate[3]|0xff;}else{Disdate[2]=Disdate[2]&0xff; //月点亮Disdate[3]=Disdate[3]&0xff;};if(Flash_flag1 & point1==3) //更新天{Disdate[4]=Disdate[4]|0xff; //天熄灭Disdate[5]=Disdate[5]|0xff;}else{Disdate[4]=Disdate[4]&0xff; //天点亮Disdate[5]=Disdate[5]&0xff;};displaydate();}if((P1&0x07)!=0x7) //**********按键处理模块******* {delay(250);if((P1&0x07)!=0x7){if(P1_2==0){point1=(point1+1)%5;}else if (P1_1==0){switch(point1){case 1:Date.Year++;break;case 2:Date.Month++;if( Date.Month==13){Date.Month=1;}break;case 3:makedays();Date.Days++;if(Date.Days>Daymount){Date.Days=1;}break;};}else if (P1_0==0){switch(point1){case 1:Date.Year--;break;case 2:Date.Month--;if( Date.Month<=0){Date.Month=12;}break;case 3:makedays();Date.Days--;if(Date.Days<=0){Date.Days=Daymount;};break;};};}if(point1==4){point1=0;break;}}}}//***************************************************** //***************调日期加时时确定天数******************* //****************************************************** void makedays(){switch (Date.Month){case 4:case 6:case 9:case 11:Daymount=30;break;case 2:if(Date.Year%4==0)Daymount=29;elseDaymount=28;break;default: Daymount=31;break;}}void runSec(){while(1){if(DisPlay_Back!=Flash_flag) //是否显示?{DisPlay_Back=Flash_flag; //显示过后要半秒后再显示ChangeToDispCode2(); //转化时间为可显示代码if(Flash_flag) //更新双点闪烁{DisSec[2]=DisSec[2]|0x10; //双点熄灭DisSec[4]=DisSec[4]|0x20;}else{DisSec[2]=DisSec[2]&0xef; //点亮双点DisSec[4]=DisSec[4]&0xdf;};displaySec();}if((P1&0x07)!=0x7) //按键处理模块模块{delay(250);if((P1&0x07)!=0x7){if(P1_2==0){break;}else if (P1_1==0){point2=( point2+1)%3;switch( point2-1){case 0:SetMillisecond=0;break;case 1: point2=point2-2;SetMillisecond=1;break;}}else if(P1_0==0){SetMillisecond=0;Millisecond.Minite=0;Millisecond.Second=0;liSec=0;SetMillisecond=1;}}}} }。