基于51单片机的电子时钟设计源程序.docx
《基于51单片机的电子时钟设计源程序.docx》由会员分享,可在线阅读,更多相关《基于51单片机的电子时钟设计源程序.docx(21页珍藏版)》请在冰豆网上搜索。
基于51单片机的电子时钟设计源程序
#include
unsignedcharDispBuf[6];//时间显示缓冲区
unsignedcharDisdate[6];//日期显示缓冲区
unsignedcharDisSec[6];//秒表缓冲区
struct//设定时间结构体
{
unsignedcharHour;
unsignedcharMin;
unsignedcharSec;
}Time;
struct//设定日期结构体
{
unsignedcharYear;
unsignedcharMonth;
unsignedcharDays;
}Date;
struct//设定毫秒结构体
{
unsignedcharMinite;
unsignedcharSecond;
unsignedcharMilliSec;
}Millisecond;
unsignedcharpoint=0;
unsignedcharpoint1=0;
unsignedcharpoint2=0;
unsignedcharDaymount;
unsignedcharDaymount1;
unsignedcharT0_Int_Times=0;//中断次数计数变量
unsignedcharFlash_flag=0;//闪烁标志,每半秒闪烁
unsignedcharFlash_flag1=0;//闪烁标志,每半秒闪烁
unsignedcharDisPlay_Back=0;//显示缓冲区更新备份,如果显示缓冲区更新则跟闪烁标志不一致
unsignedcharDisPlay_Back1=0;//显示缓冲区更新备份,如果显示缓冲区更新则跟闪烁标志不一致
unsignedchari,j;unsignedcharSetMillisecond;//启动秒表
codeunsignedcharLEDCode[]={0x01,0xd7,0x22,0x82,0xc4,0x88,0x08,0xc1,0x00,0x80};//数码管显示代码
codeunsignedcharErrorLEDCode[]={0x01,0xe7,0x12,0x82,0xc4,0x88,0x08,0xc1,0x00,0x80};//绘制错误图纸的数码管显示代码
voidDisPlayBuf();voidChangeToDispCode();voidChangeToDispCode1();voidchangedate();//调日期
voiddisplaydate();//显示日期
voidmakedays();//确定每个月的日期
voidrunSec();
voiddelay(unsignedinti);//函数声名
sbitP1_0=P1^0;
sbitP1_1=P1^1;
sbitP1_2=P1^2;
//***************************************************
//Init初始化代码
//设定50ms中断一次,注:
在Fosc=6M情况下
//****************************************************
voidInit(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;
}
/******************************延时子程序*********************************************/
voiddelay(unsignedinti)
{
charj;
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;
}
elseif(P1_1==0)
{
switch(point)
{
case0:
Millisecond.Minite=0;
Millisecond.Second=0;
Millisecond.MilliSec=0;
SetMillisecond++;
runSec();
break;
case1:
Time.Hour=(Time.Hour+1)%24;
break;
case2:
Time.Min=(Time.Min+1)%60;
break;
case3:
Time.Sec=(Time.Sec+1)%60;
break;
};
}
elseif(P1_0==0)
{
switch(point)
{
case0:
ChangeToDispCode1();
Disdate[2]=Disdate[2]&0xef;//点亮双点
Disdate[4]=Disdate[4]&0xdf;
displaydate();
delay(2000);
break;
case1:
Time.Hour=(Time.Hour+24-1)%24;
break;
case2:
Time.Min=(Time.Min+60-1)%60;
break;
case3:
Time.Sec=(Time.Sec+60-1)%60;
break;
case4:
changedate();
break;
};
};
};
};
makedays();
}
}
//*****************************************************
//把时间显示缓冲区的内容发到74HC164
//*****************************************************
voidDisPlayBuf(void)
{
unsignedchari;
for(i=0;i<6;i++)
{
SBUF=DispBuf[i];
while(TI==0);//等待发送完毕
TI=0;//把发送完标志清掉以备下次再用
};
}
//*****************************************************
//把日期显示缓冲区的内容发到74HC164
//*****************************************************
voiddisplaydate(void)
{
unsignedchari;
for(i=0;i<6;i++)
{
SBUF=Disdate[i];
while(TI==0);//等待发送完毕
TI=0;//把发送完标志清掉以备下次再用
};
}
//*****************************************************
//把秒表技术显示缓冲区的内容发到74HC164
//*****************************************************
voiddisplaySec(void)
{
unsignedchari;
for(i=0;i<6;i++)
{
SBUF=DisSec[i];
while(TI==0);//等待发送完毕
TI=0;//把发送完标志清掉以备下次再用
};
}
//*******************************************
//把时间转换为可以显示的代码
//*******************************************
voidChangeToDispCode(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];
}
//*******************************************
//把日期转化为现实的数
//*******************************************
voidChangeToDispCode1(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];
}
//*******************************************
//秒表功能
//*******************************************
voidChangeToDispCode2(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[Millisecond.MilliSec/10];
DisSec[5]=LEDCode[Millisecond.MilliSec%10];
}
//******************************************************
//定时器中断
//******************************************************
voidT0_Int(void)interrupt1using1
{
TH0=(65536-5000)/256;//定时器装填
TL0=(65536-5000)%256;
if(SetMillisecond!
=0)
{
Millisecond.MilliSec++;
if(Millisecond.MilliSec>=100)
{
Millisecond.MilliSec=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++;
};
};
};
};
}
}
//****************************************************************
//******************************调节日期***************************
//*****************************************************************
voidchangedate(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;
}
elseif(P1_1==0)
{
switch(point1)
{
case1:
Date.Year++;
break;
case2:
Date.Month++;
if(Date.Month==13)
{
Date.Month=1;
}
break;
case3:
makedays();
Date.Days++;
if(Date.Days>Daymount)
{
Date.Days=1;
}
break;
};
}
elseif(P1_0==0)
{
switch(point1)
{
case1:
Date.Year--;
break;
case2:
Date.Month--;
if(Date.Month<=0)
{
Date.Month=12;
}
break;
case3:
makedays();
Date.Days--;
if(Date.Days<=0)
{
Date.Days=Daymount;
};
break;
};
};
}
if(point1==4)
{
point1=0;
break;
}
}
}
}
//*****************************************************
//***************调日期加时时确定天数*******************
//******************************************************
voidmakedays()
{
switch(Date.Month)
{
case4:
case6:
case9:
case11:
Daymount=30;
break;
case2:
if(Date.Year%4==0)
Daymount=29;
else
Daymount=28;
b