用51单片机做一个电子钟

    学了一个多月51了,终于整了个电子钟出来,个人感觉还是比较有趣的。
    需要注意的是我用的是普中的板子,板子类型不同,io口的功能可能会有所差异。然后我这个k1开关和k2开关是接反了的,原本k1应该是接P3^0,k2接P3^1的,结果我一测试才知道k1接到了P3^1,k2接到P3^0了,不过这不要紧,用sbit定义位变量时注意换一下就可以了。然后大概讲讲功能,用8个数码管显示目前时间和闹铃时间,然后用4个独立按键对目前时间和闹铃时间进行调整(k2是加,k3是减 ,k4是用来停止闹铃的),第一次按k1是对目前时间秒数调整,第2次按k1是对目前时间分钟数调整,第三次按k1是对目前时间小时数调整,第4次按k1是对闹铃秒数调整,第5次按k1是对闹铃时间分钟数调整,第6次按k1是对闹铃秒数调整,第7次按k1是调整完毕,进去非调整状态即实时显示目前时间(不过有点差异,时间走的快了一点)。主要用到了数码管动态显示,独立按键,定时器中断这些。

代码如下:
#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
sbit led=P2^0;
sbit lsa=P2^2;
sbit lsb=P2^3;
sbit lsc=P2^4;
sbit beep=P1^5;
sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;
sbit dian=P0^7;

u8 keyvalue,alarmexist=0;
u8 smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x00};//段选码,分别对应0到无
u16 cnt=0,i=0,j=0,flag=0,time[]={0,0,0,0,0,0,0,0};//只用数码管0,1 3,4 6,7
u16 alarm[]={0,0,0,0,0,0,1,0};
u16*p;


void delay(u16 mmp);
void t0andt1init();
void addproct(int x);						    
void addproca(int x);
void reduceproct(int x);
void reduceproca(int x);
void keyscan();
void jia();
void jian();

