Both the rows and columns scanning technique (called "Direct Connection" below - 8 PIC I/O pins for a 4x4 keypad matrix) and the use of the PCF8574 port expander (2 PIC I/O pins for a 4x4 keypad matrix) were constructed and tested.
"Direct" Connection to I/O pins
The direct connection of the 4x4 keypad matrix to the PIC 18F248 in terms of the physical circuitry is straight forward (see the Schematics Section). The "rows" of the keypad matrix require 10k pullup resistors (although the option of using the PIC port internal pullups can be used, if the port has this option). Which sets of connection pins of the keypad matrix are defined as "rows" and "columns" is not important, and are defined using the settings in the firmware file "KBC.c" (#define statements for the I/O pins and the KEYS array).
The following code is a listing of "KBC.c" which performs the scanning of the matrix keypad to determine which key, if any, has been pressed. The function kbd_getc() is repeatly called from the main program loop to poll the keypad.
#define row0 PIN_C4 //Keypad I/O pins
#define row1 PIN_C5
#define row2 PIN_C6
#define row3 PIN_C7
#define col0 PIN_C0
#define col1 PIN_C1
#define col2 PIN_C2
#define col3 PIN_C3
// set the keypad layout
char const KEYS[4][4] =
{{'u','d','A','B'},
{'7','4','1','*'},
{'8','5','2','0'},
{'9','6','3','#'}};
#define KBD_DEBOUNCE_FACTOR 33
void kbd_init() { //if external pullups not used
//set_tris_b(0xF0);
//output_b(0xF0);
//port_b_pullups(true);
}
short int ALL_ROWS (void) {
if(input (row0) & input (row1) & input (row2) & input (row3))
return (0);
else
return (1);
}
char kbd_getc() {
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
byte col, kchar, row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
switch (col) {
case 0:
output_low(col0); output_high(col1); output_high(col2); output_high(col3);
break;
case 1:
output_high(col0); output_low(col1); output_high(col2); output_high(col3);
break;
case 2:
output_high(col0); output_high(col1); output_low(col2); output_high(col3);
break;
case 3:
output_high(col0); output_high(col1); output_high(col2); output_low(col3);
break;
}
if(kbd_down) {
if(!ALL_ROWS()) {
kbd_down=false;
kchar=last_key;
last_key='\0';
}
} else {
if(ALL_ROWS()) {
if(!input (row0)) row=0;
else if(!input (row1)) row=1;
else if(!input (row2)) row=2;
else if(!input (row3)) row=3;
last_key =KEYS[row][col];
kbd_down = true;
} else {
++col;
if(col==4) col=0;
}
}
kbd_call_count=0;
}
return(kchar);
}
The following is an example of how to use "KBC.c" to get a key press from a 4x4 keypad matrix and display the result on a LCD.
#include <PIC18F248.h>
#include <LCD.C>
#include <KBD.C>
#zero_ram //all variables automatically initialised to 0
#define LCD_ENABLE_PIN PIN_B0
#define LCD_RS_PIN PIN_B1
#define LCD_RW_PIN PIN_B2
#define LCD_DATA4 PIN_B4
#define LCD_DATA5 PIN_B5
#define LCD_DATA6 PIN_B6
#define LCD_DATA7 PIN_B7
void main() {
int k;
lcd_init();
kbd_init();
delay_ms(1000);
lcd_putc("\fInput\n");
lcd_putc("here:");
output_c (0x00); //clear port C
do {
k=kbd_getc();
if(k!=0)
if(k=='*') { //'*' = 'clear screen'
lcd_putc("\fInput\n");
lcd_putc("here:"); }
else
lcd_putc(k);
} while (TRUE);
}
Keypad via PCF8574 port expander
The use of a "port expander" IC is a handy technique in general for minimising the number of I/O pins required from a PIC microcontroller to interface peripherals. The PCF8574 provides general purpose remote I/O expansion via the I2C protocol. The device consists of an 8-bit quasi-bidirectional port, the I2C-bus interface and three hardware address pins which allows for use of up to 8 PCF8574 devices in a circuit (i.e., it is possible to have 8 PCF8574 x 8 pins = 64 I/O pins controlled by 2 I/O pins from a PIC microcontroller).
The downside of this additional functionality is of course added complexity of the circuit (although this is not particularly onerous - see the Schematics Section) and of the firmware.
The driver code for the PCF8574 is given below in the Downloads Section. This code enables setting of I2C control pins on the PIC microcontroller and the hardware address (or addresses) of the PCF8574.
The file "KDB_I2C.c" (available in the Downloads Section) contains the revised code to utilise the PCF8574 to scan an attached keypad matrix (4x4 matrix in this case). As for the "direction connection" method, the function kbd_getc() is repeatly called from the main program loop to poll the keypad. Therefore, with the additional of the include files for the PCF8574 and "KDB_I2C.c" the main program loop/code does not require any changes.
Downloads
Only Logged-In Members can add comments