The Arduino detects which button is pressed by detecting the row and column pin that’s connected to the button.
This happens in four steps:
1. First, when no buttons are pressed, all of the column pins are held HIGH, and all of the row pins are held LOW:
2. When a button is pressed, the column pin is pulled LOW since the current from the HIGH column flows to the LOW row pin:
3. The Arduino now knows which column the button is in, so now it just needs to find the row the button is in. It does this by switching each one of the row pins HIGH, and at the same time reading all of the column pins to detect which column pin returns to HIGH:
4. When the column pin goes HIGH again, the Arduino has found the row pin that is connected to the button:
----------------------
int row = 0;
int col = 0;
bool keypress = true;
int interrupt_count=0;
bool skip_interrupt = false;
char hexaKeys[4][4] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
void setup()
{
Serial.begin(115200);
DDRB = 0b00001111; //pin 8-11 as output
PORTB |= 0b00001111; //set pin 8-11 high
Serial.print("initial PINB ");
printBin(PINB);
Serial.println();
Serial.print("initial PIND ");
printBin(PIND);
Serial.println();
PCICR |= 0b00000100; //enable PCMSK2 (group 2: PCINT16 to PCINT23)
PCMSK2 |= 0b11110000; //pin 4-7 could trigger interrupt
}
void loop()
{
}
ISR (PCINT2_vect){
//1st interrupt happens when key is pressed, one input pin (col) goes high
//2nd interrupt happens when output pins (row) are set to low one by one
//to find which one casue the input pins (col) to go low. That's the row #
//3rd interrupt happens when output pins are set to high for detecting next keypress
//if key is pressed, input pins (col) goes high
//4th interrupt happens when key is released, input goes low
interrupt_count++;
Serial.print("interrupt count ");
Serial.println(interrupt_count);
Serial.print("keypress ");
Serial.println(keypress);
Serial.print("skip interrupt ");
Serial.println(skip_interrupt);
if(skip_interrupt){
skip_interrupt = false;
return;
}
if(keypress){
//detect keypressed and interrupt on rising edge of input pins
//if pin8-11 are high(all rows are high)
if(PINB & 0b00001111 == 0b00001111){
Serial.println("finding column");
switch(PIND & 0b11110000){
case 0b10000000:
col = 0;
break;
case 0b01000000:
col = 1;
break;
case 0b00100000:
col = 2;
break;
case 0b00010000:
col = 3;
break;
}
}
//set pin8-11 low one by one
for(int i=0; i< 4; i++){
byte b = 0b00000000;
switch(i){
case 0:
b=0b11110111; //set pin 11 low
break;
case 1:
b=0b11111011; //set pin 10 low
break;
case 2:
b=0b11111101; //set pin 9 low
break;
case 3:
b=0b11111110; //set pin 8 low
break;
}
Serial.print("loop to find row. Iteration ");
Serial.println(i+1);
PORTB = PINB & b;
Serial.print("pinB ");
printBin(PINB);
Serial.println();
Serial.print("pinD ");
printBin(PIND & 0b11110000);
Serial.println();
//if pin7-4 are low after pin11-8 are set low
if(!(PIND & 0b11110000)){
//found row #
row = i;
keypress = false;
break;
}
}
Serial.print("row col ");
Serial.print(row);
Serial.print(" ");
Serial.println(col);
Serial.println();
Serial.print("key pressed is ");
Serial.println(hexaKeys[row][col]);
Serial.println();
//reset pin 11-8 high for detect next keypress,
//next interrupt will be ignored to prevent extra code execution
Serial.println("reset output pins high for detecting next keypress");
skip_interrupt = true;
PORTB = PINB | 0b00001111;
}
//enable keypress detection
if(interrupt_count == 4){
interrupt_count = 0;
keypress = true;
}
}
void printBin(byte aByte) {
for (int8_t aBit = 7; aBit >= 0; aBit--)
Serial.write(bitRead(aByte, aBit) ? '1' : '0');
}
reference:
pin change interrupt
No comments:
Post a Comment