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;
asked Nov 24, 2017 at 17:59
\$\endgroup\$
1
  • \$\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\$ Commented Jan 2, 2018 at 16:45

1 Answer 1

1
\$\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.)

answered Nov 24, 2017 at 18:06
\$\endgroup\$
3
  • \$\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\$ Commented Nov 24, 2017 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\$ Commented Nov 24, 2017 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\$ Commented Jan 4, 2018 at 11:57

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.