Keyboard appearance
The keyboard generally looks like this. The most common ones on Taobao are 4x4 and 4x3. There are also keyboards with matrix keys instead of membrane keys, but the principles are similar.
An ordinary 4x4 keyboard
Keyboard schematic diagram
Schematic diagram of the keyboard
Generally speaking, there are as many pins as there are rows and columns on a keyboard. When a button is pressed, the switch of the row and column where the button is located is closed, and the pins between the rows and columns are connected.
MCU implements
4x3 keyboard
Based on the keyboard schematic, it is not difficult to imagine that we need to use pin scanning to detect which key is pressed.
Set the row pins as input and the column pins as output (of course, you can also do it the other way around). Only set one column pin to a high level at a time, and then detect the level of the row pins to detect which key on the keyboard is pressed.
Initialize pin
void keyboard_init(){
//Set the row pin to input
P3DIR &= ~BIT6; //Set the P3.6 port to input
P3REN |= BIT6; //Enable P3.6 to pull up/down resistor
P3OUT &= ~BIT6; //Set P3.6 to pull down resistor mode
P3SEL &= ~BIT6; //P3.6 is I/O interface
P7DIR &= ~BIT0; //Set P7.0 port to input
P7REN |= BIT0; //Enable P7.0 to pull up/down resistor
P7OUT &= ~BIT0; //Set P7.0 to pull down resistor mode
P7SEL &= ~BIT0; //P7.0 is I/O interface
P6DIR &= ~BIT4; //Set P6.4 port to inputP6REN
|= BIT4; //Enable P6.4 to pull up/down resistorP6OUT
&= ~BIT4; //Set P6.4 to pull down resistor modeP6SEL
&= ~BIT4; //P6.4 is I/O interface
P6DIR &= ~BIT3; //Set P6.3 port to input
P6REN |= BIT3; //Enable 6.3 to pull up/down resistor
P6OUT &= ~BIT3; //Set P6.3 to pull down resistor mode
P6SEL &= ~BIT3; //P6.3 is I/O interface
//Set the column pin to output
P6DIR |= BIT2+BIT1+BIT0; //Set the P6.2,1,0 port to output
P6OUT &=~(BIT2+BIT1+BIT0);
The idea of
scanning the pins
is to set the first column, the second column, etc. to high levels in turn in a do-while loop, and then detect whether the levels of the first row, the second row, etc. are high. If they are high, it means that a key is pressed, the rows and columns are turned on, the loop is exited, and the key value is returned.
char scanKey(){
//Scan column
char key_value=0;
unsigned char state=0;
do{
key_value=0;
if(state==0){
P6OUT |= BIT0;
P6OUT &=~ (BIT1+BIT2);
}else if(state==1){
P6OUT |= BIT1;
P6OUT &=~ (BIT0+BIT2);
}else if(state==2){
P6OUT |= BIT2;
P6OUT &=~ (BIT0+BIT1);
}
if(++state==3) state=0;
if(P6OUT & BIT0)
key_value = BIT5;
if(P6OUT & BIT1)
key_value = BIT6;
if(P6OUT & BIT2)
key_value = BIT7;
if(P3IN & BIT6) key_value |= BIT0;
else key_value &= ~BIT0;
if(P7IN & BIT0) key_value |= BIT1;
else key_value &= ~BIT1;
if(P6IN & BIT4) key_value |= BIT2;
else key_value &= ~BIT2;
if(P6IN & BIT3) key_value |= BIT3;
else key_value &= ~BIT3;
}while((key_value&0x0f)==0);//Until a row is pressed
switch(key_value){//Return the pressed character
case 129: return '1';
case 65: return '2';
case 33: return '3';
case 130: return '4';
case 66: return '5 ';
case 34: return '6';
case 132: return '7';
case 68: return '8';
case 36: return '9';
case 136: return '*';
case 72: return '0';
case 40: return '#';
default: return 0;
}
}
4x4 keyboard
Similarly, the 4x4 keyboard also detects which button is pressed by row and column scanning. Readers can modify the program to achieve it by themselves.
The following is the reference code:
Initialize port
void keyboard_init(){
//Set the row pin to input
P3DIR &= ~BIT5; //Set P3.5 port to input
P3REN |= BIT5; //Enable 3.5 to pull up/down resistor
P3OUT &=~ BIT5; //Set P3.5 to pull down resistor mode
P3SEL &= ~BIT5; //P3.5 is I/O interface
P3DIR &= ~BIT6; //Set P3.6 port to inputP3REN
|= BIT6; //Enable P3.6 to pull up/down resistorP3OUT
&=~ BIT6; //Set P3.6 to pull down resistor modeP3SEL
&= ~BIT6; //P3.6 is I/O interface
P7DIR &= ~BIT0; //Set P7.0 port to input
P7REN |= BIT0; //Enable P7.0 to pull up/down resistor
P7OUT &=~ BIT0; //Set P7.0 to pull down resistor mode
P7SEL &= ~BIT0; //P7.0 is I/O interface
P6DIR &= ~BIT4; //Set P6.4 port to inputP6REN
|= BIT4; //Enable P6.4 to pull up/down resistorP6OUT
&=~ BIT4; //Set P6.4 to pull down resistor modeP6SEL
&=~ BIT4; //P6.4 is I/O interface
//Set the column pin to output
P6DIR |= BIT3+BIT2+BIT1+BIT0; //P6.3,2,1,0 port is set to output
P6OUT &=~(BIT3+BIT2+BIT1+BIT0);
}
Scan pin
char scanKey(){
//Scan column
char key_value=0;
unsigned char state=0;
do{
key_value=0;
if(state==0){
P6OUT |= BIT0;
P6OUT &=~ (BIT1+BIT2+BIT3);
}else if(state==1){
P6OUT |= BIT1;
P6OUT &=~ (BIT0+BIT2+BIT3);
}else if(state==2){
P6OUT |= BIT2;
P6OUT &=~ (BIT0+BIT1+BIT3);
}else if(state==3){
P6OUT |= BIT3;
P6OUT &=~ (BIT0+BIT1+BIT2);
}
if(++state==4) state=0;
if(P6OUT & BIT0)
key_value = BIT4;
if(P6OUT & BIT1)
key_value = BIT5;
if(P6OUT & BIT2)
key_value = BIT6;
if(P6OUT & BIT3)
key_value = BIT7;
if(P3IN & BIT5) key_value |= BIT0;
else key_value &=~ BIT0;
if(P3IN & BIT6) key_value |= BIT1;
else key_value &=~ BIT1;
if(P7IN & BIT0) key_value |= BIT2;
else key_value &=~ BIT2;
if(P6IN & BIT4) key_value |= BIT3;
else key_value &=~ BIT3;
}while((key_value&0x0f)==0);//Until a row is pressed
switch(key_value){//Return the pressed character
case 129: return '1';
case 65: return '4';
case 33: return '7';
case 17: return '*';
case 130: return '2 ';
case 66: return '5';
case 34: return '8';
case 18: return '0';
case 132: return '3';
case 68: return '6';
case 36: return '9';
case 20: return '#';
case 136: return 'A';
case 72: return 'B';
case 40: return 'C';
case 24: return 'D';
default: return 0;
}
}
Conclusion
The keyboard is one of the simplest peripherals of MSP430F5529. As long as you master the way of scanning rows/columns, you can handle all kinds of different keyboards with ease.
The scanKey() function in this article uses a loop to detect key presses. PORT1 and PORT2 of MSP430F5529 support interrupt functions. You can also plug a keyboard into PORT1 or PORT2 and use interrupts to detect whether a key is pressed.
|