Connecting Martix Keypad to Microcontroller

Microcontroller Topics
Post Reply
User avatar
Reginald
Sergeant Major
Sergeant Major
Posts: 29
Joined: Mon Aug 03, 2009 9:54 pm
Location: Mount Lavinia

Connecting Martix Keypad to Microcontroller

Post by Reginald » Sun Sep 20, 2009 6:11 am

Introduction

Keypads are a part of HMI or Human Machine Interface and play really important role in a small embedded system where human interaction or human input is needed. Martix keypads are well known for their simple architecture and ease of interfacing with any microcontroller. In this part of tutorial we will learn how to interface a 4x4 matrix keypad with AVR and 8051 microcontroller. Also we will see how to program then in Assembly and C.

Constructing a Matrix Keypad
Construction of a keypad is really simple. As per the outline shown in the figure below we have four rows and four columns. In between each overlapping row and column line there is a key.
keypad.gif
keypad.gif (1.44 KiB) Viewed 3293 times
So keeping this outline we can construct a keypad using simple SPST Switches as shown below:
keypad-schematic.gif
keypad-schematic.gif (7.67 KiB) Viewed 3293 times
Now our keypad is ready, all we have to do is connect the rows and columns to a port of microcontroller and program the controller to read the input.

Scanning a Matrix Keypad

There are many methods depending on how you connect your keypad with your controller, but the basic logic is same. We make the columns as i/p and we drive the rows making them o/p, this whole procedure of reading the keyboard is called scanning.

In order to detect which key is pressed from the matrix, we make row lines low one by one and read the columns. Lets say we first make Row1 low, then read the columns. If any of the key in row1 is pressed will make the corresponding column as low i.e if second key is pressed in Row1, then column2 will give low. So we come to know that key 2 of Row1 is pressed. This is how scanning is done.

So to scan the keypad completely, we need to make rows low one by one and read the columns. If any of the button is pressed in a row, it will take the corresponding column to a low state which tells us that a key is pressed in that row. If button 1 of a row is pressed then Column 1 will become low, if button 2 then column2 and so on...

Now lets move on to the programming part of keypad in our next section.

Keypad Connections with AVR Microcontroller
keypad-avr-th.gif
keypad-avr-th.gif (17.75 KiB) Viewed 3293 times
Circuit shown above is for demonstration and does not include any reset and crystal circuit. For practical use you need to have a reset circuit and crystal.

Keypad Connections with 8051 Microcontroller
keypad-8051-th.gif
keypad-8051-th.gif (18.15 KiB) Viewed 3293 times
Circuit shown above is for demonstration and does not include any reset and crystal circuit. For practical use you need to have a reset circuit and crystal.

Programming AVR Microcontroller

ASM Code

Code: Select all

.include "8515def.inc"

.equ col1 = PINA0
.equ col2 = PINA1
.equ col3 = PINA2
.equ col4 = PINA3

.def keyval = r16
.def temp = r17
.def flags = r18

.equ keyport = PORTA
.equ pressed = 0

key_init:
        ldi keyval,$F0          ;Make Cols as i/p
        out DDRA, keyval        ;and Rows as o/p
        ldi keyval,$0F          ;Enable pullups
        out keyport, keyval     ;on columns
        ret

get_key:
        ldi keyval,$0           ;Scanning Row1
        ldi temp,$7F            ;Make Row1 low
        out keyport,temp        ;Send to keyport
        rcall read_col          ;Read Columns

        sbrc flags,pressed      ;If key pressed
        rjmp done               ;Exit the routine

        ldi keyval,$4           ;Scanning Row2
        ldi temp,$BF            ;Make Row2 Low
        out keyport,temp        ;Send to keyport
        rcall read_col          ;Read Columns

        sbrc flags,pressed      ;If key pressed
        rjmp done               ;Exit from routine

        ldi keyval,$8           ;Scanning Row3
        ldi temp,$DF            ;Make Row3 Low
        out keyport,temp        ;Send to keyport
        rcall read_col          ;Read columns

        sbrc flags,pressed      ;If key pressed
        rjmp done               ;Exit the routine

        ldi keyval,$C           ;Scanning Row4
        ldi temp,$EF            ;Make Row4 Low
        out keyport,temp        ;send to keyport
        rcall read_col          ;Read columns

