4x4 鍵盤

薄膜按鍵模組(hex keypad)

按鍵偵測與掃描原理

為了方便解說,筆者把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++;

}

}

}

}