1. 程式人生 > >基於Proteus學習微控制器系列(五)——定時器實現電子錶

基於Proteus學習微控制器系列(五)——定時器實現電子錶

  專案下載

    點選下載

1. 電路圖

  2. 程式

主函式

#include<reg51.h>
#include<DEFINE.c>
#include<KEY.c>
#include<DISPLAY.c>
void timer_isr()interrupt 1			  //中斷服務函式
{
	TL0 = (65536-2000) %256;			  //TL0重置函式
	TH0 = (65536-2000)/256;			  //TH0重置函式
	cp++;
	if(cp>=250)       //0.5s
	{
		cp1++;
		cp = 0;
		flash = ~flash;        //0.5s  - 閃爍
		if(cp1>=2)    //1s
		{
			if(mode==0)		   //調整時,時間停止
			sec++;
			cp1 = 0;
			if(sec>=60)     //1min
			{
				min++;
				sec = 0;
				if(min>60)	 //1h
				{
					hour++;
					min = 0;
					if(hour>=24)hour = 0;
				}
			}
		}
	}
	P0 = 0xff;    //消隱
	switch(mode)
	{
		case 0:dis_play0();break;  //正常
		case 1:dis_play1();break;  //調時
		case 2:dis_play2();break;  //調分
		case 3:dis_play3();break;  //調秒
		case 4:dis_play4();break;  //調鬧時
		case 5:dis_play5();break;  //調鬧分
	}
	i++;
	if(i>=8)i = 0;	
}
void timer0_init()				   //中斷初始化函式
{
	TMOD = 0x01;				  //方式一
	TL0 = (65536-2000)%256;		  //TL0 預置,65536十六進位制低8位。
	TH0 = (65536-2000)/256;		  //TH0 預置,65536十六進位制高8位。
	EA = 1;							//CPU中斷開放 ,總中斷開啟
	ET0 = 1;						//定時計數器T0的溢位終端控制位,T0中斷開啟
	TR0 = 1;						//定時計數器T0的啟停控制位,啟動T0
}
void main()
{
	timer0_init();				   //timer0初始化,為中斷做準備
	while(1)
	{
		key();
		if(hour == hour_n && min == min_n)	   //鬧鐘到時間,蜂鳴器響
		{
			P3_2 = !P3_2;
			delay(50);
		}
	}
 }

定義

#define uchar unsigned char;
#define uint unsigned int;
sbit key_set = P2^0;
sbit key_up = P2^1;
sbit key_down = P2^2;
sbit P3_0 = P3^0;
sbit P3_2 = P3^2; //蜂鳴器
sbit P2_4 = P2^4;
uchar sec = 45,min = 12,hour;
uchar sec_t,min_t,hour_t;
uchar min_n = 13,hour_n;
uchar cp,cp1;
uchar flash,mode,i;
code uchar seven_seg[] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
			0x82,0xf8,0x80,0x90};


按鍵函式

void delay(unsigned int x)	//延時函式
{
	while(x--);
}
void key()				   //按鍵函式
{
	P2_4 = 0;
	if(key_set==0)		   //如果調整按鍵按下
	{
		delay(300);		   //消抖
		if(key_set==0)	   //如果調整按鍵真的按下
		{
			while(key_set==0);
			mode++;
			if(mode>=6)mode = 0;   //mode=0,退出調整
			hour_t = hour;
			min_t = min;
			sec_t = sec;
		}
	}
	if(key_up==0)				  //如果增加按鍵按下
	{
		delay(300);				  //消抖
		if(key_up==0)			  //如果增加按鍵真的按下
		{
			while(key_up==0);
			if(mode==1)hour_t++;if(hour_t>24)hour_t = 23;hour = hour_t;
			if(mode==2)min_t++;if(min_t>60)min_t = 59;min=min_t;
			if(mode==3)sec_t++;if(sec_t>60)sec_t = 59;sec = sec_t;
			if(mode==4)hour_n++;if(hour_n>24)hour_n = 23;
			if(mode==5)min_n++;if(min_n>60)min_n = 59;

		}
	}
	if(key_down==0)				 //如果減小按鍵按下
	{							 
		delay(300);				 //消抖
		if(key_down==0)			 //如果減小按鍵真的按下
		{
			while(key_down==0);
			if(mode==1)hour_t--;if(hour_t<0)hour_t = 0;hour = hour_t;
			if(mode==2)min_t--;if(min_t<0)min_t = 0;min=min_t;
			if(mode==3)sec_t--;if(sec_t<0)sec_t = 0;sec = sec_t;
			if(mode==4)hour_n--;if(hour_n<0)hour_n = 0;
			if(mode==5)min_n--;if(min_n<0)min_n = 0;

		}
	}
}

顯示函式

