stm32按鍵識別


剛寫了一個關於stm32單片機的按鍵識別的程序。目的,同時識別多個按鍵,並且不浪費cpu的時間。

關於去抖動,以前以為是在按鍵的時候,手會抖動。通過程序驗證,這個確實是誤解。這個應該是防止意外干擾。以我的手按鍵的速度,單次持續時間小於0.2秒鍾。

前提:引腳低電平為按鍵按下。為每個按鍵設置3個變量,分別是識別過程的計數器keycnt、識別的結果keystat、可以判定的結果keymod(比如按下、釋放、單擊、雙擊、長按等)。

本例 只有單擊一種判斷,keymod暫時不用。另外考慮,按鍵判定后,直到松開,不重復判定。具體模式和規則,可根據需要修改。另外要考慮,按鍵后,要執行的其他動作,是瞬間動作還是長時間動作,比如讓燈閃爍,本例沒有涉及該步驟。

思路:定時周期內:掃描每個按鍵的引腳電平,根據預定規則改變對應的計數器;依據計數狀態,給出按鍵結果。

對於具體應用,應進一步人性化。

部分頭文件:

// KEY:PB12,PB13,PB14,PB15;PB3,PB4
// KEY On:0 ; KEY Off:1 低電平觸發

#ifndef __MINIKEY_

#define __MINIKEY_

#include "stdint.h"
#include "miniled.h"
#include "miniusart.h"
#include "minirtc.h"

#define keynum 6 //On Board KEY NUMBER

#define KEY0 (GPIOB->IDR&0x1000) //PB12
#define KEY1 (GPIOB->IDR&0x2000) //PB13,
#define KEY2 (GPIOB->IDR&0x4000) //PB14
#define KEY3 (GPIOB->IDR&0x8000) //PB15
#define KEY4 (GPIOB->IDR&0x0001) //PB0
#define KEY5 (GPIOB->IDR&0x0002) //PB1
#define KEYON 0
#define KEYOFF 1
#define KEYPRESS 0x02  //單擊

#endif

相關功能:

uint8_t keypress=15; // 去抖動參數,用於計數器參考判定按鍵單擊。定時器間隔為0.01秒。
uint8_t keycnt[keynum]; //計數器
uint8_t keystat[keynum]; //0x00/release;0x01/down; 0x02/press;0x04/up; 0x10 /click; 0x20 /double; 0x40 /keep;
uint8_t keymod[keynum]; //定義同keystat,對應bit位置1,則為啟動相應功能。

// KEY:PB12,PB13,PB14,PB15

void key_init(void)
{
uint8_t m;
RCC->APB2ENR|=0x08; //enable PORTB clock
GPIOB->CRH&=0x0000FFFF; //clean PB12,PB13,PB14,PB15¡£Per 4 bits for one Port¡£
GPIOB->CRH|=0x88880000; //set PB12,PB13,PB14,PB15
GPIOB->CRL&=0xFFF00000; //clean PB0,PB1¡£PB2,PB3 error¡£
GPIOB->CRL|=0x00008888; //set PB0,PB1¡£PB2,PB3 error¡£
GPIOB->ODR&=0x0FF0;
GPIOB->ODR|=0xF00F;

for(m=0;m<keynum;m++){
keycnt[m]=0;
keystat[m]=0;
keymod[m]=0x10;
}
}

//循環掃描,在定時中執行
void keyscan(void)
{
    uint8_t k;
    for(k=0;k<keynum;k++){
        keyone(k);
    }
}

//識別規則
void keyone(uint8_t nkey)
{
switch(nkey){
case 0:
if(KEY0==KEYON){
    if(keycnt[nkey]==keypress){
     //   keycnt[nkey]=0;//長按視為反復觸發按鍵。
        keystat[nkey]=0x02;
        }else{
        keycnt[nkey]++;
        }
}else{
     keycnt[nkey]=0;
}
break;

…………

}

//后續動作,在定時中執行
void keydo(void)
{
if(keystat[0]==0x02){
keystat[0]=0; //reset key after done
kset0();  //要執行的動作
}
……………………
if(keystat[5]==0x02){
keystat[5]=0; //reset key begin done
led_flush(2);
led_flush(3);
}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM