Matrix keypad programming

Like this should work
I don't think you have compiled this code because there are some errors. I have removed some errors
C:
#include <reg51.h>

#include <stdio.h>
sbit row1port = P1^0;
sbit row2port = P1^1;
sbit row3port = P1^2;
sbit  row4port = P1^3;
sbit col1port = P1^4;
sbit col2port = P1^5;
sbit col3port = P1^6;
sbit col4port = P1^7;   // a 4x4 keypad is used
char const keyPadMatrix[] =
{
    '1','2','3','4',
    '5','6','7','8',
    '9','0','A','B',
    'C','D','E','F',
    0xFF
};
void ScanKeyMatrixInit()
{
    // we scan the keypad by turning on the row outputs and
    // reading the columns
   row1port = 0;
   row2port = 0;
   row3port = 0;
   row4port = 0;
   col1port = 1;
   col2port = 1;
   col3port = 1;
   col4port = 1;
}
char ScanKeyMatrix()
{
    // This routine returns the first key found to be
    // pressed during the scan.
    char key = 0, row;
    for( row = 0b00000001; row < 0b00010000; row <<= 1 )
    {     
        {   // turn on row output
            row1port = (row & 0x0001)>>0;
            row2port = (row & 0x0002)>>1;
            row3port = (row & 0x0004)>>2;
            row4port = (row & 0x0008)>>3;
            __delay_ms(1);
        }
     
        // read colums - break when key press detected
        if( col1port )
            break;
        key++;
        if( col2port )
            break;
        key++;
        if( col3port )
            break;
        key++;
        if( col4port )
            break;
        key++;
    }
    row1port = 0;
    row2port = 0;
    row3port = 0;
    row4port = 0;
     
    return keyPadMatrix[ key ];
}
compiling code.c...
code.c(38): error C251: illegal octal digit
code.c(38): error C251: illegal octal digit
code.c - 2 Error(s), 0 Warning(s).
 
Here's my rendition!!!

I have compiled your code there are some errors. I have removed some errors
AT89C51 and keil compiler
C:
#include <reg51.h>
#include <stdio.h>
#define LCDport P1   /* Data pins connected to port P1 */

sbit RS = P3^5;           /* RS pin connected to pin 0 of port P2 */
sbit RW = P3^6;           /* RW pin connected to pin 1 of port P2 */
sbit EN = P3^7;           /* EN pin connected to pin 2 of port P2 */

#define KEYport P0 /* Key pad connected to port P0*/
#define C1  P0^0  /* Col 0 pin connected to pin 0 of port P0*/
#define C2  P0^1  /* Col 1 pin connected to pin 1 of port P0 */
#define C3  P0^2  /* Col 2 pin connected to pin 2 of port P0 */
#define C4  P0^3  /* Col 3 pin connected to pin 3 of port P0 */


 void delayUs(unsigned int wait);
 void delayMs(unsigned int wait);
 void LCD_Command(unsigned char cmd);
 void  putchar(char tx_data);
 /* functions for delay */
 void delayUs(unsigned int wait)
   {
     wait >>= 3;
      while(wait--);
   }
   
 void delayMs(unsigned int wait)
   {
      while(wait--)
      delayUs(1000);
   }
/* Function to send command to LCD */
void LCD_Command(unsigned char cmd)
   {
    LCDport = cmd;
    RS = 0;
    RW = 0;
    EN = 1;
    delayMs(5);
    EN = 0;
   }
   
/*Function to send data to LCD */
void LCD_Data(unsigned char Data)
   {
    LCDport = Data;
    RS = 1;
    RW = 0;
    EN = 1;
    delayMs(5);
    EN = 0;
   }
/* Function to prepare the LCD */
void LCD_init(void)
   {
    delayMs(20);
    LCD_Command(0x33);  // Init 8 it
    delayMs(15);
    LCD_Command(0x38);  // Function set
    delayMs(15);
    LCD_Command(0x0C);  // display on
    delayMs(10);
    LCD_Command(0x06);  // direction
    delayMs(5);
    LCD_Command(0x01);  // home...
    delayMs(5);
   }
   
  /* Function to position cursor on the LCD */
void LCD_goto(int x, int y)
   {
      unsigned char addr = 0x80;      // default line
       if (y ==2 ) addr = 0xC0;  // 2nd line
      if (y ==3 ) addr = 0x90;     // 3rd line
      if (y ==4 ) addr = 0xD0;  // 4th line
      addr+=x;     // Column required
      LCD_Command(addr);
    }
   
  /* Function to print on the LCD */  
 void LCD_print(int x, int y, char* str)
      {
  LCD_goto(x,y);
  while(*str!=0)      // this is a ponter  This means...
     LCD_Data(*str++); // While the character pointed to isn't 0 print to LCD then increment..
      }
   
  /* Function to pset up Uart */     
