iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
自我挑戰組

硬體學習日記系列 第 26

Day-26 arduino介紹-8 keypad

  • 分享至 

  • xImage
  •  

今天要介紹的是arduino裡的鍵盤元件-keypad~

這個是模擬器裡的keypad,有16個鍵。
https://ithelp.ithome.com.tw/upload/images/20240903/20168362rlRSbAqm5s.png
先介紹底下的引腳,總共有八個,從左邊往右來看,分別為ROW1、ROW2、ROW3、ROW4、COL1、COL2、COL3、COL4。
那這個keypad順序跟我們在C中學到的陣列是一樣的,ROW1是最上面的列、COL1是最左邊的行,依序往下、往右。
那這八個引腳,要分別接上八個不同的數位腳位,之後寫程式碼執行時會要寫入這八個引腳接到哪個角位。

那在使用keypad前,要先載他的函式庫~叫做Keypad。
然後是接上keypad,這裡我接的腳位是D13~D6。
https://ithelp.ithome.com.tw/upload/images/20240903/20168362CjZMIgqh0C.png

接著是一些使用keypad的設定:
keypad共有4個Row、4個Column,所以我先設兩個常數,分別表示Row及Column的數量:

const int ROWS = 4; //row數量
const int COLS = 4; //column數量

然後設立一個4*4大小的陣列,用來表示此keypad中每一個鍵所代表的值:

char keys[ROWS][COLS] = 
{
  {'1','2','3','A'}, //第一個ROW
  {'4','5','6','B'}, //第二個ROW
  {'7','8','9','C'}, //第三個ROW
  {'*','0','#','D'}  //第四個ROW
};

那這個每一個按鍵的值,不一定需要跟按鍵上印的字一樣,就依照自己的需求去給值就可以了;我也可以在這16個鍵上,依序給A、B、C、D、E、F、…。

然後還記得前面的時候有先接keypad的線嗎~接著就要來寫入接的腳位了,根據剛剛的接線來寫入。

uint8_t rowPins[ROWS] = {13,12,11,10}; //ROW由上到下接的腳位(R1,R2,R3,R4)
uint8_t colPins[COLS] = {9,8,7,6}; //COL由左到右接的腳位(C1,C2,C3,C4)

這邊來解釋一下uint8_t是什麼意思,u是unsigned,int就是integer,8就是位元數,t是typedef,所以uint8_t就是指宣告一個無號整數,有8位,所以值的範圍是0~255。

那keypad的基本設定都設定好了,接著就是輸入的部分,也就是傳送按下的鍵所代表的值到開發板中。

Keypad keypad = Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);

這邊使用到Keypad函式庫中的function,用來處理鍵盤的輸入。
先宣告一個變數為keypad,他的type為Keypad,keypad的值會是Keypad這個function的結果。
接著來看Keypad的每一個參數意思~
makeKeymap()是一個function,他會將一個二維陣列轉化成一個鍵盤的樣子,那括號內放入的變數就是我們先前宣告好的4*4陣列,也就是表示keypad每一個鍵的意思的那個陣列;makeKeymap(keys)執行好後,就會告訴Keypad這個鍵盤矩陣每一個按鍵的位子以及他所代表的值。
那如果是希望按下某個鍵後能產生什麼功能,只要定義好後,makeKeymap也會將此功能傳入Keypad中。
接著是rowPins及colPins,也是剛剛定義過的一維陣列,這兩個陣列負責告訴Keypad,鍵盤接到了開發板中的哪八個腳位。
最後是ROWS及COLS,這兩個則是向Keypad表達這個鍵盤有幾個row、幾個column。
那目前這些定義都不用寫在setup或loop裡,就像是寫C時定義全域變數或寫function一樣。

在keypad的部分,setup是不用特別處理他的初始化,所以單純只使用keypad的話,setup應該是可以為空。

接著就是loop執行的部分。

void loop()
{
  char key = keypad.getKey();
  if( key != NO_KEY ){
    lcd.print(key);
  }
}

在這個loop裡,我要在lcd印上我剛剛在keypad按了哪個鍵。
在Keypad函式庫中,可以透過getkey()來取得剛剛按的值;我將getkey()的回傳值儲存在key這個變數中。
那如果按下後沒有得到任何的值,getkey()就會回傳「NO_KEY」,所以如果key儲存的值不等於NO_KEY,就表示有按鈕被按、且值傳送到key儲存,然後印到lcd中。

好啦~那keypad的基本設定跟操作都介紹完了~
接下來是簡單的操作,在按下keypad後,我要lcd輸出我在鍵盤按下了什麼鍵:

#include <LiquidCrystal.h>
#include <Keypad.h>

LiquidCrystal lcd(19,18,17,16,15,14);

const int ROWS = 4;
const int COLS = 4;
char keys[ROWS][COLS] = 
{
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

uint8_t rowPins[ROWS] = {13,12,11,10};
uint8_t colPins[COLS] = {9,8,7,6};

Keypad keypad = Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);

void setup()
{
  Serial.begin(9600);
  lcd.begin(16,2);
}

void loop()
{
  char key = keypad.getKey();

  if( key != NO_KEY ){
    lcd.print(key);
    delay(1000);
  }

  lcd.clear();
}

接線的部分則是:
https://ithelp.ithome.com.tw/upload/images/20240903/20168362pIh4py3IUb.png
當我按下keypad的其中一個鍵,lcd就會顯示我按的鍵是哪一個,顯示一秒後就消失。
那因為我要求lcd要顯示1秒,所以在這顯示的1秒內,如果按其他鍵,是不會有反應的,得等1秒結束。

寫一下改良版:

void loop()
{
  char key = keypad.getKey();

  if( key != NO_KEY ){
    lcd.clear(); //清空畫面
    lcd.print(key);
  }
  
}

跟上一個的差別是,把delay移除、在lcd印字前先清空畫面。
有沒有清空畫面的差異是,如果有清空,則每一次按下按鈕時,值都會固定顯示在左上第一格。
https://ithelp.ithome.com.tw/upload/images/20240903/20168362ICVGtpS8Kn.png
那如果沒有清空畫面,按下的值就會一直存在,所以再按下其他按鈕時,字會接著印在後面。
https://ithelp.ithome.com.tw/upload/images/20240903/20168362M3Ur7Ncds6.png

那接著來點lcd的小補充。
如果按照上述的程式碼,我按了16個鍵後,第一排滿了,接下來再按任何的數值,畫面都不會有改變。

那如果我希望第一排滿了之後,改印在第二排,就要來做點設定:

int cnt = 0;
void loop()
{
  char key = keypad.getKey();

  if( key != NO_KEY ){
    cnt += 1;
    if( cnt == 17 ){
      lcd.setCursor(0,1);
    }
    lcd.print(key);
  }
  
}

我新增了一個cnt,負責計數目前按了幾個鍵;當按到第17個鍵,就表示要換到下一行,所以就將cursor移到(0,1)的位子,這樣就會在第一排滿了之後,接這印在第二排了。
https://ithelp.ithome.com.tw/upload/images/20240903/20168362HpkMOCnzko.png
我本來寫成if(cnt > = 17 ),但這樣就是17之後每次游標都會停留在(0,1)的地方XD

喔對,如果沒有換行,那按到第41個鍵時,就會印到第二排囉~因為其實這個LCD板子每一排都有40個位子,會顯示出來的卻只有16格。

那今天就先這樣~keypad是一個很神奇的東西吧XD


上一篇
Day-25 arduino介紹-7 元件 蜂鳴器
系列文
硬體學習日記26
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言