一句話解釋按鍵的彈跳:

你來不及放開按鍵之前,程式已經來問第二次了,所以程式不知道你是按了第二次,還是你單純還沒放開。

如果你懶得管那麼多,不妨直接在 loop 裡面加入 delay(100),避開明顯的彈跳問題。

如果你想嚴謹一點,那就引用一些現成的庫來用吧。

(以下用例中,我的 MCU 是 ESP32)

EasyButton

如果你什麼都不要,就只要防彈跳,可以考慮 EasyButton 這個 library。

使用方法很簡單,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <ezButton.h>

const int led = 19;

ezButton btn(23);

void setup(){
pinMode(led, OUTPUT);
//pinMode(btn, INPUT_PULLUP); //ezButton已經幫你預設上拉了

btn.setDebounceTime(50); //如果你手速夠快(50ms內點兩下),你依然可以讓彈跳發生

}

void loop() {

btn.loop(); //ezButton開始讀btn
//bool reading = digitalRead(btn); //所以不用自己讀

if(btn.isPressed()){ //如果要放開才觸發就用 isReleased
digitalWrite(led, !digitalRead(led));
}

}

額外送你判斷按下跟放開的時機,可以讓你在按下就觸發,或是放開才觸發。

OneButton

如果你除了基本的防彈跳,還想要可以定義單擊、雙擊、長按,可以考慮 OneButton

可參考我的範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <OneButton.h>

OneButton btn; //設btn為一個OneButton物件

const int led = 19;

void setup() {
pinMode(led, OUTPUT);

btn.setup( //設定定義的這個btn
23, //設定按鍵pin
INPUT_PULLUP, //設定爲上拉
true //按下為LOW
);

btn.attachClick(whenSingle); //單擊行爲
btn.attachDoubleClick(whenDouble); //雙擊行爲
btn.attachLongPressStart(whenLong); //長按行爲

}

void loop() {
btn.tick(); //loop中一定要寫這個,它才會持續監視按鈕
}

void whenSingle(){
digitalWrite(led, !digitalRead(led));
}
void whenDouble(){
digitalWrite(led, !digitalRead(led));
}
void whenLong(){
digitalWrite(led, !digitalRead(led));
}

此例中,我單擊、雙擊、長按都觸發一樣的動作,你可以自己定義要分別做什麼動作。