void UART_Init()
   {
    TMOD = 0x20; /* Timer 1, 8-bit auto reload mode */
    TH1 = 0xFD; /* Load value for 9600 baud rate */
    SCON = 0x50; /* Mode 1, reception enable */
    TR1 = 1;  /* Start timer 1 */
   }
   
  /* Function to send a character */  
void  putchar(char tx_data)
   {
    SBUF = tx_data;  /* Load char in SBUF register */
    while (TI == 0); /* Wait until stop bit transmit */
    TI = 0;    /* Clear TI flag */
   }
   /* Function to fetch a character */  
char getchar(void)
   {
    while(!RI);        // Wait here until SBUF clear
    RI = 0;
    return SBUF;     
    }
   
  /* Function to send a line of characters untill a null*/  
   
char keypad(void)
    {
    unsigned char keymask = 0xEF;
    char key = 0, row;
     char act_key[]  = {0,1,4,7,11,2,5,8,10,3,6,9,12} ;
    for(row=0;row < 4; row++)   
        {
          KEYport = keymask;
          if(!C1) key = 1;
          if(!C2) key = 2;
          if(!C3) key = 3;
          if(!C4) key = 4;
                   if(key)
            {  
              key += (row*4);
              return act_key[key];
            }
                keymask <<= 1;
         keymask ++;   
       }       
    return key;
    }
   
void main(void)
   {
    char  key;  // receive variable
      char buff[20];
    int pos = 0;  // where we are on screen
    UART_Init();        /* UART initialize function */
    LCD_init();  // set up LCD
    puts("Press some keys\n\r");        /* Transmit 'test' */
    while(1)
      {
  key = keypad();
  if (key)
     {
      sprintf(buff,"Key Pressed %d ", key) ;
     LCD_print(0,0,buff);
     }
 }
   }
compiling keypad.c...
keypad.c(19): error C231: '_putchar': redefinition
keypad.c(100): error C231: '_putchar': redefinition
keypad.c(104): error C231: '_putchar': redefinition
keypad.c - 3 Error(s), 0 Warning(s).

How to make this code workable for my chip
 
I've dug out some code from a few years ago that reads a 4x4 keypad and returns the key code. It has key rollover, keydelay before repeating and autorepeat.
It should be called between 20 and 50 times per second - this is important for debounce purposes.
Code:
//assuming the rows are on port bits 4 to 7
//and columns are on 0 to 3 with WPUs on

uint16_t keys,prev,edges;

char ReadKeyPad(){
char i;
rom char KeyPad[16]="580247*169#3ABCD";    //swap around until right depends how keypad is wired
    prev=keys;                        //make a copy of previous value
    for(i=0x80;i>0x08;i>>=1){        //this will loop with i equal to 0x80, 0x40, 0x20 & 0x10.
        keys<<=4;                    //make room for next four keys
        TRISA=255-i;                //make row output
        porta=255-i;                //and make it low
        keys|=(porta&0x0f);            //get the lower 4 bits and move into keys variable
    }
    if(keys==0)                        //if no key pressed
        return(0);                    //return zero
    if(((keys^prev)&prev)==0){        //if it's not a new keypress
        if(--KeyCount!=0)            //must be repeating key
            return(0);                //if keycount <> 0 then return no key
        KeyCount=KeyRepeat;            //else reset repeat and fall through to return key.
    }else{                            //must be new key
        KeyCount=KeyDelay;            //set repeat delay
        edges=((keys^prev)&prev);    //set variable edges to the new key value
    }                                //edges will contain the repeated key pattern or the new one.
    i=0;                            //convert bit pattern to key code.
    while((edges&(1<<i))==0){        //count until first bit set
        i++;
    }
    i=KeyPad[i];                    //convert position to key value
    return i;                        //and return it
}

Mike.
 
Last edited:
Parth86 I don't know witch of us going to learn C me or you LOL The code I posted was the keypress part not a whole code but, My lord
You should look at and see how it works I was from the same compiler you using I got it working on a pic16f15376 .
I just ordered
AT89C51 Got find a compiler for linux LOL



Going to try Mikes code in post #23 Looks nice


 
I've added comments to the above code to make it easier to follow.

Mike.
 
Parth!! delete all these definitions.... The are conflicting.

