- 簡介:傳統的按鍵掃描程序,大部分都是採用 delay_ms(5); 這樣的語句來進行按鍵消抖,但當你把它放在你高速運行的程序中時,這5ms可能會拖慢你的成語運行,導致體驗感受下降,因此,我便找到了新的按鍵掃描思想,並將這一思想移植到ESP8266中以便後續工程使用!
- 這種新的按鍵掃描思想並不複雜,你需要定義一個 1ms 的定時器,在定時器中判斷按鍵狀態,如果按鍵按下,則按鍵的檢測按下次數 加一,最後將 按鍵的檢測按下次數 乘以 1ms 則可以得到按鍵按下時間,如果檢測到按鍵鬆開,則令按鍵的檢測按下次數 歸零,這樣一來,我們便可以實現按鍵的 短按&&長按。
- 接下來看下例子吧!
/*
*@作者:劉澤文
*@功能:四個按鍵,放在定時器裏邊的按鍵掃描程序,防止拖慢程序
*@時間:2020/3/15
*/
#include <Ticker.h>
#include <ESP8266WiFi.h>
//LED和按鍵引腳定義
#define LED D4 //gpio2
#define UP_KEY D6 //gpio12
#define M_KEY D5 //gpio14
#define DOWN_KEY D7 //gpio13
#define WAKE_UP D3 //gpio0
//讀按鍵值
#define KEYU digitalRead(UP_KEY)
#define KEYM digitalRead(M_KEY)
#define KEYD digitalRead(DOWN_KEY)
#define KEYW digitalRead(WAKE_UP)
#define LED_OFF digitalWrite(LED, HIGH)//關燈
#define LED_ON digitalWrite(LED, LOW)//開燈
#define LED_PWM digitalWrite(LED, !digitalRead(LED))//燈閃爍
#define short_press_time 10 //短按時間
#define long_press_time 1000 //長按時間
#define NO_KEY_PRES 0 //無按鍵按下
#define UP_KEY_PRES 1
#define M_KEY_PRES 2
#define DOWN_KEY_PRES 3
#define WAKE_UP_PRES 4
#define UP_KEY_LONG_PRES 11
#define M_KEY_LONG_PRES 22
#define DOWN_KEY_LONG_PRES 33
#define WAKE_UP_LONG_PRES 44
uint16_t KEYU_PRESS_COUNT = 0;//按KEYU時間計數
uint16_t KEYM_PRESS_COUNT = 0;//按KEYM時間計數
uint16_t KEYD_PRESS_COUNT = 0;//按KEYD時間計數
uint16_t KEYW_PRESS_COUNT = 0;//按KEYW時間計數
bool KEYU_UP = 0;//按鍵狀態,0爲彈起,1爲按下
bool KEYM_UP = 0;//按鍵狀態,0爲彈起,1爲按下
bool KEYD_UP = 0;//按鍵狀態,0爲彈起,1爲按下
bool KEYW_UP = 0;//按鍵狀態,0爲彈起,1爲按下
uint8_t KEYU_KEY_READ = NO_KEY_PRES;//KEYU按鍵狀態
uint8_t KEYM_KEY_READ = NO_KEY_PRES;//KEYM按鍵狀態
uint8_t KEYD_KEY_READ = NO_KEY_PRES;//KEYD按鍵狀態
uint8_t KEYW_KEY_READ = NO_KEY_PRES;//KEYW按鍵狀態
Ticker key_tick;
/*
*@定時器裏邊檢測按鍵狀態並計數
*/
void flip() {
//UP_KEY
if(KEYU==0){
KEYU_PRESS_COUNT++;
KEYU_UP = 1;
if(KEYU_PRESS_COUNT<=short_press_time)
KEYU_KEY_READ = NO_KEY_PRES;
if(KEYU_PRESS_COUNT>=short_press_time&&KEYU_PRESS_COUNT<=long_press_time)
KEYU_KEY_READ = UP_KEY_PRES;
if(KEYU_PRESS_COUNT>=long_press_time)
KEYU_KEY_READ = UP_KEY_LONG_PRES;
}
if(KEYU){
KEYU_PRESS_COUNT = 0;
KEYU_UP = 0;//按鍵狀態,0爲彈起,1爲按下
}
//M_KEY
if(KEYM==0){
KEYM_PRESS_COUNT++;
KEYM_UP = 1;
if(KEYM_PRESS_COUNT<=short_press_time)
KEYM_KEY_READ = NO_KEY_PRES;
if(KEYM_PRESS_COUNT>=short_press_time&&KEYM_PRESS_COUNT<=long_press_time)
KEYM_KEY_READ = M_KEY_PRES;
if(KEYM_PRESS_COUNT>=long_press_time)
KEYM_KEY_READ = M_KEY_LONG_PRES;
}
if(KEYM){
KEYM_PRESS_COUNT = 0;
KEYM_UP = 0;//按鍵狀態,0爲彈起,1爲按下
}
//DOWN_KEY
if(KEYD==0){
KEYD_PRESS_COUNT++;
KEYD_UP = 1;
if(KEYD_PRESS_COUNT<=short_press_time)
KEYD_KEY_READ = NO_KEY_PRES;
if(KEYD_PRESS_COUNT>=short_press_time&&KEYD_PRESS_COUNT<=long_press_time)
KEYD_KEY_READ = DOWN_KEY_PRES;
if(KEYD_PRESS_COUNT>=long_press_time)
KEYD_KEY_READ = DOWN_KEY_LONG_PRES;
}
if(KEYD){
KEYD_PRESS_COUNT = 0;
KEYD_UP = 0;//按鍵狀態,0爲彈起,1爲按下
}
//WAKE_UP
if(KEYW==0){
KEYW_PRESS_COUNT++;
KEYW_UP = 1;
if(KEYW_PRESS_COUNT<=short_press_time)
KEYW_KEY_READ = NO_KEY_PRES;
if(KEYW_PRESS_COUNT>=short_press_time&&KEYW_PRESS_COUNT<=long_press_time)
KEYW_KEY_READ = WAKE_UP_PRES;
if(KEYW_PRESS_COUNT>=long_press_time)
KEYW_KEY_READ = WAKE_UP_LONG_PRES;
}
if(KEYW){
KEYW_PRESS_COUNT = 0;
KEYW_UP = 0;//按鍵狀態,0爲彈起,1爲按下
}
if(KEYU_KEY_READ == UP_KEY_LONG_PRES && KEYU_UP == 0){
LED_PWM;
Serial.println("--KEYU_UP長按");
KEYU_KEY_READ = NO_KEY_PRES;
}
if(KEYU_KEY_READ == UP_KEY_PRES && KEYU_UP == 0){
LED_PWM;
Serial.println("----KEYU_UP短按");
KEYU_KEY_READ = NO_KEY_PRES;
}
if(KEYM_KEY_READ == M_KEY_LONG_PRES && KEYM_UP == 0){
LED_PWM;
Serial.println("------KEYM_UP長按");
KEYM_KEY_READ = NO_KEY_PRES;
}
if(KEYM_KEY_READ == M_KEY_PRES && KEYM_UP == 0){
LED_PWM;
Serial.println("--------KEYM_UP短按");
KEYM_KEY_READ = NO_KEY_PRES;
}
if(KEYD_KEY_READ == DOWN_KEY_LONG_PRES && KEYD_UP == 0){
LED_PWM;
Serial.println("------------KEYD_UP長按");
KEYD_KEY_READ = NO_KEY_PRES;
}
if(KEYD_KEY_READ == DOWN_KEY_PRES && KEYD_UP == 0){
LED_PWM;
Serial.println("--------------KEYD_UP短按");
KEYD_KEY_READ = NO_KEY_PRES;
}
if(KEYW_KEY_READ == WAKE_UP_LONG_PRES && KEYW_UP == 0){
LED_PWM;
Serial.println("----------------KEYW_UP長按");
KEYW_KEY_READ = NO_KEY_PRES;
}
if(KEYW_KEY_READ == WAKE_UP_PRES && KEYW_UP == 0){
LED_PWM;
Serial.println("------------------KEYW_UP短按");
KEYW_KEY_READ = NO_KEY_PRES;
}
}
void setup()
{
Serial.begin(9600);
pinMode(UP_KEY,INPUT_PULLUP);
pinMode(M_KEY,INPUT_PULLUP);
pinMode(DOWN_KEY,INPUT_PULLUP);
pinMode(WAKE_UP,INPUT_PULLUP);
pinMode(LED,OUTPUT);
LED_OFF;//滅燈
key_tick.attach_ms(1, flip);//按鍵檢測定時器(1ms)
}
void loop()
{
delay(10*1000);
LED_PWM; //閃燈
}
- 打開你的串口監視器(波特率:9600),按下你的按鍵看看效果吧~