Matrix keypad interfacing with a PIC Microcontroller

Matrix keypad interfacing with a PIC Microcontroller

4×4 matrix keypads are commonly used keypads in embedded applications. Such keypads are seen in telephones and other commonly seen applications. Here in this chapter, we discuss in detail about how a matrix keypad is interfaced to a PIC microcontroller.

keypad-pin-arrangement

Matrix Keypad interfacing

The advantage of a matrix keypad is that the use of it will allow the programmer to reduce the number of pins to be used. In a 4×4 matrix keypad, there are four rows and four columns connected to 16 push button switches. It may look like one needs 16 pins for the microcontroller to be connected to the matrix keypad, but practically 16 inputs of keypad interface are possible with the 8 pins of a microcontroller port. All 8 lines can be connected to the same port or different ports based on the application requirements. In fact, 8 port pins of a microcontroller are sufficient for a 4×4 keypad interface using row & column matrix connection technique by saving other 8 bits of the port.

Matrix keypad

Matrix keypad interfacing and key press identification can be explained in a step by step manner which involves a software. First, we input HIGH on row pins. When a key is pressed, the corresponding row and column get shorted. In the second step, a software scans the pins connected to the columns. If it detects a HIGH on any particular column, then it is found that the key press has been made on a key in that column. The third step is to figure out which key is pressed exactly. For this, the software writes logic high on row pins sequentially. The pin of the column on which the pressed key is situated will become high.

Principle of working

4×4 keypads can be connected in three modes.

  1. Normal mode
  2. Pull up mode
  3. Pull down mode

In normal mode, rows are connected to a microcontroller without any pull-up or pull-down resistors. Pull-up and pull-down modes will have a default state on input pins depending on the modes.

Normal mode

In this mode, the row pins are connected to the microcontroller directly. They need to be defined as output pins.

Matrix keypad interfacing - normal modeProcedure of working

  • Connect four column pins and four-row pins to the microcontroller port.

In this example, we use port D of PIC microcontroller.

  • Define column pins as input and row pins as output

Here, we use the first four bits of port D as column pins and last four bits as row pins. Matrix keypad - PIC Microcontroller pin mappingDon’t forget to define 7-4 pins (columns) as inputs and 3-0 pins (rows) as outputs.

TRISD = 0XF0; /*TRISD register decides the direction of the PORT D pins. 
               1 for input and 0 for output */
  • Wait for a key press (initial scanning)

Make all the row pins high, then keep scanning the rows till a keypress get detected.

do {
    PORTD = 0X0F;           // Make Row pins high 
    column = PORTD;         // Read column pin status: Read the port
    column &= 0xF0;         // Read column pin status: Extract column pin status from PortD
    }while(column==0x00);      // Repeat this procedure till a keypress event got detected
  • Detect and identify the pressed key

Check all the possible combinations. For example, if we give a high on row 3 and reads the status of column 1 as high, that means, S9 has got pressed.

Matrix keypad - identifying the pressed key

So we check every possible combination here. Please note: there are many ways to this step, but we are doing the easily understandable way.

Set a row bit high and then scan each line in the column to check whether it is high. If it is high then a key is pressed.

PORTD = 0x01;                        // PORTDbits -> 0000001, D0 is high
if (PORTDbits.RD4)&&(PORTDbits.RD0)
    {                               // S1 is the pressed key
         key = "S1";
    }
elsif (PORTDbits.RD5)&&(PORTDbits.RD0)
    {                               // S5 is the pressed key
         key = "S5";
    }
elsif (PORTDbits.RD6)&&(PORTDbits.RD0)
    {                               // S9 is the pressed key
         key = "S9";
    }
elsif (PORTDbits.RD7)&&(PORTDbits.RD0)
    {                               // S13 is the pressed key
         key = "S13";
    }

PORTD = 0x02;                       // PORDbits -> 00000010, D1 is high
if (PORTDbits.RD4)&&(PORTDbits.RD1)
    {                               // S3 is the pressed key
         key = "S2";
    }
