1. 程式人生 > 其它 >二、獨立按鍵開關機,紅藍閃爍燈切換頻率實驗

二、獨立按鍵開關機,紅藍閃爍燈切換頻率實驗

功能:單鍵操作 長按開關機;開機狀態下,短按切換閃爍頻率5Hz 8Hz,紅藍燈雙閃

閃爍方式:紅單閃5次----藍單閃5次----紅藍同閃5次

1MS掃描

bit B_1ms=0;
u16 T_2s=0;


#define Const_Key_Jitter  40 //抖動計數
#define Const_Key_Long   1000 //長按1秒

u16 INT1_Cnt=0;
bit Short_Click=0;
bit Long_Click=0;
bit INT1_Lock=0;
bit Power_On=0;
u8  key_num=0;
bit key_Flag=0;
#define Const_Flash_5Hz_On     100  // 100ms
#define Const_Flash_5Hz_Off     100  // 100ms
#define Const_Flash_8Hz_On     62  // 62ms
#define Const_Flash_8Hz_Off     63  // 63ms
#define Flash_Times       5   //閃5次
u8 Temp_On;					 //用於資料快取
u8 Temp_On_Times;	  
u8 Temp_Off;
u8 Temp_Off_Times;
u8 Temp_Times;
bit FLone,FLtwo,Plon;
/*******************************************************
	當短按有效時,繼續計數,滿足長按條件自鎖
	鬆手解鎖
	短按為鬆手後判斷
	長按不需要鬆手就有效	
*******************************************************/
void Key_Scan()
{	 
	if(INT1==1)
	{
		INT1_Cnt=0;	 //按下計數清0
		if(INT1_Lock==1)  //長按鎖標誌
		{
			INT1_Lock=0;	
		}
		else if (Short_Click==1&&(Power_On==1))	//短按標誌且電源開啟
		{
			Short_Click=0;
			key_Flag=1;
			
		}	 	       
		
	}
	else if(INT1_Lock==0) //有鍵按下,且自鎖標誌為0,即第一次按下
	{
		INT1_Cnt++;
		if(INT1_Cnt>=Const_Key_Jitter)
		{
			Short_Click=1;			  //短按有效標誌
		
		}
		if(INT1_Cnt>=Const_Key_Long)	  //說明是長按,開自鎖
		{
			INT1_Lock=1;			  //長按鎖住
			Short_Click=0;
			Power_On=~Power_On;		  //長按開關機
			
		}
	}
}
/*******************************************************
	當短按有效時,根據鍵值,切換頻率
		
*******************************************************/
void KEY_Result()
{
	if(key_Flag)
	{
		key_Flag=0;
		key_num++;
		if(key_num>=2)key_num=0;
		switch(key_num)
		{
			case 0:
				Temp_On_Times=Const_Flash_5Hz_On;
				Temp_Off_Times=Const_Flash_5Hz_Off;
				Temp_Times=Flash_Times;
				break;
			case 1:
				Temp_On_Times=Const_Flash_8Hz_On;
				Temp_Off_Times=Const_Flash_8Hz_Off;
				Temp_Times=Flash_Times;
				break;
		}
	}	
}
/*******************************************************************
	標誌法寫閃爍迴圈
	1、長按開機進入閃爍頻率為5Hz:紅閃5次,藍閃5次,紅藍同閃5次
	2、短按改變閃爍頻率,即在5Hz、8Hz之間切換
	3、長按關機,並進入睡眠狀態	
********************************************************************/
void RED_Flash()
{
	if((Power_On)&&(FLone==0)&&(FLtwo==0))
	{
		if(Plon==0)
		{
			RED=1;
			if((Temp_On--)==0)
			{
				Temp_On=Temp_On_Times;
				Plon=1;
			}
			
		}
		else
		{
			RED=0;
			if((Temp_Off--)==0)
			{
				Temp_Off=Temp_Off_Times;
				Plon=0;
				if((Temp_Times--)==0)
				{
					Temp_Times=Flash_Times;
					FLone=1;
				}	
			}
		}
	}
}
void BLUE_Flash()
{
	if((Power_On)&&(FLone==1)&&(FLtwo==0))
	{
		if(Plon==0)
		{
			BLUE=1;
			if((Temp_On--)==0)
			{
				Temp_On=Temp_On_Times;
				Plon=1;
			}
			
		}
		else
		{
			BLUE=0;
			if((Temp_Off--)==0)
			{
				Temp_Off=Temp_Off_Times;
				Plon=0;
				if((Temp_Times--)==0)
				{
					Temp_Times=Flash_Times;

					FLtwo=1;
				}	
			}
		}
	}
}
void ALL_Flash()
{
	if((Power_On)&&(FLtwo==1))
	{
		if(Plon==0)
		{
			BLUE=1;
			RED=1;
			if((Temp_On--)==0)
			{
				Temp_On=Temp_On_Times;
				Plon=1;
			}
			
		}
		else
		{
			BLUE=0;
			RED=0;
			if((Temp_Off--)==0)
			{
				Temp_Off=Temp_Off_Times;
				Plon=0;
				if((Temp_Times--)==0)
				{
					Temp_Times=Flash_Times;
					FLone=0;
					FLtwo=0;

				}	
			}
		}
	}
}
void main( )
{	 

	GPIO_Inilize();
	Timer0_Inilize();
	Exti_Inilize();
	Temp_On_Times=Const_Flash_5Hz_On;
	Temp_On=Temp_On_Times;
	Temp_Off_Times=Const_Flash_5Hz_Off;
	Temp_Off=Temp_Off_Times;
	Temp_Times=Flash_Times;
	delay_ms(5);
	TR0=1;
	EA=1;
	while(1)
	{
		if(B_1ms==1)
		{
			B_1ms=0;
			if(++T_2s>=2000)
			{
				T_2s=0;
				if(INT1&&(Power_On==0))
				{
					
					TR0=0;
					BLUE=0;
					RED=0;
					INT1_Clear();  //清標誌 IE1=0	
					INT1_Enable(); //使能按鍵中斷EX1=1,用於喚醒
					MCU_POWER_DOWN(); //進入睡眠 PCON |= 2
					NOP7();
				}
			}
			Key_Scan();
			RED_Flash();
			BLUE_Flash();
			ALL_Flash();
		}
	 KEY_Result();
	}
}

/********************* Timer0中斷函式************************/
void timer0_int (void) interrupt TIMER0_VECTOR
{
	TF0=0;
	B_1ms=1;
}

void Ext_INT1 (void) interrupt INT1_VECTOR		//進中斷時已經清除標誌
{
	INT1_Disable();  //關閉按鍵中斷使能 EX1=0
	TR0=1;

}