1
\$\begingroup\$

I am trying to simulate this project in Proteus using keil C. We are basically interfacing 4x4 keypad with 8051 microcontroller.

This is the code for the project:

 #include<reg51.h>

    //Function declarations
    void cct_init(void);
    void delay(int);
    void lcdinit(void);
    void writecmd(int);
    void writedata(char);
    void Return(void);
    char READ_SWITCHES(void);
    char get_key(void);

    //*******************
    //Pin description
    /*
    P2 is data bus
    P3.7 is RS
    P3.6 is E
    P1.0 to P1.3 are keypad row outputs
    P1.4 to P1.7 are keypad column inputs
    */
    //********************
    // Define Pins
    //********************
    sbit RowA = P1^0;     //RowA
    sbit RowB = P1^1;     //RowB
    sbit RowC = P1^2;     //RowC
    sbit RowD = P1^3;     //RowD

    sbit C1   = P1^4;     //Column1
    sbit C2   = P1^5;     //Column2
    sbit C3   = P1^6;     //Column3
    sbit C4   = P1^7;     //Column4

    sbit E    = P3^6;     //E pin for LCD
    sbit RS   = P3^7;     //RS pin for LCD

    // ***********************************************************
    // Main program
    //
    int main(void)
    {
       char key;                // key char for keeping record of pressed key

       cct_init();              // Make input and output pins as required
       lcdinit();               // Initilize LCD

       writecmd(0x95);
       writedata('w');                                 //write
       writedata('w');                                 //write
       writedata('w');                                 //write
       writedata('.');                                 //write
       writedata('T');                                 //write
       writedata('h');                                 //write
       writedata('e');                                 //write
       writedata('E');                                 //write
       writedata('n');                                 //write
       writedata('g');                                 //write
       writedata('i');                                 //write
       writedata('n');                                 //write
       writedata('e');                                 //write
       writedata('e');                                 //write
       writedata('r');                                 //write
       writedata('i');                                 //write
       writedata('n');                                 //write
       writedata('g');                                 //write

       writecmd(0xd8);

       writedata('P');                                 //write
       writedata('r');                                 //write
       writedata('o');                                 //write
       writedata('j');                                 //write
       writedata('e');                                 //write
       writedata('c');                                 //write
       writedata('t');                                 //write
       writedata('s');                                 //write
       writedata('.');                                 //write
       writedata('c');                                 //write
       writedata('o');                                 //write
       writedata('m');                                 //write
       writecmd(0x80);
       while(1)
       { 
         key = get_key();       // Get pressed key
         //writecmd(0x01);        // Clear screen
         writedata(key);        // Echo the key pressed to LCD
       }
    }


    void cct_init(void)
    {
        P0 = 0x00;   //not used
        P1 = 0xf0;   //used for generating outputs and taking inputs from Keypad
        P2 = 0x00;   //used as data port for LCD
        P3 = 0x00;   //used for RS and E   
    }

    void delay(int a)
    {
       int i;
       for(i=0;i<a;i++);   //null statement
    }

    void writedata(char t)
    {
       RS = 1;             // This is data
       P2 = t;             //Data transfer
       E  = 1;             // => E = 1
       delay(150);
       E  = 0;             // => E = 0
       delay(150);
    }


    void writecmd(int z)
    {
       RS = 0;             // This is command
       P2 = z;             //Data transfer
       E  = 1;             // => E = 1
       delay(150);
       E  = 0;             // => E = 0
       delay(150);
    }

    void lcdinit(void)
    {
      ///////////// Reset process from datasheet /////////
         delay(15000);
       writecmd(0x30);
         delay(4500);
       writecmd(0x30);
         delay(300);
       writecmd(0x30);
         delay(650);
      /////////////////////////////////////////////////////
       writecmd(0x38);    //function set
       writecmd(0x0c);    //display on,cursor off,blink off
       writecmd(0x01);    //clear display
       writecmd(0x06);    //entry mode, set increment
    }

    void Return(void)     //Return to 0 location on LCD
    {
      writecmd(0x02);
        delay(1500);
    }

    char READ_SWITCHES(void)    
    {   
        RowA = 0; RowB = 1; RowC = 1; RowD = 1;     //Test Row A

        if (C1 == 0) { delay(10000); while (C1==0); return '7'; }
        if (C2 == 0) { delay(10000); while (C2==0); return '8'; }
        if (C3 == 0) { delay(10000); while (C3==0); return '9'; }
        if (C4 == 0) { delay(10000); while (C4==0); return '/'; }

        RowA = 1; RowB = 0; RowC = 1; RowD = 1;     //Test Row B

        if (C1 == 0) { delay(10000); while (C1==0); return '4'; }
        if (C2 == 0) { delay(10000); while (C2==0); return '5'; }
        if (C3 == 0) { delay(10000); while (C3==0); return '6'; }
        if (C4 == 0) { delay(10000); while (C4==0); return 'x'; }

        RowA = 1; RowB = 1; RowC = 0; RowD = 1;     //Test Row C

        if (C1 == 0) { delay(10000); while (C1==0); return '1'; }
        if (C2 == 0) { delay(10000); while (C2==0); return '2'; }
        if (C3 == 0) { delay(10000); while (C3==0); return '3'; }
        if (C4 == 0) { delay(10000); while (C4==0); return '-'; }

        RowA = 1; RowB = 1; RowC = 1; RowD = 0;     //Test Row D

        if (C1 == 0) { delay(10000); while (C1==0); return 'C'; }
        if (C2 == 0) { delay(10000); while (C2==0); return '0'; }
        if (C3 == 0) { delay(10000); while (C3==0); return '='; }
        if (C4 == 0) { delay(10000); while (C4==0); return '+'; }

        return 'n';             // Means no key has been pressed
    }

    char get_key(void)           //get key from user
    {
        char key = 'n';              //assume no key pressed

        while(key=='n')              //wait untill a key is pressed
            key = READ_SWITCHES();   //scan the keys again and again

        return key;                  //when key pressed then return its value
    }

