STC89C52实现时钟功能

注意:本程序仅供参考交流,切莫抄袭!

实验芯片:STC89C52

实验电路板:铁牛单片机电路板

如图:

实现功能:

1、时钟功能,可调整时间,调整位闪烁,到点蜂鸣器发出一声。

2、秒表功能,可开始,暂停,继续,清零。

3、闹钟功能,可调整,到时间蜂鸣器持续发声

代码如下:

/*************************************************************************************/
/********************程序名称:时钟芯片***********************************************/
/********************作者:pchospitalcjk*****************************************************/
/********************完成时间:2012年6月6日*******************************************/
/*************************************************************************************/
/*电子时钟程序,以HH-MM-SS的格式显示时间,并带有时间调校功能,调教时被调校位会闪烁,
带有秒表功能,可以开始,暂停,清零,带有闹钟功能,闹钟可设定,用蜂鸣器进行提醒。*/
#include
#define uchar unsigned char
#define uint unsigned int
char code duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00};
char code wei[]={0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7};	
uchar j,i,n,ge,shi,bai,qian,wang,shiwang;
uint number;                                    //时钟中断计数标志位
char h_num,m_num,s_num,Nh_num,Nm_num,Ns_num;
char h_shi,h_ge,m_shi,m_ge,s_shi,s_ge;
uchar mode;									 //mode为时间选位,mode1为闹钟时间选位
bit fan,mb,nz,sy;					 //fan标志当前闪烁数码管显示状态,mb标志当前是否是秒表状态,clm标志按钮一再秒表状态按下,nz为闹钟打开标志位,nz1为界面标志位。
sbit fm=P3^4;
sbit key1 = P3^2;							//调校按钮
sbit key2 = P3^3;							//调校选位按钮
sbit key3 = P1^0;							//进入秒表模式
sbit key4 = P1^1;							//打开或关闭闹钟			
void delay(uchar);
void disp(char,char,char,char,char,char);
void init0();
void init1();
void time_out();
void scankey();
void click1();
void clock();
void stopwatch();

/************主函数***************/
void main()
{
	mb=0;								   //将秒表状态为0
	nz=0;								   //闹钟状态为0
	init0();							   //初始化时钟中断0寄存器变量
	init1();							   //初始化时钟中断1寄存器变量
	mode = 0;							   	//将调校模式置为0
	s_num = 55;							  	//初始化时钟显示时间
	m_num = 59;
	h_num = 10;
	Ns_num = 5;								//初始化闹钟显示时间			   
	Nm_num = 0;
	Nh_num = 11;
	 TR1 = 0;
	while(1)
	{	
		 	
		TR0 = 1;							 //开启定时器0
		if(sy==1)							 //检测声音标志位是否为1
		{
			fm=0;							 //响蜂鸣器
			delay(10);
			fm=1;
		}

		 scankey();											  //键盘扫描		                                    //定时中断0关闭
		stopwatch();								  //秒表状态函数		
		time_out();							 	  //时钟状态函数
		clock();								  //闹钟扫描函数
	

		 
	}	
}

/************************显示函数****************************/
void disp(char h_shi,char h_ge,char m_shi,char m_ge,char s_shi,char s_ge)
{
	
	P2 = duan[h_shi];
	P1 = wei[0];
	delay(5);
	
	P2 = duan[h_ge];
	P1 = wei[1];
	delay(5);
	
	P2 = duan[10];
	P1 = wei[2];
	delay(5);

	
	
	P2=duan[m_shi];
	P1=wei[3];		
	delay(5);

	P2=duan[m_ge];
	P1=wei[4];		
	delay(5);
	
	P2=duan[10];
	P1=wei[5];		
	delay(5);

	
	P2=duan[s_shi];
	P1=wei[6];		
	delay(5);

	P2=duan[s_ge];
	P1=wei[7];		
	delay(5);

}

/*******************模糊延时函数***********************/ 
void delay(uchar x)
{

	char a,b;
	for(a=x;a>0;a--)
			for(b=110;b>0;b--);
}

  /********************定时器中断0*************************/
 void init0()
{
	EA=1;						
	ET0=1;					
	TMOD=0x11;					
	TH0=0x4c;		
	TL0=0x00;
}

/***********************定时中断1****************************/
 void init1()
{						
	ET1=1;										
	TH0=0x4c;
	TL0=0x00;
}	 