elsif (PORTDbits.RD5)&&(PORTDbits.RD1)
    {                               // S6 is the pressed key
         key = "S6";
    }
elsif (PORTDbits.RD6)&&(PORTDbits.RD1)
    {                               // S10 is the pressed key
         key = "S10";
    }
elsif (PORTDbits.RD7)&&(PORTDbits.RD1)
    {                               // S14 is the pressed key
         key = "S14";
    }
 
 PORTD = 0x04;                       // PORDbits -> 00000100, D2 is high
if (PORTDbits.RD4)&&(PORTDbits.RD2)
    {                               // S3 is the pressed key
         key = "S3";
    }
elsif (PORTDbits.RD5)&&(PORTDbits.RD2)
    {                               // S7 is the pressed key
         key = "S7";
    }
elsif (PORTDbits.RD6)&&(PORTDbits.RD2)
    {                               // S11 is the pressed key
         key = "S11";
    }
 elsif (PORTDbits.RD7)&&(PORTDbits.RD2)
    {                               // S15 is the pressed key
         key = "S15";
    }
  
  PORTD = 0x08;                       // PORDbits -> 00001000, D3 is high
if (PORTDbits.RD4)&&(PORTDbits.RD3)
    {                               // S4 is the pressed key
         key = "S4";
    }
elsif (PORTDbits.RD5)&&(PORTDbits.RD3)
    {                               // S8 is the pressed key
         key = "S8";
    }
elsif (PORTDbits.RD6)&&(PORTDbits.RD3)
    {                               // S12 is the pressed key
         key = "S12";
    }
 elsif (PORTDbits.RD7)&&(PORTDbits.RD3)
    {                               // S16 is the pressed key
         key = "S16";
    }

 

The above steps are essential, but we need to add some noise filtering techniques because noise spikes may get detected as false keypress event in above scanning methods.

Debouncing

These are spurious spikes generated during keypress events. Normally several spikes get generated during a key press because of the mechanical contacts in the switch and it causes multiple spikes, which may be detected as multiple keypress events instead of a single event. Below is an Oscilloscope screenshot of the keypress event. There you can see, there are multiple spikes during the low to high transition.

We can filter these spikes with the help of either a hardware circuit or a software routine. Hardware methods need to use low pass filters in each line which increases the number of components in the circuit. Here we use the easiest way, the software.

We are going to use time window for reading the port status. Introduce a delay between detection and scanning.

By introducing a delay of 100ms between detection and scanning, we can differentiate between spikes and actual key press.

Pull-up mode

Matrix keypad - pull up mode
In this mode, row pins are connected to the microcontroller in pull-up mode, i.e., each line is pulled to high and default state of the pins will be high. So we need to set low to the port to check for the keypress.

if (PORTDbits.RD4)&&(PORTDbits.RD0)
    {                               // S1 is the pressed key
        delay_ms(100);              // 100ms delay for avoiding spike detection
        if (PORTDbits.RD4)&&(PORTDbits.RD0)     // re-check the keypress
        {
            key = "S1";                         // It is S1
        }
        else{}                      // It is a bounce, **else** part is for understanding, not needed in real case       
    }

 

While detecting the keypress,

if !((PORTDbits.RD4)&&(PORTDbits.RD0))

will be the condition to check individual bits. This one checks whether both bits are low.

Pull-down mode

In pull-down mode, all the row pins will be connected to ground through a resistor. So the default state is low. Hence the mode of operation is same as in the case of normal mode.

Matrix keypad - pull down mode

keypad encoder

A keypad encoder is a technique by which the keypad is interfaced to the microcontroller. EDE1144 is a keypad encoder IC with features such as contact debouncing and key auto-repeat which considerably reduces software overhead in the host microcontroller and lessen the I/O pin requirements to just one from eight. The key press data is returned through a serial or parallel interface. The best of advantages is that the use of this IC reduces the work on firmware, which in turn reduces time to market.

 

Further reading: We’ve prepared an extensive guide on PIC Microcontroller.