有限狀態(tài)機由有限的狀態(tài)和相互之間的轉(zhuǎn)移構(gòu)成,在任何時候只
能處于給定數(shù)目的狀態(tài)中的一個。當接收到一個輸入事件時,狀態(tài)機產(chǎn)生一個輸出,同時也可能伴隨著狀態(tài)的轉(zhuǎn)移。
#define key_input PIND.7 // 按鍵輸入口
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
char read_key(void)
{
static char key_state = 0;
char key_press, key_return = 0;
key_press = key_input; // 讀按鍵 I/O (狀態(tài)機的輸入)
switch (key_state)
{
case key_state_0: // 按鍵初始態(tài)
if (!key_press) key_state = key_state_1; // 鍵被按下,狀態(tài)轉(zhuǎn)換到鍵確認態(tài) , 確定下一次按鍵的狀態(tài)值
break;
case key_state_1: // 按鍵確認態(tài)
if (!key_press)
{
key_return = 1; // 按鍵仍按下,按鍵確認輸出為“1”
key_state = key_state_2; // 狀態(tài)轉(zhuǎn)換到鍵釋放態(tài)
}
else
key_state = key_state_0; // 按鍵已抬起,轉(zhuǎn)換到 按鍵初始態(tài)
break;
case key_state_2:
if (key_press) key_state = key_state_0; //按鍵已釋放,轉(zhuǎn)換到按鍵初始態(tài)
break;
}
return key_return;
}
該簡單按鍵接口函數(shù) read_key()在整個系統(tǒng)程序中應(yīng)每隔10ms
調(diào)用執(zhí)行一次,每次執(zhí)行時將先讀取與按鍵連接的 I/O 的電平到變量 key_press 中,然后進入用 switch 結(jié)構(gòu)構(gòu)成的狀態(tài)機。switch 結(jié)構(gòu)中的 case 語句分別實現(xiàn)了 3 個不同狀態(tài)的處理判別過程,在每個狀態(tài)中將根據(jù)狀態(tài)的不同,以及 key_press 的值(狀態(tài)機的輸入)確定輸出值(key_return),和確定下一次按鍵的狀態(tài)值(key_state) 。 函數(shù) read_key()的返回參數(shù)提供上層程序使用。返回值為 0 時,表示按鍵無動作;而返回 1 表示有一次按鍵閉合動作,需要進入按鍵處理程序做相應(yīng)的鍵處理。在函數(shù) read_key()中定義了 3 個局部變量,其中 key_press和key_return為一般普通的局部變量,每次函數(shù)執(zhí)行時,key_press 中保存著剛檢測的按鍵值。key_return 為函數(shù)的返回值,總是先初始化為 0,只有在狀態(tài) 1 中重新置 1,作為表示按鍵確認的標志返回。變量 key_state 非常重要,它保存著按鍵的狀態(tài)值,該變量的值在函數(shù)調(diào)用結(jié)束后不能消失,
必須保留原值,因此在程序中定義為“局部靜態(tài)變量” ,用static 聲明。如果使用的語言環(huán)境不支持 static 類型的局部變量,應(yīng)將 key_state 定義為全局變量(關(guān)于局部靜態(tài)變量的特點請參考相關(guān)介紹 C 語言程序設(shè)計的書籍) 。 |