4x4 鍵盤
按鍵偵測與掃描原理
為了方便解說,筆者把4×4按鍵簡化成3×1,像下圖這樣串連三個開關,連接到同一個微控制器的輸入腳。此外,因為要簡化開關電路,所以要啟用微控器內部的上拉電阻(請參閱《超圖解Arduino互動設計入門》第四章「啟用微控器內部的上拉電阻」一節,4-13頁):
假設開關的「行1」~「行3」輸入端全都輸入高電位,無論開關是否被按下,Arduino將接收到高電位(1)。為了檢測到其中按鍵被按下,程式必須依序將「行1」~「行3」腳位設定成低電位。
輪到「行2」腳輸入低電位,此時,微控器的輸入腳也將接收到低電位(0),由此可知連接「行2」的「開關B」被按下了。
輪到「行3」腳輸入低電位,由於「開關C」未被按下,因此微控器的輸入腳接收到高電位(1)。
到此,偵測按鍵的程式必須再次回到「行1」,輸入低電位…如此反覆循環掃描,才能持續偵測到某個按鍵是否被按下。實際的程式需要運用雙重迴圈,才能分批掃描每一列:
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
#include <Keypad.h> // 引用Keypad程式庫
#define KEY_ROWS 4 // 按鍵模組的列數
#define KEY_COLS 4 // 按鍵模組的行數
// 依照行、列排列的按鍵字元(二維陣列)
char keymap[KEY_ROWS][KEY_COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte colPins[KEY_COLS] = {7, 6, 5, 4}; // 按鍵模組,行1~4接腳。
byte rowPins[KEY_ROWS] = {11, 10, 9, 8}; // 按鍵模組,列1~4接腳。
// 初始化Keypad物件
// 語法:Keypad(makeKeymap(按鍵字元的二維陣列), 模組列接腳, 模組行接腳, 模組列數, 模組行數)
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, KEY_ROWS, KEY_COLS);
void setup(){
Serial.begin(9600);
}
void loop(){
// 透過Keypad物件的getKey()方法讀取按鍵的字元
char key = myKeypad.getKey();
if (key){ // 若有按鍵被按下…
Serial.println(key); // 顯示按鍵的字元
}
}
修改成可以輸入數值以方便設定
#include <Keypad.h> // 引用Keypad程式庫
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2); // 若LCD 無法啟用,請將0X3F 改為0X27
#define KEY_ROWS 4 // 按鍵模組的列數
#define KEY_COLS 4 // 按鍵模組的行數
// 依照行、列排列的按鍵字元(二維陣列)
char keymap[KEY_ROWS][KEY_COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte colPins[KEY_COLS] = {7, 6, 5, 4}; // 按鍵模組,行1~4接腳。
byte rowPins[KEY_ROWS] = {11, 10, 9, 8}; // 按鍵模組,列1~4接腳。
char cmd[12];
unsigned long num ;
int i = 0 ;
// 初始化Keypad物件
// 語法:Keypad(makeKeymap(按鍵字元的二維陣列), 模組列接腳, 模組行接腳, 模組列數, 模組行數)
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, KEY_ROWS, KEY_COLS);
void setup(){
Serial.begin(9600);
lcd.init();
lcd.backlight();
lcd.clear();
}
void loop(){
// 透過Keypad物件的getKey()方法讀取按鍵的字元
char key = myKeypad.getKey();
if (key){ // 若有按鍵被按下…
if(key == '#'){ //確認輸出並送出數字
num = atol(cmd);
lcd.clear();
lcd.setCursor(0,1);
lcd.print(num);
i=0;
for(int j=0 ;j<10;j++){ //送出後清除所有輸入的字元
cmd[j]=' ' ;
}
}else{
cmd[i]=key; //逐一顯示輸入數字
lcd.setCursor(i,0);
lcd.print(cmd[i]);
if(key == '*'){ //按*鈕修改輸入
cmd[i]=' ';
lcd.setCursor(i,0);
lcd.print(cmd[i]);
i=i-1;
if(i<0){ //避免按"修改"鈕使位數變成負數
i=0;
}
cmd[i]=' ';
lcd.setCursor(i,0);
lcd.print(cmd[i]);
}else if(i<9){
i++;
}
}
}
}