void main()
{
  	led=0;
    t0andt1init();
	P0=0x00;
	while(1)
	{   
	    
		if(time[0]==alarm[0]&&time[1]==alarm[1]&&time[3]==alarm[3]&&time[4]==alarm[4]&&time[6]==alarm[6]&&time[7]==alarm[7])//满足条件 蜂鸣器以一定的时间间隔响,只到K4按键并松开,此时数码管任然正常显示当前时间
		{   
			alarmexist=0;
			while(k4)
			{
				beep=~beep;
				delay(25);
				beep=~beep;
				delay(25);
			}
		}
		keyscan();
	}
}
void delay(u16 mmp)
{
	while(mmp--);
}
void t0andt1init()
{
	TMOD=0x11;
	TH0=0xfc;
	TL0=0x67;//赋定时器初始值,定时1ms
	TH1=0xfc;
	TL1=0x67;
	TR0=1;//T0定时器开始定时
	EA=1;
	ET0=1;
	ET1=1;	
}
void addproct(int x)	  //对非调整状态和调整状态的加1处理(仅用于对当前时间)
{
	if(x==0||x==3||x==6)
		if(time[x]==10)
		{
			time[x]=0;
			time[x+1]=time[x+1]+1;
			addproct(x+1);
		}
   
   	if(x==1||x==4)
   		if(time[x]==6)
		{
			time[x]=0;
			time[x+2]=time[x+2]+1;
			addproct(x+2);
		}
	if(time[6]==4&&time[7]==2)
		time[6]=time[7]=0;		
}
void addproca(int x)	  //对调整状态的加1处理(仅用于对闹钟时间)
{
	if(x==0||x==3||x==6)
		if(alarm[x]==10)
		{
			alarm[x]=0;
			alarm[x+1]=alarm[x+1]+1;
			addproca(x+1);
		}
   
   	if(x==1||x==4)
   		if(alarm[x]==6)
		{
			alarm[x]=0;
			alarm[x+2]=alarm[x+2]+1;
			addproca(x+2);
		}
	if(alarm[6]==4&&alarm[7]==2)
		alarm[6]=alarm[7]=0;		
}
void reduceproct(int x) // 对调整状态的减1处理(仅用于对当前时间)
{
	if(time[0]==0&&time[1]==0&&time[3]==0&&time[4]==0&&time[6]==0&&time[7]==0)
	{
		time[0]=time[3]=9;
		time[1]=time[4]=5;
		time[6]=3;
		time[7]=2;
		return ;
	}
	if(x==0||x==3||x==6)
	{
		if(time[x]>=1)
			time[x]=time[x]-1;
		else
		{   
			if(time[7]==0&&x==6)
			{
				time[6]=3;
				time[7]=2;
			}
			else
			{
				time[x]=9;
				reduceproct(x+1);	
			}
		}
		
	}
	else
	{
		if(time[x]>=1)
			time[x]=time[x]-1;
		else
		{
			time[x]=5;
			if(x!=7)
				reduceproct(x+2);
			else
				time[x]=1;
		}
	}
	
}
void reduceproca(int x) // 对调整状态的减1处理(仅用于对闹钟时间)
{
	if(alarm[0]==0&&alarm[1]==0&&alarm[3]==0&&alarm[4]==0&&alarm[6]==0&&alarm[7]==0)
	{
		alarm[0]=alarm[3]=9;
		alarm[1]=alarm[4]=5;
		alarm[6]=3;
		alarm[7]=2;
		return ;
	}
	if(x==0||x==3||x==6)
	{
		if(alarm[x]>=1)
			alarm[x]=alarm[x]-1;
		else
		{   
			if(alarm[7]==0&&x==6)
			{
				alarm[6]=3;
				alarm[7]=2;
			}
			else
			{
				alarm[x]=9;
				reduceproca(x+1);	
			}
		}
		
	}
	else
	{
		if(alarm[x]>=1)
			alarm[x]=alarm[x]-1;
		else
		{
			alarm[x]=5;
			if(x!=7)
				reduceproca(x+2);
			else
				alarm[x]=1;
		}
	}
	
}
void keyscan()
{   
	flag=0;
	keyvalue=0;
    if(k1==0)
	{   
	    TR0=0;//不在显示当前时间
		TR1=1;
	    delay(1000);
		if(k1==0)
		{   
			while(!k1) ;
			delay(1000);
			led=~led;
		    keyvalue++;
		}
		else
			return ;
		
		while(keyvalue!=7)
		{
			if(k1==0)
			{   
			    delay(1000);
				if(k1==0)
				{
					while(!k1) ;
					led=~led;
		            keyvalue++;
					if(keyvalue==4)
						flag=1;
				} 
				
			}	
			if(k2==0)
			{
				delay(1000);
				if(k2==0)
				{
					while(!k2) ;
				 	led=~led;
					jia();
				}
			}
			if(k3==0)
			{
				delay(1000);
				if(k3==0)
				{
					while(!k3) ;
				    led=~led;
					jian();
				}
			}	
		}
		TR0=1;
		TR1=0;
		if(((alarm[6]+alarm[7]*10)*60+alarm[3]+alarm[4]*10)>((time[6]+time[7]*10)*60+time[3]+time[4]*10))//判断闹钟时间是否大于当前时间,
			alarmexist=1;
		else
			alarmexist=0;
		
		
	}
}			
void jia()
{
	switch(keyvalue)
	{
		case 1:time[0]=time[0]+1;addproct(0);break;
		case 2:time[3]=time[3]+1;addproct(3);break;
		case 3:time[6]=time[6]+1;addproct(6);break;
		case 4:alarm[0]=alarm[0]+1;addproca(0);break;
		case 5:alarm[3]=alarm[3]+1;addproca(3);break;
		case 6:alarm[6]=alarm[6]+1;addproca(6);break;
		

	}
}
void jian()
{
	switch(keyvalue)
	{
		case 1:reduceproct(0);break;
		case 2:reduceproct(3);break;
		case 3:reduceproct(6);break;
		case 4:reduceproca(0);break;
		case 5:reduceproca(3);break;
		case 6:reduceproca(6);break;
		

	}
	
}
void Timer0() interrupt 1//非调整时,执行的中断服务程序
{
	TH0=0xfc;
	TL0=0x67;//赋定时器初始值,定时1ms
	cnt++;
	if(1000==cnt)
	{   
		cnt=0;
		time[0]=time[0]+1;
		addproct(0);
	}
	P0=0X00;
	switch(i)
	{	
	    case 0:lsa=0;lsb=0;lsc=0;P0=smgduan[time[0]];dian=(alarmexist==1)?1:0;i++;break;
		case 1:lsa=1;lsb=0;lsc=0;P0=smgduan[time[1]];i++;i++;break;
		case 3:lsa=1;lsb=1;lsc=0;P0=smgduan[time[3]];i++;break;
		case 4:lsa=0;lsb=0;lsc=1;P0=smgduan[time[4]];i++;i++;break;
		case 6:lsa=0;lsb=1;lsc=1;P0=smgduan[time[6]];i++;break;
		case 7:lsa=1;lsb=1;lsc=1;P0=smgduan[time[7]];i=0;break;
	}
}
void Timer1() interrupt 3	//调整时,执行的中断服务程序  ,flag=0显示正在调整的time,为1显示正在调整的alarm
{
    
	TH1=0xfc;
	TL1=0x67;//赋定时器初始值,定时1ms
    if(flag==0)
		p=time;
	else
		p=alarm;
	P0=0X00;
	switch(j)
	{	
	    case 0:lsa=0;lsb=0;lsc=0;P0=smgduan[p[0]];j++;break;
		case 1:lsa=1;lsb=0;lsc=0;P0=smgduan[p[1]];j++;j++;break;
		case 3:lsa=1;lsb=1;lsc=0;P0=smgduan[p[3]];j++;break;
		case 4:lsa=0;lsb=0;lsc=1;P0=smgduan[p[4]];j++;j++;break;
		case 6:lsa=0;lsb=1;lsc=1;P0=smgduan[p[6]];j++;break;
		case 7:lsa=1;lsb=1;lsc=1;P0=smgduan[p[7]];j=0;break;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40642465/article/details/80573832