/*===============================================================
功能:一個按鍵實現按鍵的長按,短按,多擊
長按:按下有效,有長按,短按一般來講都是松開有效
多擊(包含單擊):松開有效
按鍵按下的觸發事件:(觸發事件可以按需求修改)
長按:點亮Led0
單擊:點亮Led1
雙擊:點亮Led2
三擊:點亮Led3
===============================================================*/
/*============================注意事項==================================
1.關于Seg的變量和ucLed可以不必理會,
前者是數碼管顯示Reg_Test_Count,后者是按鍵按下后的觸發事件。這兩個大家可以自己更改
=======================================================================*/
/* 頭文件聲明區 */
#include <STC15F2K60S2.H>//單片機寄存器專用頭文件
#include <Init.h>//初始化底層驅動專用頭文件
#include <Led.h>//Led底層驅動專用頭文件
#include <Key.h>//按鍵底層驅動專用頭文件
#include <Seg.h>//數碼管底層驅動專用頭文件
sbit KEY4 = P3^3; //定義了一個按鍵
/* 變量聲明區 */
unsigned char Key_Slow_Down; //按鍵減速專用變量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10}; //數碼管顯示數據存放數組
unsigned char Seg_Pos; //數碼管掃描專用變量
unsigned int Seg_Slow_Down; //數碼管減速專用變量
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0}; //Led顯示數據存放數組
/*變量*/
unsigned int Reg_Test_Count; //測試用的一個變量,表示短按了多少次。這個可以自己定義一個
unsigned int Reg_Tick; //表示每次按下的時間間隔是多少。初始值可以自己改,看后面的代碼就知道了
unsigned int Reg_Key_Filter_50ms; //按下時濾波,我這里濾波50ms。
unsigned int Reg_Key_10ms; //10ms計數
/*標志位*/
unsigned char Bit_Short_Press; //短按標志位
unsigned char Bit_10ms; //10ms定時到達標志位
/* 鍵盤處理函數 */
void Key_Proc()
{
static unsigned int Reg_Key_Press_Time = 0; //請記得標為靜態變量
if(Bit_10ms) //10ms進來一次
{
Bit_10ms = 0;
if(KEY4==0) //如果按下了按鍵
{
Reg_Tick = 50; //給多擊的時間間隔賦初值
if(++Reg_Key_Press_Time <=0 ) --Reg_Key_Press_Time; //計量按鍵時間,并避免數據溢出
if(Bit_Short_Press == 0) //判斷短按標志位
{
if(++Reg_Key_Filter_50ms >= 5) //如果濾波時間到達了50ms
{
Reg_Key_Filter_50ms = 0; //濾波時間清0
Reg_Test_Count++;
Bit_Short_Press = 1; //短按標志位置1
}
}
if(Reg_Key_Press_Time >= 100) //長按時間已經到達1s
{
ucLed[0] = 1; //這里寫事件,我這里寫的點燈
}
}
else//松開
{
Reg_Key_Filter_50ms = 0; //濾波的50ms只有檢測到高電平立馬清零,此次按鍵無效
Bit_Short_Press = 0; //短按標志位清零
Reg_Key_Press_Time = 0; //長按計數清零
if(Reg_Tick) //如果多擊時間間隔不為零
{
Reg_Tick--;
}
if(Reg_Tick == 0) //只要減到0,就說明此時我已經不再按下按鍵了,開始寫多擊事件
{
if(Reg_Test_Count == 1) //如果按下一次
{
ucLed[1] = 1; //寫按下一次的事件,這個可以自己改,我寫的點燈
}
else if(Reg_Test_Count == 2) //如果按下兩次
{
ucLed[2] = 1; //同上
}
else if(Reg_Test_Count == 3) //如果按下三次
{
ucLed[3] = 1; //同上
}
Reg_Test_Count = 0; //Reg_Test_Count清零,等待執行下一次多擊事件
//到這里就完整的執行了一次多擊事件,注意Reg_Test_Count一定要清零。
}
}
}
}
/* 信息處理函數 */
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;//數碼管減速程序
Seg_Buf[0] = Reg_Test_Count%10;
}
/* 定時器0中斷初始化函數 */
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設置定時器模式
TL0 = 0x18; //設置定時初始值
TH0 = 0xFC; //設置定時初始值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0 = 1; //定時器中斷0打開
EA = 1; //總中斷打開
}
/* 定時器0中斷服務函數 */
void Timer0Server() interrupt 1
{
if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//鍵盤減速專用
if(++Seg_Slow_Down == 100) Seg_Slow_Down = 0;//數碼管減速專用
if(++Seg_Pos == 8) Seg_Pos = 0;//數碼管顯示專用
if(++Reg_Key_10ms >= 10)
{
Reg_Key_10ms = 0;
Bit_10ms = 1;
}
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
}
/* Main */
void main()
{
System_Init();
Timer0Init();
while (1)
{
Key_Proc();
Seg_Proc();
}
}
|