關於按鍵掃描程序的終極討論

1、思路函數

基於STM8,按鍵處理,思路是這樣的:spa

每20ms左右一次去掃描按鍵,用一個key_now記錄當前值,用key_last記錄上次的值,若是key_now和key_last同時有效,則開始進行cnt++。
我設定兩個閾值,LONG_PRESS爲100(100*20ms=2s),SHORT_PRESS爲4(4*20ms=80ms,去抖)。
cnt大於LONG_PRESS,表示是長按,反之再判斷cnt是否是大於SHORT_PRESS,表示是短按,不然把cnt清零。code

另一種狀況,咱們在設置參數的時候,要不停加1或者減1,我長按,但願數值連續增減,怎麼實現?blog

接上面的cnt值,再設置一個連按的閾值,MID_PRESS=50(50*20ms=1s)。
當cnt大於MID_PRESS時,我認爲觸發了短按,但此時不清空cnt,只是將cnt減去SHORT_PRESS的值。
如此下去,若是按鍵一直不鬆開,則一直連線觸發短按。it

 

2、實現ast

硬件上有三個按鍵,分別是set,up,down。class

// 控制按鍵時長 
#define LONG_PRESS 100 // 20ms*100=2s,長按 
#define SHORT_PRESS 5 // 20ms*5=100ms,短按 
#define MID_PRESS 50 // 20ms*50=1s,連按 
#define REPEAT_PRESS 5 // 200ms*5=100ms,連按靈敏參數 

#define KEY_PORT (GPIOC) 
#define KEY_SET (GPIO_PIN_5) // set鍵接PC5 
#define KEY_UP (GPIO_PIN_6) // up鍵接PC6 
#define KEY_DOWN (GPIO_PIN_7) // down鍵接PC7

uchar pinNow; 
bool pinSet_now, pinUp_now, pinDown_now; 
bool pinSet_last, pinUp_last, pinDown_last; 
bool set_long = FALSE; // set鍵長按 
bool set_short = FALSE; // set鍵短按 
bool up_short = FALSE; // up鍵短按 
bool down_short = FALSE; // down鍵短按

// 初始化 
void key_proc_init(void) 
{ 
    GPIO_Init(KEY_PORT, KEY_SET|KEY_UP|KEY_DOWN, GPIO_MODE_IN_FL_IT); 
    EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOC, EXTI_SENSITIVITY_FALL_ONLY);

    pinNow = 0; 
    set_cnt = 0; 
    up_cnt = 0; 
    down_cnt = 0;

    set_long = FALSE; 
    set_short = FALSE; 
    up_short = FALSE; 
    down_short = FALSE; 
}

// 按鍵處理 
void key_scan(void) 
{ 
    //按鍵端口上拉了,默認是高電平,有按鍵時變低。這裏取反,有按鍵時變高。 
    pinNow = 0xFF - GPIO_ReadInputData(KEY_PORT); 
    pinSet_now = pinNow & KEY_SET; 
    pinUp_now = pinNow & KEY_UP; 
    pinDown_now = pinNow & KEY_DOWN;

    // set鍵只分長按和短按,沒有連按 
    if (pinSet_now & pinSet_last) { 
        set_cnt++; 
        if (set_cnt>LONG_PRESS) { 
            set_long = TRUE; 
            set_cnt = 0; 
        } 
    }else { 
        if (set_cnt>SHORT_PRESS) { 
            set_short = TRUE; 
            set_cnt = 0; 
        }else{ 
            set_cnt = 0; 
        } 
    } 

    // up和down鍵有連按和短按,沒有長按 
    if (pinUp_now & pinUp_last) { 
        up_cnt++; 
        if (up_cnt>MID_PRESS) { 
            up_short = TRUE; 
            up_cnt = up_cnt - REPEAT_PRESS; 
        } 
    }else{ 
        if (up_cnt>SHORT_PRESS) { 
            up_short = TRUE; 
            up_cnt = 0; 
        } 
    }

    if (pinDown_now & pinDown_last) { 
        down_cnt++; 
        if (down_cnt>MID_PRESS) { 
            down_short = TRUE; 
            down_cnt = down_cnt - REPEAT_PRESS; 
        } 
    }else{ 
        if (down_cnt>SHORT_PRESS) { 
            down_short = TRUE; 
            down_cnt = 0; 
        } 
    }

    // 添加本身對於set_long,set_short,up_short,down_short的處理代碼 
    // 處理完了不要忘記把相應的值置爲FALSE

    pinSet_last = pinSet_now; 
    pinUp_last = pinUp_now; 
    pinDown_last = pinDown_now; 
}

而後用定時器中斷,每20ms去執行一個key_scan()函數。硬件

相關文章
相關標籤/搜索