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;
-
\$\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\$user105009– user1050092018年01月02日 16:45:48 +00:00Commented Jan 2, 2018 at 16:45
1 Answer 1
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.)
-
\$\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– Anwesa Roy2017年11月24日 18:22:12 +00:00Commented 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\$Chris Stratton– Chris Stratton2017年11月24日 19:24:14 +00:00Commented 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\$user105009– user1050092018年01月04日 11:57:43 +00:00Commented Jan 4, 2018 at 11:57