done:
        ret

read_col:
        cbr flags, (1<<pressed) ;Clear status flag

        sbic PINA, col1         ;Check COL1
        rjmp nextcol            ;Go to COL2 if not low

hold:
        sbis PINA, col1         ;Wait for key release
        rjmp hold
        sbr flags, (1<<pressed) ;Set status flag
        ret                     ;key 1 pressed
nextcol:
        sbic PINA,col2          ;Check COL2
        rjmp nextcol1           ;Goto COL3 if not low

hold1:
        sbis PINA, col2         ;Wait for key release
        rjmp hold1
        inc keyval              ;Key 2 pressed
        sbr flags,(1<<pressed)  ;Set status flag
        ret
nextcol1:
        sbic PINA,col3          ;Check COL3
        rjmp nextcol2           ;Goto COL4 if no pressed

hold2:
        sbis PINA, col3         ;Wait for key release
        rjmp hold2
        inc keyval              ;Key 3 pressed
        inc keyval
        sbr flags, (1<<pressed) ;Set status flag
        ret
nextcol2:
        sbic PINA,col4          ;Check COL4
        rjmp exit               ;Exit if not low

hold3:
        sbis PINA, col4         ;Wait for key release
        rjmp hold3
        inc keyval              ;Key 4 Pressed
        inc keyval
        inc keyval
        sbr flags, (1<<pressed) ;Set status flag
        ret
exit:
        clr keyval              ;reset keyval
        cbr flags, (1<<pressed) ;No Key Pressed
        ret
C Code

Code: Select all

#include <avr/io.h>             // Include file for AVR
#define keyport PORTA           //Keypad Port
#define keyportddr DDRA         //Data Direction Register
#define keyportpin PINA         //Keypad Port Pins

#define col1 PA0                //Column1 PortA.0
#define col2 PA1                //Column2 PortA.1
#define col3 PA2                //Column3 PortA.2
#define col4 PA3                //Column4 PortA.3

#define TRUE 1
#define FALSE 0

unsigned char keyval;   //A variable

/*
+---------------------------------------+
| Prototype: void key_init(void);       |
| Return Type: void                     |
| Arguments: None                       |
| Description: Initialize ports and     |
|              Keypad.                  |
+---------------------------------------+
*/
void key_init(){
        keyportddr = 0xF0;
        keyport = 0x0F;
}

/*
+-----------------------------------------------+
| Prototype: unsigned char get_key(void);       |
| Return Type: unsigned char                    |
| Arguments: None                               |
| Description: To read key from the keypad      |
+-----------------------------------------------+
*/
unsigned char get_key(){
        unsigned char i,key=1;
        for(i=0;i<4;i++){               //Loop for 4 rows
                keyport &=~(0x80>>i);   //Make rows low one by one
                        if(!(keyportpin & (1<<col1))){
                         //check COL1
                                while(!(keyportpin & (1<<col1)));
                                //wait for release
                                return key;
                                //return pressed key value
                        }
                        if(!(keyportpin & (1<<col2))){
                         //Check COL2
                                key += 1;
                                //Second key pressed
                                while(!(keyportpin & (1<<col2)));
                                //wait for release
                                return key;
                                //return key value
                        }
                        if(!(keyportpin & (1<<col3))){
                         //Check COL3
                                key += 2;
                                //Third key pressed
                                while(!(keyportpin & (1<<col3)));
                                //Wait for release
                                return key;
                                //Return value
                        }
                        if(!(keyportpin & (1<<col4))){
                         //check COL4
                                key += 3;
                                //Fourth key pressed
                                while(!(keyportpin & (1<<col4)));
                                //Wait for release
                                return key;
                                //Return key value
                        }
                key +=4;        //Next row
                keyport |= 0x80>>i;
                //make read row high again
        }
        return FALSE;   //return false if no key pressed
}
The next section of the tutorial will cover the programming of 8051.

Programming 8051 Microcontroller

ASM Code

Code: Select all

