關于一種新的按鍵處理的思路,今天和應廣的技術支持通了一個電話,討論到了按鍵下理的問題,他和我說了有兩種按鍵處理的方法,一種就是我用的那一種,即每10ms判斷一次按鍵的情況,然后oldkey,newkey的方法,他還說了另一種更為簡單的辦法,當然這個也只能用在最簡單的情況,他說每30ms判斷一次按鍵的情況,如果按鍵是按下的情況那么就執行相應的按鍵處理程序,仔細分析一下他說的很有道理啊!!!
下面分析一下這種情況的可行性,首先無論是按鍵按下或是釋放的時候都有一個抖動的時間,這個時間一般是10ms左右,首先從邏輯上來分析一下這個問題消抖的目的無非就是將這個不穩定的抖動的狀態的多次高低電平的變化,使其只有作用一次低電平(假如這里是低電平有效)的相應的處理,條條大路通羅馬,假如一第一個下降沿的時候單片機檢測到這個低電平,而后是按鍵的處理程序,然后是按鍵處理的失能,想要再次使能按鍵的作用只有等待按鍵的再次變為高電平,試想如果這個檢測的時間如果太短或太長的話會有什么情況,如果這個時間設置的太短的假如是1ms那么在這個10ms的時間里會他就會檢測到10次,現在以最壞的情況一分析的話,如果按照原來的按鍵處理程序的話,按照最壞的情況就會有5次按鍵作用的情況,也就是說有5次高電平和5次低電平都被檢測到了,有5次的按鍵使能故能最多作用5次的樣子.假如這個時間足夠長的話,比如檢測一次要1年的時間,那么這其間的按鍵作用都會丟失掉,這是非常可怕的啊,其實這個時間在邏輯上只能大于10ms就行了,只要這個時間大于1倍的按鍵抖時間就能保證在這個抖動時間里按鍵最多只檢測兩次,而只有在抖動時間里按鍵的檢測次數超過3次才能導致多次觸發的情況發生,因為這個抖動的時間一共是20ms這個情況是在最壞的情況下考慮到的最壞的,最壞的情況下沒有按鍵的多次作用那么在其他情況下也就更不會有按鍵的多次作用了.
下面直接上源代碼:
/***************************************************************************************************
函數功能:掃描按鍵值,交將掃描到的按鍵觸發信息轉換成數字賦給Key_num
函數入口:無
函數出口:無
作者 :任丁
***************************************************************************************************/
void KeyScan(void)
{
if(KEY1==0&&KEY2==1&&KEY3==1)
{
key_num=1; //KEY1鍵按下,返回1
return;
}
elseif(KEY1==1&&KEY2==0&&KEY3==1)
{
key_num=2; //KEY2鍵按下,返回2
return;
}
elseif(KEY1==1&&KEY2==1&&KEY3==0)
{
key_num=3; //KEY3鍵按下,返回3
return;
}
elseif(KEY1==1&&KEY2==0&&KEY3==0)
{
key_num=4; //KEY2鍵和KEY3鍵同時按下,返回4
return;
}
//這里還可以添加更多的按鍵,和更多的返回值,霸氣不?!?!?!
//這里有一個問題啊,就是這里是三個按鍵的情況,如果為大于三個按鍵的情況
//而同時要處理多個按鍵按下的問題用這種if else if else if ...else的形式
//就會有一個嚴峻的問題,不能很好的區分每一種按鍵的情況,因為這時會有一個非常復雜的邏輯空間
//區別這每一種按鍵的
//邏輯條件,如果有更多的按鍵,那么這種方法肯定是行不通的,但是如果只是最簡單
//的情況,也就是只會按下一個鍵的情況,那樣的話問題就會簡單很多
//總而言之使用if else if else if else if else的這種結構的關鍵就在于每一個if 或 else if 語句
//都必順是不同的情況,如果不是這樣的話就會有重和漏掉的情況的發生
//對于多個按鍵的情況有一個較為聰明的解決的辦法,就是把在在每一個if或else if 語句里把每一個按鍵的情況
//都寫清楚,使每一種分支都和別的分支都沒有邏輯上的包含的被包含的情況都,從而用這種方法構建的if else if ...else
//是一個沒有包含和被包含情況的邏輯關系非常清晰的空間,也就是實際上這是一個數學上的一個非常簡單的問題
//最終的可能的情況有2的按鍵次數次方的個數,一個關鍵的問題就是書寫條件時先寫if 和 else if 里面的語句而后再
//用一個else語句來把剩下的情況全部概括,其實思路就是抓信己知的情況,從而把未知的情況剩出來。編程時這
//些情況直接用一個else語句來概括,這樣的話對于這些沒有定義的情況統統返回一個0,在KEY_process()里面這些情況
//全部作為是無效按鍵的情況,這些情況下的按鍵觸動情況就會直接作為無效按鍵的情況,KEPY_process()會直接路出
//這些情況從而對于這些情況想當于是沒有任何的作用的.只有有作用的按鍵觸發情況才會轉而去執行相應的按鍵處理程序
//特別要注意的一點就是這些有作用的按鍵觸發情況有都是最細小的邏輯體,這樣才話能夠做到不重不漏,嚴謹有序
//這一種方法是非常有實踐意義和應用價值的
else
{
key_num=0; //如果所有按鍵都沒有按下就返回0或255,這里返回0
return;
}
}
/***************************************************************************************************
函數功能:根據掃描到的不同的按鍵觸發情況,執行相應的按鍵的處理功能
函數入口:無
函數出口:無
作者 :任丁
***************************************************************************************************/
void KeyProcess(void)
{
if(KeyScan_Flag==1) //按鍵掃描的時間30ms到了
{
KeyScan_Flag=0;
KeyScan();
if(0<key_num&&key_num<255) //如果有鍵按下
{
if(key_num==1)
{
if(Key1_EnableFlag==0)
{
//此處添加KEY1按鍵的處理程序
Key1_EnableFlag=1;
return;
}
}
elseif(key_num==2)
{
if(Key2_EnableFlag==0)
{
//此處添加KEY2按鍵的處理程序
Key2_EnableFlag=1;
return;
}
}
elseif(key_num==3)
{
if(Key3_EnableFlag==0)
{
//此處添加KEY3按鍵的處理程序
Key3_EnableFlag=1;
return;
}
}
else
{
return;//實際上不會走到這一條語句,因為return回的有效值為1到255
//除此之外沒有其他值,而如果為0或者大于255時,是不會進入這個分支的
//直接在第二層的else語句執行相應的程序
}
}
else //按鍵無效,即無鍵按下
{
Key1_EnableFlag=0; //按鍵使能標志位置0,使能按鍵作用
Key2_EnableFlag=0; //按鍵使能標志位置0,使能按鍵作用
Key3_EnableFlag=0; //按鍵使能標志位置0,使能按鍵作用
Key4_EnableFlag=0; //按鍵使能標志位置0,使能按鍵作用
return;
}
}
else //按鍵檢測使能標志為0,即沒有到達按鍵檢測的時間間隔,這里設置為10ms,不進行按鍵檢測
{
return;
}
}