Thursday, September 9, 2010

PIC16F887/877 programming in C Tutorial 6 (Keypad Interfacing)

Keypad Interfacing:
This tutorial is about the interfacing of 4x3(4 rows & 3 columns) keypad with micro-controller using library routine of mikroc. Using these functions it is much easy to program. The basic technique is,  make the coloums as i/p and 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 coloums. Lets say we first make Row1 low, then read the columns. If any of the key in row1 is pressed will make the corrosponding 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 corrosponding 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...

The above whole algorithm is in Keypad_Key_Click() function, we are going to use, ones we have key just compare it the ASCII value to get the right key.  

Lets write a program that display the pressed key and quantity (how many times the key is pressed), on LCD using mickroc routines.  

unsigned short kp, cnt, oldstate = 0;
char txt[4];

// Keypad module connections
char  keypadPort at PORTD;
// End Keypad module connections

// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

void main() {
  cnt = 0;                                 // Reset counter
  Keypad_Init();                           // Initialize Keypad
 ///////////// comment for 877/////////////////////////////////////
  ANSEL  = 0;                              // Configure AN pins as digital I/O
  ANSELH = 0;
  Lcd_Init();                              // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                     // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);                // Cursor off

  Lcd_Out(1, 1, "Key Pressed :");                 // Write message text on LCD
  Lcd_Out(2, 1, "Times: ");

  do {
    kp = 0;                                // Reset key code variable

    // Wait for key to be pressed and released
            kp = Keypad_Key_Click();             // Store key code in kp variable
    while (!kp);
   // Prepare value for output, transform key to it's ASCII value
    switch (kp) {

      case  1: kp = 49; break; // 1
      case  2: kp = 50; break; // 2
      case  3: kp = 51; break; // 3
      case  4:                              //  kp = 65; break; // A for 4x4 pad
      case  5: kp = 52; break; // 4
      case  6: kp = 53; break; // 5
      case  7: kp = 54; break; // 6
      case  8:                              //kp = 66; break; // B for 4x4 pad
      case  9: kp = 55; break; // 7
      case 10: kp = 56; break; // 8
      case 11: kp = 57; break; // 9
      case 12:                             //kp = 67; break; // C for 4x4 pad
      case 13: kp = 42; break; // *
      case 14: kp = 48; break; // 0
      case 15: kp = 35; break; // #
      //case 16: kp = 67; break; // D for 4x4 pad

    if (kp != oldstate) {                  // Pressed key differs from previous
      cnt = 1;
      oldstate = kp;
    else {                                 // Pressed key is same as previous

    Lcd_Chr(1, 15, kp);                    // Print key ASCII value on LCD

    byteToStr(cnt, txt);                   // Transform counter value to string
    Lcd_Out(2, 12, txt);                   // Display counter value on LCD
  } while (1);

First specify the keypad connections; same thing we did in last tutorial, and LCD connections. Then initialize the keypad routine by using Keypad_Init() function, initialize the lcd and display the appropriate messages. Now once the key is pressed and the value is store in kp, by using Keypad_Key_Click() function, we have to compare the key number to its ASCII code to get the right key. Switch(kp) is used for this purpose.

Once we get the right key we compare it with oldstate; if Pressed key differs from previous, assign the cnt with one and update the oldstate. And if the Pressed key is same as previous, cnt is incremented (to count the number of times this key is pressed).

After this we want to display the pressed key and number of times on LCD. To display ASCII value, kp, we use 'Lcd_Chr' function. On the other hand cnt is a short to display it we have to convert it into a string; 'byteToStr' function is do the job. It converts input byte to a string. The output string has fixed width of 4 characters including null character at the end. txt[4] is declared for this purpose. For the next key the whole steps are repeated. 

keypad connection diagram


  1. hye..can you explain me a bit about programming using keypad and lcd using pic16f628a?

    1. this tutorial is for keypad interfacing. me just using built in library commands for this. the basic concept of reading keypad is; apply high or low to the columns then reads the rows by applying 1 and 0 combinations.

  2. can you help me with my project 'security door lock' which use keypad as input

    1. check this link of combination lock;

  3. i wanna know( case 1: kp = 49; break; // 1) why you put 49 !
    sbit LCD_RS at RB4_bit; what mean (sbit) RB4_bit
    Lcd_Chr(1, 15, kp); what 1,15 mean in this line

    1. ASCII value of 1 is 49 (refer ASCII table), "sbit LCD_RS at RB4_bit" means RS of lcd is connected to the RB4 bit,"Lcd_Chr(1, 15, kp);" means 1st row 15col and kp is the character in othrt words >>Lcd_Chr(char row, char column, char out_char)

  4. how to make rows low?