《ESP8266學習筆記》之 採用定時器內的按鍵掃描方法,摒棄傳統的延時按鍵消抖

  • 簡介:傳統的按鍵掃描程序,大部分都是採用 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),按下你的按鍵看看效果吧~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章