參考:https://swf.com.tw/?p=917
利用Time 1中斷,每0.1秒去掃描看沒有按鍵被按。
Time中斷可參考http://tomyam-yang.blogspot.com/2017/06/arduino-timer-as-counter.html
提升電阻參考https://www.arduino.cc/en/Tutorial/DigitalPins
volatile char key_pad;因為key_pad變數使用在中斷內如果不使用volatile去定義,有可能這一次編譯可以正常執行,下一次編譯卻有問題,詳細說明可參考http://newscienceview.blogspot.com/2013/09/c-volatile.html
將多維陣列keymap[][]傳入副函式scan_key的方法如下:
key_pad=scan_key(KEY_COLS,KEY_ROWS,(char *)keymap,colPins,rowPins);
key_pad=scan_key(KEY_COLS,KEY_ROWS,*keymap,colPins,rowPins);
key_pad=scan_key(KEY_COLS,KEY_ROWS,keymap[0],colPins,rowPins);
key_pad=scan_key(KEY_COLS,KEY_ROWS,&keymap[0][0],colPins,rowPins);
陣列的參數傳遞可以參考C陣列、[C++]如何將多維陣列傳入副函式、二維陣列與雙重指標之間的關係
char scan_key(byte,byte,char *,byte *,byte *);
#define KEY_ROWS 4 // 按鍵模組的列數
#define KEY_COLS 4 // 按鍵模組的行數
const byte colPins[KEY_COLS] = {9, 8, 7, 6}; // 設定「行」腳位
const byte rowPins[KEY_ROWS] = {13, 12, 11, 10}; // 設定「列」腳位
const char keymap[KEY_ROWS][KEY_COLS] = {
{'A', '7', '8', '9'},
{'B', '4', '5', '6'},
{'C', '1', '2', '3'},
{'D', 'E', 'F', '0'}
};
volatile char key_pad;
void setup() {
byte i;
//設定中斷1參數:
TCCR1A=0x00;
TCCR1B=0b00000101;//設定除頻1024 15625HZ
TCNT1=-1562; //約0.1秒掃描一次
TIMSK1 |=0x01; //啟動Timer中斷
key_pad=0;
for ( i = 0; i <= 3; i++) {
pinMode(rowPins[i], INPUT);
pinMode(colPins[i], OUTPUT);
digitalWrite(colPins[i], HIGH);
digitalWrite(rowPins[i], HIGH);//啟動上拉電阻
}
Serial.begin(9600);
}
void loop() {
while(key_pad)
{
Serial.println(key_pad);
key_pad=0;
}
}
ISR(TIMER1_OVF_vect)
{
TIMSK1 &=0xfe;
key_pad=scan_key(KEY_COLS,KEY_ROWS,(char *)keymap,colPins,rowPins);
TCNT1=-1562;
TIMSK1 |=0x01;
}
char scan_key(byte col,byte row,char *key_map,byte *col_pin,byte *row_pin)
{
unsigned long time_;
byte i,j;
byte scanVal; // 暫存掃描到的按鍵值low or high
time_=millis();
for (i = 0; i < row; i++) { //按著不放的情況下不用理它
scanVal=digitalRead(*(row_pin+i));
if (scanVal == LOW)
{
return 0;
}
}
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
digitalWrite(*(col_pin+j),LOW);
scanVal=digitalRead(*(row_pin+i));
if (scanVal == LOW) { // 如果輸入值是「低電位」…
for(;;)
{
if((millis()-time_)>1000)
{
return 0;
}
delay(100);
scanVal=digitalRead(*(row_pin+i));
if (scanVal == LOW)
{
return *(key_map+i*row+j);
}
}
}
digitalWrite(*(col_pin+j),HIGH);
}
}
return 0;
}