Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

KEYPAD Interfacing issue using PIC18f4520 and Mikroc Pro for PIC

Status
Not open for further replies.

djc

Advanced Member level 1
Joined
Jan 27, 2013
Messages
402
Helped
3
Reputation
6
Reaction score
2
Trophy points
1,298
Location
India
Activity points
4,554
Hello,

I wrote a program for interfacing 4*4 matrix keypad with PIC18f4520 using mikrocPro for pic, which is as follows,
Code:
#include <math.h>
#define ROW0    PORTB.B1  //o/p
#define ROW1    PORTB.B3
#define ROW2    PORTB.B5
#define ROW3    PORTB.B7
#define COL0    RB0_bit   //i/p
#define COL1    RB2_bit
#define COL2    RB4_bit
#define COL3    RB6_bit
#define Select_DS     PORTD.B7
#define Select_Clk    PORTD.B6
#define Data_DS       PORTD.B5
#define Data_Clk      PORTD.B4
#define Test          PORTD.B0  //Pin 19
#define TIMER_START_VALUE   250   //230,200,255,500
#define TIMER_START_VALUE_1 250  //210,160,254,255
#define adjust 1000//500,1000
unsigned char i=0,j=0,k=0,m=0,FND_0=0,FND_1=0,FND_2=0,FND_3=0,FND_4=0,FND_5=0,FND_6=0,FND_7=0,FND_8=0,FND_9=0;
bit bulb;

 unsigned int num[10] = {39578,65215,6939,23067,32318,23130,6746,65178,6682,23066};
 unsigned int alpha[26]= {15898,53779,39898,53907,7002,16218,39514,15934,54227,38867,15854,39934,48812,48316,
                         39578,16154,39066,15642,23130,63443,39614,45038,44222,60909,63469,52171};

 unsigned int num_2[17]= {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
 unsigned int Data=0,quotient=0 ;

 unsigned char binaryNumber[20];
void Key_Detect(unsigned int Data){
           
           quotient = Data;
           i=1;
           //j=0;
                     while(quotient>0){
                             binaryNumber[i++]= quotient % 2;
                             quotient = quotient / 2;

                     }
                             for(i=i;i<17;i++)
                             {
                                 binaryNumber[i] = 0;
                             }
                             //i--;
                             //for(j = i-1;j>=0;j--){

                             while(i!=0){
                             Data_DS = binaryNumber[i];
                             Data_Clk = 1;
                             Delay_us(1);
                             Data_Clk = 0;
                           //Delay_us(2);
                             i--;
                             };
                 Data_Clk = 1;
                 Delay_us(1);
                 Data_Clk = 0;
                 //Delay_ms(1000);
         //}

}

//void Key_Detect_2(int Data) {
 void Key_Detect_2() {

                 for(i=17;i>0;i--){
                             Data_DS = num_2[i];
                             Data_Clk = 1;
                             Delay_us(1);
                             Data_Clk = 0;
                           //Delay_us(2);
                             //i--;
                             //Delay_ms(1000);
                     }


}
void select_fun(){
                 Select_Clk = 1;
                 Delay_us(1);
                 Select_DS = 0;
                 Select_Clk = 0;
                 /*Delay_ms(adjust);*/
                 //Delay_ms(adjust);

}
void disp_clr(){
         Select_DS = 1;
         Delay_us(1);
         for(k=0;k<7;k++){
             select_fun();
             //Key_Detect(num[0]);
             //Delay_ms(400);
         }

         select_fun();
         Key_Detect_2();
         Delay_ms(2);
         select_fun();
         Key_Detect_2();
         select_fun();
         Key_Detect_2();
         select_fun();
         Key_Detect_2();
         select_fun();
         Key_Detect_2();
         select_fun();
         Key_Detect_2();
         select_fun();
         Key_Detect_2();
         select_fun();
         Key_Detect_2();
         select_fun();
         Key_Detect_2();
         select_fun();
         Key_Detect_2();
}


void interrupt(){
        
      if(INTCON.TMR0IF){
      TMR0L = TIMER_START_VALUE;
      TMR0H = TIMER_START_VALUE_1;
      TMR0IF_bit = 0;
      }
         Select_DS = 1;
         Delay_us(1);
         for(k=0;k<7;k++){
             select_fun();
             //Key_Detect(num[0]);
             //Delay_ms(400);
         }

         select_fun();
         Key_Detect(num[FND_0]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[FND_1]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[FND_2]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[FND_3]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[4]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[5]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[6]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[7]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[8]);
         Delay_ms(2);
         select_fun();
         Key_Detect(num[9]);
         Delay_ms(2);
         //select_fun();
         //Key_Detect(alpha[1]);
         //disp_clr();
         //Test = ~Test;
        //TMR0L = TIMER_START_VALUE;
        //TMR0H = TIMER_START_VALUE_1;
}


void main() {

     TRISD = 0x00;            /*//PortD as output*/
     PORTD = 0x00;            /*//Initial value*/
     TRISB = 0x55;
     PORTB = 0x00;
     INTCON = 0xa0;           /*//0xc0;*/
     
     TMR0ON_bit = 0;          /*//Stop timer 0 during set up*/
     T08BIT_bit = 0;      /*// Enable 16 bit timer*/
     T0CS_bit = 0;        /*// use internal clock to trigger timer to count*/
     PSA_bit = 0;         /*// Use the prescaler to slow the timer down*/
     
     
     T0PS0_bit = 0; //1             /*//for 16 bit timer 1/4 of clock freq   001*/
     T0PS1_bit = 1; //0
     T0PS2_bit = 0; //0

     TMR0L = TIMER_START_VALUE;
     TMR0H = TIMER_START_VALUE_1;

     TMR0ON_bit = 1;       //start the timer
     

         while(1){
         
         //Test=1;
         disp_clr();
            ROW0 = 0;
            ROW1 = 1;
            ROW2 = 1;
            ROW3 = 1;
            //Delay_ms(5);
                         //FND_1=1;
                         //Test = ~Test;
                         if(COL0==0){
                         Delay_ms(1);
                         FND_1=1;
                         /*do
                         {
                         Delay_ms(1);
                         FND_1=1;
                         Test =~Test;
                         }while(COL0!=1);*/
                         }
                         
                         if(COL1==0){
                         do
                         {
                         Delay_ms(1);
                         FND_2=2;
                         Test = 0;
                         }while(COL1!=1);
                         }

                         if(COL2==0){
                         do
                         {
                         Delay_ms(1);
                         FND_3=3;
                         Test =0;
                         } while(COL2!=1);
                         }

           /*ROW0 = 1;
           ROW1 = 0;
           ROW2 = 1;
           ROW3 = 1;
                         Delay_ms(5);

                         if(COL0==0){
                         do
                         {
                          Delay_ms(1);
                         }while(COL0!=1);
                         FND_4=4;
                         }
                         if(COL1==0){
                         do
                         {
                         Delay_ms(1);
                         }while(COL1!=1);
                         FND_5=5;
                         }

                         if(COL2==0){
                         do
                         {
                         Delay_ms(1);
                         } while(COL2!=1);
                         FND_6=6;

                         }

           ROW0 = 1;
           ROW1 = 1;
           ROW2 = 0;
           ROW3 = 1;

                         Delay_ms(5);

                         if(COL0==0){
                         do
                         {
                          Delay_ms(1);
                         }while(COL0!=1);
                         FND_7=7;

                         }

                         if(COL1==0){
                         do
                         {
                         Delay_ms(1);
                         }while(COL1!=1);
                         FND_8=8;

                         }

                         if(COL2==0){
                         do
                         {
                         Delay_ms(1);
                         } while(COL2!=1);
                         FND_9=9;

                         }

               ROW0 = 1;
               ROW1 = 1;
               ROW2 = 1;
               ROW3 = 0;

                         if(COL1==0){
                         do
                         {
                         Delay_ms(1);
                         }while(COL1!=1);
                         FND_0=0;

                         }

                         if(COL2==0){
                         do
                         {
                         Delay_ms(1);
                         }while(COL2!=1);
                         bulb = 1;
                         }*/
         disp_clr();

         };

}

I have declared ROW as output and Column as input. Initial voltage on column pins is 5V so when any key is pressed that column pins gets grounded and has 0V. I am checking the same using
"if(COL0 == 0)" condition, However somehow this condition is always failing. I checked the hardware. It is perfectly fine. But don't know whats the issue with software. It is not checking the given condition for any of the ROW and Column. Can somebody guide me what could be the isue.

Regards
Dheeraj
 

That has to be the most complicated and convoluted keypad code ever written. Make life easy for yourself, put the rows on adjacent pins and the columns on adjacent pins, then use the shift operators to scan the keys.

Brian.
 

Thanx Brain,

However the hardware is already made, so can't do any changes in hardware. I have shifted the scanning mechanism from interrupt to normal function. Now it is scanning keypad perfectly. It seems it is working fine. Now i have another isue, that when i scan the 16 segment display and display data on it using serial in parallel out shift register, unwanted segment also glows a little bit. I am not getting how to remove that. I also sent the data for blank after each 16 segment data is selected and particular data is displayed on it. But it's not helping.
Can you guide on it?
 

I would need to see the schematic to help with the LED 'ghosting' but if you are using a shift register it will normally hold the data between one shift and the next so the only way to provide blanking between digits is to turn the power to the 'other side' of the LED off momentarily. I'm not sure whether you are using the shift register to drive digits or segments so I can't tell which the 'other side' is in your design.

The better way to drive your keypad is to set up a timer so it generates a periodic interrupt every 5mS or so, then use the interupt to move to the next row of your key scan. Read the column back and use an array to decode the column input value to a real number and save it. If ANY column returns a key press, set a variable (aka a 'flag') to say a key press was detected. Remove all the delays from the interrupt routine, it is never good practice to use delays inside ISRs because they block further interrupts being serviced.

Then all you have to do in your main() routine is check the flag to see if a key was pressed, if one was, read its value and reset the flag for next time.

Brian.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top