/************************时钟调用函数*******************************/
void time_out()						
{
	if(j>=20)					   //如果到1S
		{
			fan = ~fan;				//数码管亮暗交叉显示标志位
			j=0;					//时钟中断0技术标志位清零
			if(s_num>58)			//如果秒显示到59
			{
				s_num = -1;
				if(m_num>58)	   //如果分显示到59
				{
					m_num = -1;
					if(h_num>23)	//如果小时显示到23
						{
						h_num = -1;
						}
						h_num++;
					    fm=0;		//到整点后蜂鸣器会响一下
					    delay(50);
					    fm=1;
					
					
				}
				m_num++;
			}
				s_num++;
				if(h_num>23)		   //小时手工调校到23时
				h_num = 0;
				if(m_num>59)		  //分钟手工调校到59
				m_num = 0;
		if(nz == 1)					  //如果在闹钟显示模式下
		{
			h_shi=Nh_num/10;					
			h_ge =Nh_num%10;			
			m_shi=Nm_num/10;					
			m_ge =Nm_num%10;	
			s_shi=Ns_num/10;					
			s_ge =Ns_num%10;	
		}
		if(nz == 0)					  //如果在秒表显示模式下
		{
			h_shi=h_num/10;					
			h_ge =h_num%10;			
			m_shi=m_num/10;					
			m_ge =m_num%10;	
			s_shi=s_num/10;					
			s_ge =s_num%10;
		}
		if(mode==1)									 //如果选中个位
				{
					if(fan==1)						//如果闪烁标志1位为1
					{
						s_shi = 11;				   //让个位数码管不亮
						s_ge  = 11;
					 }
					 s_shi = s_shi;				   //让数码管显示数字
					 s_ge = s_ge;
				}	
		if(mode==2)										  //如果选中十位
				{
					if(fan==1)							  
					{
						m_shi = 11;					//让十位数码管不亮
						m_ge  = 11;
					 }
					 m_shi = m_shi;
					 m_ge = m_ge;
				}
		if(mode==3)
				{
					if(fan==1)
					{
						h_shi = 11;					//让百位数码管不亮
						h_ge  = 11;
					 }
					 h_shi = h_shi;
					 h_ge = h_ge;
				}								
		
		}
		if (mb == 0)
		disp(h_shi,h_ge,m_shi,m_ge,s_shi,s_ge);
}

/**********************秒表状态函数*******************************/
void stopwatch()											 //秒表调用函数
{
	
 	if(i>=2)											 //如果到0.1秒
		{
			i=0;
			
			if(number==999999)							//如果计数到最大,就清0。
				number=0;
			number++;
			
		} 
		
		
		shiwang=number%100000/10000;
		wang=number%10000/1000;					//求千位的值。这个不难理解吧。不会的翻C语言的书
		qian=number%1000/100;				//求百位的值。
		bai=number%1000%100/10;				//求十位的值。
		shi=number%10;
		ge=0;						 	//求个位的值
		if(mb == 1)						//如果当前为秒表模式,则在数码管显示秒表计数
		disp(shiwang,wang,qian,bai,shi,ge);	
									   		
	  	
}	  

/*********************键盘扫描函数***********************/
void scankey()						
{
	if(key2 == 0)					   //按键二按下
	{
		delay(10);
		if(key2 == 0)
		{
			if(mb ==0)						 //如果不在秒表模式下
			{
				mode++;						 //数码管选择位增加
				if(mode>3)						 //数码管选择位超过最大值,就返回数码管未选位模式
				mode = 0;					 
			}
			if(mb == 1){					 //如果在秒表模式下
				number=0;					 //计数清零
			}
			
			while(!key2);	
		}
	}
	if(key1 == 0)
	{
		delay(10);
							    //将声音关闭
		if(key1 == 0)
		{ 
		 sy = 0;	
		if(mb==1)						 //秒表状态
		 TR1 = ~TR1;					 //打开或关闭计数器1
		 if(mb==0)						  //时钟状态
		 click1();								  //时间选位调整
		while(!key1);
		
											
		}
	}
	if(key3 == 0)
	{
		delay(10);
		if(key3 == 0)
		{
			
			mb = ~mb;					  //将秒表标志位取
										  
			while(!key3);
		}
	}
	if(key4 == 0)
	{
		delay(10);
		if(key4 == 0)
		{
			nz = ~nz;					 //闹钟模式转换
			while(!key4);				 //闹钟界面标志位置反向结果
		}
	}
}		 

/*******************数码管选位函数**********************/
void click1(){							 
	  switch(mode)
	  {
	  	case 1:	 
			   if(nz==0)
				s_num++;
				if(nz==1)
				Ns_num++;
				 break;

		case 2:	
				 if(nz==0)
				 m_num++;
				 if(nz==1)
				 Nm_num++;
				 break;

		case 3:	
		 		if(nz==0)
				h_num++;
				if(nz==1)
				 Nh_num++;
		         break;
	  }
}						

/******************闹钟计算函数*********************/
void clock()
{
	 if(h_num-Nh_num==0&m_num-Nm_num==0&s_num-Ns_num==0)
	 sy = 1;
}

/*******************定时中断1(控制时钟)********************/
void time()interrupt 1 				
{
	TH0=0x4c;					//因为晶振用的是11.0592MHZ,定义初值15ms.
	TL0=0x00;
	j++;
		
}

/****************定时中断1(控制秒表)******************/
void time1()interrupt 3
{
	TH0=0x4c;					//因为晶振用的是11.0592MHZ。在取初值时,大概定义为一个中断为50MS
	TL0=0x00;
	i++;
	n++;	
}


 

你可能感兴趣的:(单片机)