keyport equ P2                  ;Keypad port connected here
col1 equ P2.0                   ;Column 1
col2 equ P2.1                   ;Column 2
col3 equ P2.2                   ;Column 3
col4 equ P2.3                   ;Column 4

keyval equ 30H                  ;To store key number
pressed bit 0H                  ;Flag

key_init:
        mov keyport,#0FH        ;Make rows as o/p and col as i/p
        ret

get_key:
        mov keyval,#0           ;reset the number
        mov keyport,#7FH        ;make Row1 low
        acall read_col          ;read columns

        jb pressed, done        ;check if flag is set

        mov keyval,#4           ;if not then read next row
        mov keyport,#0BFH       ;make Row2 low
        acall read_col          ;read columns

        jb pressed, done        ;check if flag is set

        mov keyval,#8           ;if not then read next row
        mov keyport,#0DFH       ;make row3 low
        acall read_col          ;read columns

        jb pressed, done        ;check if flag is set

        mov keyval,#12          ;if not read row4
        mov keyport,#0EFH       ;make row4 low
        acall read_col          ;read columns

done:
        ret

read_col:                       ;read columns routine
        clr pressed             ;reset the flag

        jb col1, nextcol        ;check if first key is pressed
        jnb col1,$              ;if yes then wait for key release       
        setb pressed            ;set the flag
        ret

nextcol:                        ;read col2
        jb col2, nextcol1       ;check if second key is pressed
        jnb col2,$              ;if yes then wait for key release
        inc keyval              ;its key number 2
        setb pressed            ;set the flag
        ret

nextcol1:                       ;read col3
        jb col3, nextcol2       ;check if third key is pressed
        jnb col3,$              ;if yes then wait for key release
        inc keyval              ;its key 3
        inc keyval
        setb pressed            ;set the flag
        ret

nextcol2:                       ;read column 4
        jb col4, exit           ;check if fourth key pressed
        jnb col4,$              ;if yes then wait for key release
        inc keyval              ;its key 4
        inc keyval
        inc keyval
        setb pressed            ;set the flag
        ret

exit:                           ;if no key is pressed
        clr pressed             ;clr the flag
        clr keyval              ;reset the number
        ret

        end
C Code

Code: Select all

#include <AT89X51.H>    //Include file for 8051
#define keyport P2      //keypad connected to P2
#define col1 P2_0       //column 1
#define col2 P2_1       //column 2
#define col3 P2_2       //column 3
#define col4 P2_3       //column 4
#define TRUE 1          //some defines
#define FALSE 0

/*
+---------------------------------------+
| Prototype: void key_init(void);       |
| Return Type: void                     |
| Arguments: None                       |
| Description: Initialize ports and     |
|              Keypad.                  |
+---------------------------------------+
*/
void key_init(){
        keyport &=0x0F; //make Rows as o/p and cols are i/p
}

/*
+-----------------------------------------------+
| Prototype: unsigned char get_key(void);       |
| Return Type: unsigned char                    |
| Arguments: None                               |
| Description: To read key from the keypad      |
+-----------------------------------------------+
*/
unsigned char get_key(){
        unsigned char i,k,key=0;
        k=1;
        for(i=0;i<4;i++){               //loop for 4 rows
                keyport &=~(0x80>>i);   //to make rows low 1 by 1
                        if(!col1){      //check if key1 is pressed
                                key = k+0;      //set key number
                                while(!col1);   //wait for release
                                return key;     //return key number
                        }
                        if(!col2){      //check if key2 is pressed
                                key = k+1;      //set key number
                                while(!col2);   //wait for release
                                return key;     //return key number
                        }
                        if(!col3){      //check if key3 is pressed
                                key = k+2;      //set key number
                                while(!col3);   //wait for release
                                return key;     //return key number
                        }
                        if(!col4){      //check if key4 is pressed
                                key = k+3;      //set key number
                                while(!col4);   //wait for release
                                return key;     //return key number
                        }
                k+=4;                   //next row key number
                keyport |= 0x80>>i;     //make the row high again
        }
        return FALSE;                   //return false if no key pressed
}
Post Reply

Return to “Microcontrollers”