石头

深入浅出玩转51单片机——学习笔记:数码管时间显示+调时功能

0
阅读(3963)
/**********************************************
实现功能:数码管时间显示+调时功能(按键只具备单击功能)
          时间初始值:12:34:56
	  Key1未按下,Key2、Key3按下无效
          当Key1第一次按下,可以调整秒时间(Key2按下,秒加1;Key3按下,秒减1)
          当Key1第二次按下,可以调整分时间(Key2按下,分加1;Key3按下,分减1)
	  当Key1第三次按下,可以调整时时间(Key2按下,时加1;Key3按下,时减1)
	  当Key1第四次按下,时间正常运行
硬件平台:基于MGMC-V1.0实验板
晶振频率:11.0592Mhz
时间:2014年5月16日
***********************************************/

#include<reg52.h>

typedef unsigned char uint8;
typedef unsigned int  uint16;

sbit We_En = P1^6;		 //定义数码管位选
sbit Du_En = P1^7;		 //定义数码管段选

uint8 Key_Return = 0;	 //返回的按键键值
uint8 j = 0;
sbit Key1 = P3^4;
sbit Key2 = P3^5;
sbit Key3 = P3^6;
#define Initial_State 0   //按键初始状态 
#define Affirm_State  1   //按键消抖状态
#define Signel_State  2   //按键松手确认状态


uint8 Bit_Tab[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};	//数码管位选
uint8 SEG_Tab[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,	 
                          0x7f,0x6f};		                    //数码管段选
char time[3];
uint8 Dis_Buff[6];
uint8 We_Cnt = 0;
uint8 time_2ms_ok = 0;		     //2ms时间到标志位
uint8 time_1s_ok = 0;		     //1s时间到标志位
uint8 time_10ms_ok = 0;		     //10ms时间到标志位
uint16 i = 0;

void initial_myself();			 //上电初始化
void initial_peripheral();		 //外围设备初始化
void Dleay_Ms(uint16 z);
void Dis_Buffer();				 //时间分离函数
void SEG_Display();				 //数码管刷新函数
void Time_Service();			 //时间计时函数
char Key_Scan();				 //按键扫描函数
void Key_Service();				 //按键调整时间函数

void main()
{
	initial_myself();			//上电初始化
	Dleay_Ms(10);
    initial_peripheral();		//外围设备初始化
	time[0] = 56;
	time[1]	= 34;
	time[2]	= 12;		 //设置时间为:12:34:56
	while(1)
	{
		if(1 == time_10ms_ok)  //10ms时间到
		{
		  time_10ms_ok = 0;
		  Key_Scan();		   //按键扫描
		}
		Dis_Buffer();		//时间分离函数
		SEG_Display();		//数码管刷新函数
		Time_Service();		//时间计时函数
		Key_Service();		//按键调整时间函数
	}
}

void Time_Service()		 //时间计时函数
{
    if(1 == time_1s_ok)	 //1s时间到
	{
		time_1s_ok = 0;
		if(++time[0] >= 60)
		{
		    time[0] = 0;
			if(++time[1] >= 60)
			{
			    time[1] = 0;
				if(++time[2] >= 24)
				{
				    time[2] = 0;
				}
			}
		}
	}
}

void SEG_Display()	 //数码管刷新函数
{
    if(1 == time_2ms_ok)    //2ms时间到
	{
		time_2ms_ok = 0;
		switch(We_Cnt)
		{
		    case 0:		 //刷新第一个数码管
			{
				Du_En = 1; P0 = 0x00; Du_En = 0;
				We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
				P0 = 0x00;
				Du_En = 1; P0 = SEG_Tab[Dis_Buff[0]]; Du_En = 0;
				We_Cnt++;
			}
			break;

			case 1:		 //刷新第二个数码管
			{
				Du_En = 1; P0 = 0x00; Du_En = 0;
				We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
				P0 = 0x00;
				Du_En = 1; P0 = SEG_Tab[Dis_Buff[1]]; Du_En = 0;
				We_Cnt++;
			}
			break;

			case 2:		 //刷新第三个数码管
			{
				Du_En = 1; P0 = 0x00; Du_En = 0;
				We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
				P0 = 0x00;
				Du_En = 1; P0 = 0x40; Du_En = 0;
				We_Cnt++;
			}
			break;

			case 3:		 //刷新第四个数码管
			{
				Du_En = 1; P0 = 0x00; Du_En = 0;
				We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
				P0 = 0x00;
				Du_En = 1; P0 = SEG_Tab[Dis_Buff[2]]; Du_En = 0;
				We_Cnt++;
			}
			break;

			case 4:		 //刷新第五个数码管
			{
				Du_En = 1; P0 = 0x00; Du_En = 0;
				We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
				P0 = 0x00;
				Du_En = 1; P0 = SEG_Tab[Dis_Buff[3]]; Du_En = 0;
				We_Cnt++;
			}
			break;

			case 5:		 //刷新第六个数码管
			{
				Du_En = 1; P0 = 0x00; Du_En = 0;
				We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
				P0 = 0x00;
				Du_En = 1; P0 = 0x40; Du_En = 0;
				We_Cnt++;
			}
			break;

			case 6:		 //刷新第七个数码管
			{
				Du_En = 1; P0 = 0x00; Du_En = 0;
				We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
				P0 = 0x00;
				Du_En = 1; P0 = SEG_Tab[Dis_Buff[4]]; Du_En = 0;
				We_Cnt++;
			}
			break;

			case 7:		 //刷新第八个数码管
			{
				Du_En = 1; P0 = 0x00; Du_En = 0;
				We_En = 1; P0 = Bit_Tab[We_Cnt]; We_En = 0;
				P0 = 0x00;
				Du_En = 1; P0 = SEG_Tab[Dis_Buff[5]]; Du_En = 0;
				We_Cnt = 0;
			}
			break;
		}	    
	}    
}