I am having difficulty in understanding that if the function READ_SWITCHES(void) is called, there is no conditional statement, ie if-else statement to check if

RowA = 0; RowB = 1; RowC = 1; RowD = 1;

or

RowA = 1; RowB = 0; RowC = 1; RowD = 1;

or

RowA = 1; RowB = 1; RowC = 0; RowD = 1;

or

RowA = 1; RowB = 1; RowC = 1; RowD = 0;

These isn't any case statement either. How does then this code work?

EDIT:

Shouldn't the code have been as written below with if-else statements? How does the code work without if-else statements or case statements

if{RowA = 0 && RowB = 1 && RowC = 1 && RowD = 1} {...}

else if{RowA = 1 && RowB = 0 && RowC = 1 && RowD = 1;} {...}

else if{RowA = 1 && RowB = 1 && RowC = 0 && RowD = 1;} {...}

else if{RowA = 1 && RowB = 1 && RowC = 1 && RowD = 0;} {...}


else return n;
\$\endgroup\$
  • \$\begingroup\$ RowA = 0; RowB = 1; RowC = 1; RowD = 1 here you are assigning the values. So, for this values, you are making if (C1 == 0)... return '/' and hence for next values. No need of "if else" \$\endgroup\$ – Krishna Shweta Jan 2 '18 at 16:45
0
\$\begingroup\$

The system works by driving one "row" line at a time low.

If it sees any of C1-C4 low in response (ie, if a button is pushed) it waits for some debounce time, additional waits for that line to cease being low (button to be released) and then returns a value.

Hence it is scanning a matrix keyboard.

(Arguably, the debounce is performed incorrectly - it should probably wait after seeing a release, especially before being willing to detect another press. As implemented, it would seem to be susceptible to detecting bouncing on release of a key held down longer than the delay time. There's also no dwell time on each row drive setting - many more modern processors could perform the check and decide no key is pressed faster than the input with some capacitive loading could actually change in response to the output.)

\$\endgroup\$
  • \$\begingroup\$ Sir, I have edited my question. I can't understand why the code snippet works without using if-else statements like I have used(in the edited portion)? I haven't seen C programs involving conditionals being written without if-else statements or case statements. \$\endgroup\$ – Anwesa Roy Nov 24 '17 at 18:22
  • \$\begingroup\$ else if is redundant, since the first "if" that is true will return from the function. Even if it didn't, it would likely only introduce the possibility of detecting two keys pressed in a given row, and what should happen then is a higher level issue of system design. \$\endgroup\$ – Chris Stratton Nov 24 '17 at 19:24
  • \$\begingroup\$ @ChrisStratton please see my comment under the question. That's what i understood. Can u tell me whether I understood it correctly or not? \$\endgroup\$ – Krishna Shweta Jan 4 '18 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.