void display(unsigned char x1,x2)
{
	P3_0 = 0;	  //鎖存器關
	P0 = x1;	  //輸入位選			 
	P3_0 = 1;	  //鎖存器開
	P3_0 = 0;	  //鎖存器關
	P0 = x2;	  //輸入段選		
}
void dis_play0()			  //mode = 0 正常  顯示
{
	switch(i)
	{
		case 0:display(0x01,seven_seg[sec%10]);break;	  //顯示秒個位
		case 1:display(0x02,seven_seg[sec/10]);break;	  //顯示秒十位
		case 2:display(0x04,0xbf|flash);break;			  //顯示 -	  閃爍
		case 3:display(0x08,seven_seg[min%10]);break;	  //顯示分個位
		case 4:display(0x10,seven_seg[min/10]);break;	  //顯示分十位
		case 5:display(0x20,0xbf|flash);break;			  //顯示 -    閃爍
		case 6:display(0x40,seven_seg[hour%10]);break;	  //顯示時個位
		case 7:display(0x80,seven_seg[hour/10]);break;	  //顯示時十位
	}
}
void dis_play1()			  //mode = 1 調時
{
	switch(i)
	{
		case 0:display(0x01,seven_seg[sec_t%10]);break;	  //顯示調秒個位
		case 1:display(0x02,seven_seg[sec_t/10]);break;	  //顯示調秒十位
		case 2:display(0x04,0xbf);break;				  //顯示 -
		case 3:display(0x08,seven_seg[min_t%10]);break;	  //顯示調分個位
		case 4:display(0x10,seven_seg[min_t/10]);break;	  //顯示調分十位
		case 5:display(0x20,0xbf);break;				  //顯示 -
		case 6:display(0x40,seven_seg[hour_t%10]|flash);break;	 //顯示調時個位	   閃爍
		case 7:display(0x80,seven_seg[hour_t/10]|flash);break;	 //顯示調時十位	   閃爍
	}
}
void dis_play2()			  //mode = 2 調分
{
	switch(i)
	{
		case 0:display(0x01,seven_seg[sec_t%10]);break;	  //顯示調秒個位
		case 1:display(0x02,seven_seg[sec_t/10]);break;	  //顯示調秒十位
		case 2:display(0x04,0xbf);break;				  //顯示  -
		case 3:display(0x08,seven_seg[min_t%10]|flash);break;	  //顯示調分個位   閃爍
		case 4:display(0x10,seven_seg[min_t/10]|flash);break;	  //顯示調分十位   閃爍
		case 5:display(0x20,0xbf);break;						  //顯示 -
		case 6:display(0x40,seven_seg[hour_t%10]);break;		  //顯示調時個位
		case 7:display(0x80,seven_seg[hour_t/10]);break;		  //顯示調時十位
	}
}
void dis_play3()			  //mode = 3 調秒
{
	switch(i)
	{
		case 0:display(0x01,seven_seg[sec_t%10]|flash);break;	  //顯示調秒個位  閃爍
		case 1:display(0x02,seven_seg[sec_t/10]|flash);break;	  //顯示調秒十位  閃爍
		case 2:display(0x04,0xbf);break;						  //顯示 -
		case 3:display(0x08,seven_seg[min_t%10]);break;			  //顯示調分個位
		case 4:display(0x10,seven_seg[min_t/10]);break;			  //顯示調分十位
		case 5:display(0x20,0xbf);break;						  //顯示 -
		case 6:display(0x40,seven_seg[hour_t%10]);break;		  //顯示調時個位
		case 7:display(0x80,seven_seg[hour_t/10]);break;		  //顯示調時十位
	}
}		
void dis_play4()			  //mode = 4 調鬧時
{
	switch(i)
	{
		case 0:display(0x01,0xbf);break;						  //顯示 -
		case 1:display(0x02,0xbf);break;						  //顯示 -
		case 2:display(0x04,0xbf);break;						  //顯示 -
		case 3:display(0x08,seven_seg[min_n%10]);break;			  //顯示鬧分個位
		case 4:display(0x10,seven_seg[min_n/10]);break;			  //顯示鬧分十位
		case 5:display(0x20,0xbf);break;						  //顯示 -
		case 6:display(0x40,seven_seg[hour_n%10]|flash);break;	  //顯示鬧時個位    閃爍
		case 7:display(0x80,seven_seg[hour_n/10]|flash);break;	  //顯示鬧時十位    閃爍
	}
}
void dis_play5()			  //mode = 5 調鬧分
{
	switch(i)
	{
		case 0:display(0x01,0xbf);break;						  //顯示 -
		case 1:display(0x02,0xbf);break;						  //顯示 -
		case 2:display(0x04,0xbf);break;						  //顯示 -
		case 3:display(0x08,seven_seg[min_n%10]|flash);break;	  //顯示鬧分個位    閃爍
		case 4:display(0x10,seven_seg[min_n/10]|flash);break;	  //顯示鬧分十位	閃爍
		case 5:display(0x20,0xbf);break;						  //顯示 -
		case 6:display(0x40,seven_seg[hour_n%10]);break;		  //顯示鬧時個位
		case 7:display(0x80,seven_seg[hour_n/10]);break;		  //顯示鬧時十位
	}
}