void Dis_Buffer()        //时间分离函数
{
	Dis_Buff[0] = time[0]%10;		//秒个位
	Dis_Buff[1] = time[0]/10;		//秒十位
	Dis_Buff[2] = time[1]%10;		//分个位
	Dis_Buff[3] = time[1]/10;		//分十位
	Dis_Buff[4] = time[2]%10;		//时个位
	Dis_Buff[5] = time[2]/10;		//时十位
}

void initial_myself()	//上电初始化
{
	P0 = 0xff;
	P3 = 0xff;
	We_En = 0;		//关位选
	Du_En = 0;		//关段选
	TMOD &= 0x00;
	TMOD |= 0x01;   // 定时器0,模式1
	TMOD |= 0x10;	// 定时器1,模式1

	TH0 = 0xf8;		//设置初值,没2ms进入一次中断
	TL0 = 0xcd;

	TH1 = 0xdc;		//设置初值,没10ms进入一次中断
	TL1 = 0x00;
}

void initial_peripheral()	 //外围设备初始化
{
    EA = 1;		//开总中断

	ET0 = 1;	//使能T0中断
	TR0 = 1;	//使能T0

	ET1 = 1;    //使能T1中断
	TR1 = 1;    //使能T1
}

void T0_interrupt() interrupt 1	   //定时器0中断函数
{
    TF0 = 0;
	TH0 = 0xf8;
	TL0 = 0xcd;
    time_2ms_ok = 1;	//2ms时间到

	if(++j >= 5)
	{
	    j = 0;
		time_10ms_ok = 1;  //10ms时间到
	}
}

void T1_interrupt() interrupt 3		//定时器1中断函数
{
    TF1 = 0;
	TH1 = 0xdc;
	TL1 = 0x00;
	if(++i >= 100)
	{
	    i = 0;
		time_1s_ok = 1;	 //1s时间到
	}
}

void Dleay_Ms(uint16 z)
{
    uint16 x,y;
	for(x = 0; x < z; x++)
	  for(y = 0; y < 100; y++);
}

char Key_Scan()
{
    static uint8 Key_State = 0;
	uint16 Key_Valve;
	Key_Valve = (Key1&Key2&Key3);
	switch(Key_State)
	{
	    case Initial_State :		//按键初始状态
		{
			if(Key_Valve != 1)
			{
		    	Key_State = Affirm_State;
			}
		}			 
		break;						   
		
		case Affirm_State :			//按键消抖状态
		{
			if(Key_Valve != 1)
			{
		    	if(0 == Key1)
				{
			    	Key_Return = 1;
				}
				if(0 == Key2)
				{
			    	Key_Return = 2;
				}
				if(0 == Key3)
				{
			    	Key_Return = 3;
				}
				Key_State = Signel_State;	 //转到松手检测
			}
			else
			{
		    	Key_State = Initial_State;	 //转到初始状态
			}
		}
		break;
								   
		case Signel_State :			   //按键松手检测
		{
		    if(1 == Key_Valve)
			{
				Key_State = Initial_State;			       
			}
		}	
		break;
	}
	return 0;
}

void Key_Service()
{
    static uint8 Key_Num = 0;
	if(1 == Key_Return)		 // Key1按下
	{
	    Key_Return = 0;			
		TR1 = 0;			 //关定时器1,时间停止计数
		Key_Num++;			 //Key1按下次数
	} 
	switch(Key_Num)
	{
	    case 1:		 //Key1按下1次,秒调整状态
		{
			if(2 == Key_Return)		 //Key2按下,秒时间加1;
			{
		    	Key_Return = 0;
				time[0]++;
				if(time[0] > 59)
				{
			    	time[0]	= 0;
				}

			}
			if(3 == Key_Return)		//Key3按下,秒时间减1
			{
		    	Key_Return = 0;
				time[0]--;
				if(time[0]<0)
				{
			    	time[0] = 59;
				}
			}
		}
		break;
		case 2:		 //Key1按下2次,分钟调整状态
		{
			if(2 == Key_Return)		 //Key2按下,分时间加1;
			{
		    	Key_Return = 0;
				time[1]++;
				if(time[1] > 59)
				{
			    	time[1]	= 0;
				}

			}
			if(3 == Key_Return)		//Key3按下,分时间减1
			{
		    	Key_Return = 0;
				time[1]--;
				if(time[1]<0)
				{
			    	time[1] = 59;
				}
			}
		}
		break;

		case 3:		 //Key1按下3次,小时调整状态
		{
			if(2 == Key_Return)		 //Key2按下,小时时间加1;
			{
		    	Key_Return = 0;
				time[2]++;
				if(time[2] > 24)
				{
			    	time[2]	= 0;
				}
			}
			if(3 == Key_Return)		//Key3按下,小时时间减1
			{
		    	Key_Return = 0;
				time[2]--;
				if(time[2]<0)
				{
			    	time[2] = 24;
				}
			}
		}
		break;

		case 4:	   //Key1按下4次,时间运行确认
		{
			Key_Num = 0;
			TR1 = 1;
		}
		break;
	}   
}