MCU Examples.com
PIC Microcontroller Project Examples, free source codes and resources collection.
Matrix keypads are very useful when designing certain systems which needs user input. These keypads are constructed by arranging push button switches in rows and columns as shown in Fig.1. Scanning keypad to detect pressed keys involves several steps and there are several methods to achieve this. The method presented here is capable of detecting more that one key press at time and encode that information in single 16bit (unsigned int) variable. For example this keypad scan routine can be used to detect key presses like CTRL+C in computer keypads.
The example program given in this page uses schematic diagram shown and uses Microchip C18 compiler. The example program will display number of key pressed in 7 segment LED display. If more than one key pressed at a time, it will display ‘H’ character. Schematic diagram shown also shows ICD2 connection which is optional and you can use any programmer/debugger to upload this program to PIC.
Example program has function “ unsigned int ScanKeypad(void) ” where you can use this in your codes provided that keypad is connected to PICs pins as given in schematic bellow.
Scanning any matrix keypad involves several steps. The operation algorithm of example ScanKeypad(void) routine given here is explained in following steps. This routine uses logic operations instead of assigning values to ports because we can change only necessary pins while not touching unused pin values. This is very useful when you have other IP or OP devices connected to remaining pins of same port used by keypad. i.e. PORTB4:7 and PORTD0:3 in this example. ScanKeypad(void) routine should be called only after setting ROW pins and OP and Column pins as IP from main program via setting and clearing appropriate TRIS bits (shown in example code).
// // Designed by www.MCUExamples.com // rasika0612@gmail.com // Following code is compiled by Microchip C18 compiler // Example shows how to use 4x4 matrix keypad with 7 segment LED display // #include <p18f4520.h> #include <delays.h> #pragma config OSC = HS // 20MHz Crystal, (HS oscillator) #pragma config PBADEN = OFF // PORTB<4:0> pins are configured as digital I/O on Reset) #pragma config WDT = OFF // watch dog timer off #pragma config LVP = OFF // Low voltage program off unsigned int ScanKeypad(void); unsigned char LED_PATTERN[]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0xEE,0x3E,0x9c,0x7A,0x9E,0x8E,0x6E}; void main() { unsigned int keystatus; ADCON1=0x0f; // Make all pins digital in PORTA and PORTB. TRISC=0x00; // PORTC connected to 7 segment LED display. so it is O/P TRISB=0x0F; // PORTB0:3 are keypad colomn inputs TRISD=0xF0; // PORTD4:7 are outputs to keypad from PIC LATC=0; // Turn off all segments of 7 segment display while(1) { keystatus=ScanKeypad(); if(keystatus!=0) { // atleast one key pressed so debounce. //refer switch debouncing @ http://www.mcuexamples.com/push-buttons-and-switch-debouncing-with-PIC.php Delay10KTCYx(5); //wait 10mS keystatus=keystatus&ScanKeypad(); // get verified key presses after debounce switch(keystatus) { case 0x0001: LATC=LED_PATTERN[0];break; case 0x0002: LATC=LED_PATTERN[1];break; case 0x0004: LATC=LED_PATTERN[2];break; case 0x0008: LATC=LED_PATTERN[3];break; case 0x0010: LATC=LED_PATTERN[4];break; case 0x0020: LATC=LED_PATTERN[5];break; case 0x0040: LATC=LED_PATTERN[6];break; case 0x0080: LATC=LED_PATTERN[7];break; case 0x0100: LATC=LED_PATTERN[8];break; case 0x0200: LATC=LED_PATTERN[9];break; case 0x0400: LATC=LED_PATTERN[10];break; case 0x0800: LATC=LED_PATTERN[11];break; case 0x1000: LATC=LED_PATTERN[12];break; case 0x2000: LATC=LED_PATTERN[13];break; case 0x4000: LATC=LED_PATTERN[14];break; case 0x8000: LATC=LED_PATTERN[15];break; default: LATC=LED_PATTERN[16];break; // display H if more than one key pressed at a time } } } } //**************************************************************************************** //Function ScanKeypad() // input: NONE // Output: unisgned int value (16bit) where each bit represents a key from key pad and // if key press detected, repective bit will be set to 1; // 16 bits represent 16 keys and simultaneous key presses are encoded in this // return value. // *make sure you set TRIS bits of ports accordingly before calling this routine. // unsigned int ScanKeypad(void) { unsigned int keys,keys_tmp; LATD=LATD&0x0F; // make sure PORTD4:7 pins are LOW without changing other PORTD pins LATD=LATD|0b00010000; // ebable ROW1 of keypad( make RD4 pin 1) Nop(); keys=LATB&0x0F; // read column1 of keypad (we need to read only PORTB0:3) keys=keys<<12; // put column1 values in keys15:12 bits LATD=LATD&0x0F; // make sure PORTD4:7 pins are LOW without changing other PORTD pins LATD=LATD|0b00100000; // enable ROW2 of keypad Nop(); keys_tmp=LATB&0x0f; // read column2 of keypad keys_tmp=keys_tmp<<8; // place column 2 key values in keys_tmp8:11 keys=keys|keys_tmp; //combine comomn 1 and 2 data in to keys LATD=LATD&0x0F; // make sure PORTD4:7 pins are LOW without changing other PORTD pins LATD=LATD|0b01000000; // enable ROW3 of keypad Nop(); keys_tmp=LATB&0x0f; // read column3 of keypad keys_tmp=keys_tmp<<4; // place column 3 key values in keys_tmp4:7 keys=keys|keys_tmp; //combine comomn 1 and 2 nad 3 data in to keys LATD=LATD&0x0F; // make sure PORTD4:7 pins are LOW without changing other PORTD pins LATD=LATD|0b1000000; // enable ROW2 of keypad Nop(); keys_tmp=LATB&0x0f; // read column2 of keypad keys=keys|keys_tmp; //combine comumn 1,2,3,4 data in to keys return keys; } //****************************************************************************************