MCU Examples.com
PIC Microcontroller Project Examples, free source codes and resources collection.


Matrix Keypad interfacing with PIC microcontroller.

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.

 

 

Keypad Scan Algorithm.

 

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).

 

  • 1. ScanKeypad(void) routine supply logic 0 (0V or GND) to all 4 keypad row wires named R1, R2, R3 and R4 in schematic diagram.(Assume that no key is pressed and since all columns has 1k pull down resisters connected as in schematic diagram. This will cause PICs PORTB0:3 pins to read logic 0 if we read them)

  • 2. Next ScanKeypad(void) will set RD4 (ROW1) pin to Logic High (5V). Now if one or more key from keypad ROW1 pressed, Logic High will be passed through respective switch to PICs respective PORTB0:3 inputs. Pressing keys from any other row will not have any effect on this because these rows have logic 0.

  • 3. Now we read all 4 columns (PORTB0:3) at once and get that data in to unsigned int variable. Since we read only 4 bits, these bits will be recorded in bits 0 to 3 in keys variable. Other 12 bits of keys variable will be set to 0. If any switch belongs to row one pressed, that respective bit will be set.

  • 4. Now we shift least significant 4 bits with row 1 keypad data in keys variable to most significant 4 bits of keys variable in ScanKeypad(void) routine. i.e. shift keys bits 0:3 to keys bits 12:15.

  • 5. Next make ROW1 (RD4) logic 0 and ROW2 (RD5) logic1. Read PORTB0:3 and get result tin to unsigned int keys_tmp variable. Then shift result left by 8 and position row2 data acquired in to keys_tmp bits 8:11. Then combine (bit wise OR) keys and keys_tmp variables in to keys variable. Now we have row1 and row 2 switch status in keys variable bits 8:15.

  • 6. Repeat 5 for column 3 with respective modifications, (refer example code) and take row 3 key status in to keys variable bits 4:7. Now we have rows 1,2 and 3 data in keys bits 4:15

  • 7. Repeat 5 for column 4 with respective modifications, (refer example code).

  • 8. Now we have status of all 16 keys in variable keys and return that variable from ScanKeypad() routine

  • 9. If we have at least one key pressed, then return from ScanKeypad()  will be non zero.

  • 10. If we get non zero value from ScanKeypad(), we should de-bounce keypad and identify really pressed keys and process them as required.


//
// 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;
     
}

//****************************************************************************************

 

 

 

Custom Search