1. 程式人生 > >用51微控制器做一個電子鐘

用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;
	}
}