void delayUs(unsigned int wait);
void delayMs(unsigned int wait);
void LCD_Command(unsigned char cmd);
void putchar(char tx_data);

if "main" is place last you do not use definitions... ( It's just the way I write C )..

putchar() is already defined elsewhere... It must not be redefined..
 
Parth!! delete all these definitions.... The are conflicting.
I have removed prototype function deceleration
program show only two errors
compiling keypad.c...
keypad.c(96): error C231: '_putchar': redefinition
keypad.c(100): error C231: '_putchar': redefinition
keypad.c - 2 Error(s), 0 Warning(s).

putchar() is already defined elsewhere... It must not be redefined..
I think it's predefine in #include <stdio.h> here
I have notice in main function. you are using puts("Press some keys\n\r"); but you have not declared this outside the main function
 
Have you tested this code. Is it working for you?
Of course... I don't like posting untested code..

Why don't you download SDCC... If you have proteus 8 it integrates with VSM... Seamlessly!! It has auto wizzard to set up simple projects...
 
Of course... I don't like posting untested code..

Why don't you download SDCC... If you have proteus 8 it integrates with VSM... Seamlessly!! It has auto wizzard to set up simple projects...
I have test your code on sdcc it's work fine

you ware using uart but I don't want to use it. I just wrote simple program on kiel and I think it should be work but it's not working
so can you tell me what's the wrong in my program. why it's not working
C:
#include<reg51.h>

#define LCDport P3

sbit RS = P2^0;
sbit RW = P2^1;
sbit EN = P2^2;

#define KEYport P1
#define C1  P1^0
#define C2  P1^1
#define C3  P1^2
#define C4  P1^3

/* functions for delay */
 void delayUs(unsigned int wait)
   {
     wait >>= 3;
      while(wait--);
   }
 
 void delayMs(unsigned int wait)
   {
      while(wait--)
  delayUs(1000);
   }
/* Function to send command to LCD */
void LCD_Command(unsigned char cmd)
   {
    LCDport = cmd;
    RS = 0;
    RW = 0;
    EN = 1;
    delayMs(5);
    EN = 0;
   }
 
/*Function to send data to LCD */

    void LCD_Data(unsigned char dat)
   {
    LCDport = dat;
    RS = 1;
    RW = 0;
    EN = 1;
    delayMs(5);
    EN = 0;
   }
/* Function to prepare the LCD */
void LCD_init(void)
   {
    delayMs(20);
    LCD_Command(0x33);  // Init 8 it
    delayMs(15);
    LCD_Command(0x38);  // Function set
    delayMs(15);
    LCD_Command(0x0C);  // display on
    delayMs(10);
    LCD_Command(0x06);  // direction
    delayMs(5);
    LCD_Command(0x01);  // home...
    delayMs(5);
   }
 
    void LCD_goto( char x, char y)
   {
   int addr = 0x80;   // start address
   if(y==2) addr+=0x40;  // are we on second row
   addr += x;    // add in the columns
   LCD_Command(addr);   // send to display.
   }
 
    char keypad(void)
    {
       unsigned char keymask = 0xEF;
       char key = 0, row;
       char act_key[]  = {0,1,4,7,11,2,5,8,10,3,6,9,12} ;
       for(row=0;row < 4; row++)
        {
          KEYport = keymask;
          if(!C1) key = 1;
          if(!C2) key = 2;
          if(!C3) key = 3;
          if(!C4) key = 4;
                   if(key)
            {
              key += (row*4);
              return act_key[key];
            }
                keymask <<= 1;
         keymask ++;
       }   
    return key;
    }
   
void main(void)
   {
    char  ke;
    LCD_init();  // set up LCD
 
    while(1)
      {
           key = keypad();
     
            LCD_goto(3,1);
           LCD_Data(key);       
      }
   }
I am just trying to display only one key
get the key
set cursor position
print the key
 
Last edited:
It will not compile as key is not defined... you missed the 'y' of the definition..
My bad I have corrected it. but still program doesn't show key on screen, Do I need to make any other function.

I just want to see one key on screen and I think program should be work because I am following all the basic thing that I know so what's the missing here
 
I am also getting same result with same code

Now I am thinking to use sdcc . I think its time for programming.
Yes.... key is a number 0 ~ 12... to see it you need to convert to ascii... ie add 48 to key..

LCD_Data(key+48);
but this function return char
C:
char keypad(void)
    {
        return key;
    }

How to print the key shown into keypad
 

Attachments

  • keypad.jpg
    238.9 KB · Views: 337
Last edited:
'-' ,'=' ,'+', so on. Don't something like that work after all he is using C
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…