Actually we have already understood the working of both keypad and LCD so I thought to share this small project as it will give you the practical application of both keypad and LCD. And if you are new to 8051 Microcontroller then its always better to first design a small project and then move to pro one. The Simulation file along with hex file and complete code is given at the end for download. But my suggestion is to design it by yourself as it will help you in learning. You will do mistakes but obviously it will help you in learning so make mistakes and learn with it. So, let's get started with it.
while(1) { //get numb1 key = get_key(); writecmd(0x01); //clear display writedata(key); //Echo the key pressed to LCD num1 = get_num(key); //Get int number from char value, it checks for wrong input as well if(num1!=Error) //if correct input then proceed, num1==Error means wrong input { //get function key = get_key(); writedata(key); //Echo the key pressed to LCD func = get_func(key); //it checks for wrong func if(func!='e') //if correct input then proceed, func=='e' means wrong input { //get numb2 key = get_key(); writedata(key); //Echo the key pressed to LCD num2 = get_num(key); //Get int number from char value, it checks for wrong input as well if(num2!=Error) //if correct input then proceed, num2==Error means wrong input { //get equal sign key = get_key(); writedata(key); //Echo the key pressed to LCD if(key == '=') //if = is pressed then proceed { switch(func) //switch on function { case '+': disp_num(num1+num2); break; case '-': disp_num(num1-num2); break; case 'x': disp_num(num1*num2); break; case '/': disp_num(num1/num2); break; } } else //key other then = here means error wrong input { if(key == 'C') //if clear screen is pressed then clear screen and reset writecmd(0x01); //Clear Screen else DispError(0); //Display wrong input error } } } } }
#include<reg51.h> #include<string.h> //Define Macros #define Error 13 // Any value other than 0 to 9 is good here //Function declarations void cct_init(void); void delay(int); void lcdinit(void); void writecmd(int); void writedata(char); void writeline(char[]); void ReturnHome(void); char READ_SWITCHES(void); char get_key(void); int get_num(char); char get_func(char); void DispError(int); void disp_num(int); void WebsiteLogo(); //******************* //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 int num1 = 0; //First number char func = '+'; //Function to be performed among two numbers int num2 = 0; //Second number cct_init(); //Make input and output pins as required lcdinit(); //Initilize LCD WebsiteLogo(); while(1) { WebsiteLogo(); //get numb1 key = get_key(); writecmd(0x01); //clear display WebsiteLogo(); writedata(key); //Echo the key pressed to LCD num1 = get_num(key); //Get int number from char value, it checks for wrong input as well if(num1!=Error) //if correct input then proceed, num1==Error means wrong input { //get function key = get_key(); writedata(key); //Echo the key pressed to LCD func = get_func(key); //it checks for wrong func if(func!='e') //if correct input then proceed, func=='e' means wrong input { //get numb2 key = get_key(); writedata(key); //Echo the key pressed to LCD num2 = get_num(key); //Get int number from char value, it checks for wrong input as well if(num2!=Error) //if correct input then proceed, num2==Error means wrong input { //get equal sign key = get_key(); writedata(key); //Echo the key pressed to LCD if(key == '=') //if = is pressed then proceed { switch(func) //switch on function { case '+': disp_num(num1+num2); break; case '-': disp_num(num1-num2); break; case 'x': disp_num(num1*num2); break; case '/': disp_num(num1/num2); break; } } else //key other then = here means error wrong input { if(key == 'C') //if clear screen is pressed then clear screen and reset { writecmd(0x01); //Clear Screen WebsiteLogo(); } else { DispError(0); //Display wrong input error WebsiteLogo(); } } } } } } } void WebsiteLogo() { 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); } 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 ReturnHome(void) /* Return to 0 cursor location */ { writecmd(0x02); delay(1500); WebsiteLogo(); } void writeline(char Line[]) { int i; for(i=0;i<strlen(Line);i++) { writedata(Line[i]); /* Write Character */ } ReturnHome(); /* Return to 0 cursor position */ } 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 } int get_num(char ch) //convert char into int { switch(ch) { case '0': return 0; break; case '1': return 1; break; case '2': return 2; break; case '3': return 3; break; case '4': return 4; break; case '5': return 5; break; case '6': return 6; break; case '7': return 7; break; case '8': return 8; break; case '9': return 9; break; case 'C': writecmd(0x01); return Error; break; //this is used as a clear screen and then reset by setting error default: DispError(0); return Error; break; //it means wrong input } } char get_func(char chf) //detects the errors in inputted function { if(chf=='C') //if clear screen then clear the LCD and reset { writecmd(0x01); //clear display WebsiteLogo(); return 'e'; } if( chf!='+' && chf!='-' && chf!='x' && chf!='/' ) //if input is not from allowed funtions then show error { DispError(1); WebsiteLogo(); return 'e'; } return chf; //function is correct so return the correct function } void DispError(int numb) //displays differet error messages { writecmd(0x01); //clear display WebsiteLogo(); switch(numb) { case 0: writeline("Wrong Input"); break; case 1: writeline("Wrong Function"); break; default: writeline("Wrong Input"); break; } } void disp_num(int numb) //displays number on LCD { unsigned char UnitDigit = 0; //It will contain unit digit of numb unsigned char TenthDigit = 0; //It will contain 10th position digit of numb if(numb<0) { numb = -1*numb; // Make number positive writedata('-'); // Display a negative sign on LCD } TenthDigit = (numb/10); // Findout Tenth Digit if( TenthDigit != 0) // If it is zero, then don't display writedata(TenthDigit+0x30); // Make Char of TenthDigit and then display it on LCD UnitDigit = numb - TenthDigit*10; writedata(UnitDigit+0x30); // Make Char of UnitDigit and then display it on LCD }
Anyways, let's come back to keypad, if you wanna read the keypad details then you should read Interfacing of keypad with Arduino in Proteus ISIS as I have mentioned all the basic details about keypad in that tutorial and I am not gonna repeat it. But as a simple recall, keypad works on matrix system like it has 4 columns and 4 rows so we will have total 8 pins through which we are gonna control these 16 buttons. So, let's get started with it.
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 }
#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 }
LCD is also used almost in every Engineering Project for displaying different values. For example, if you have used the ATM machine, which you must have, then you have seen an LCD there displaying the options to select. Obviously that's quite a big LCD but still LCD. Similarly, all mobile phones are also equipped with LCDs. The LCD we are gonna use in this project is quite small and basic. It is normally known as the 16x2 LCD as it has rows and 2 columns for writing purposes. So, we are gonna interface that LCD with 8051 Microcontroller. The proteus Simulation along with hex file and the programming code in keil uvision 3 is given at the end of this post for download. If you are working with Arduino, then you should have a look at Interfacing of LCD with Arduino. The next level from LCD is Graphical LCD also known as GLCD, so if you wanna know more about that then you should read Interfacing of Arduino with GLCD. So, let's get started with it.
void lcdinit(void) { 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 writecmd(int z) { RS = 0; // => RS = 0 P2 = z; //Data transfer E = 1; // => E = 1 delay(150); E = 0; // => E = 0 delay(150); }
void writedata(char t) { RS = 1; // => RS = 1 P2 = t; //Data transfer E = 1; // => E = 1 delay(150); E = 0; // => E = 0 delay(150); }
#include<reg51.h> //Function declarations void cct_init(void); void delay(int); void lcdinit(void); void writecmd(int); void writedata(char); void ReturnHome(void); //******************* //Pin description /* P2 is data bus P1.0 is RS P1.1 is E */ //******************** // Defines Pins sbit RS = P1^0; sbit E = P1^1; // *********************************************************** // Main program // void main(void) { cct_init(); //Make all ports zero lcdinit(); //Initilize LCD writecmd(0x81); 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(0xc4); 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 ReturnHome(); //Return to 0 position while(1) { } } void cct_init(void) { P0 = 0x00; //not used P1 = 0x00; //not used P2 = 0x00; //used as data port P3 = 0x00; //used for generating E and RS } void delay(int a) { int i; for(i=0;i<a;i++); //null statement } void writedata(char t) { RS = 1; // => RS = 1 P2 = t; //Data transfer E = 1; // => E = 1 delay(150); E = 0; // => E = 0 delay(150); } void writecmd(int z) { RS = 0; // => RS = 0 P2 = z; //Data transfer E = 1; // => E = 1 delay(150); E = 0; // => E = 0 delay(150); } void lcdinit(void) { 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 ReturnHome(void) //Return to 0 location { writecmd(0x02); delay(1500); }
Download Proteus Simulation & Code
That's all for today, in the next post I am gonna share how to display custom characters on LCD with 8051 Microcontroller, because till now you can just display the simple characters like alphabets and numbers on it but can't display the custom characters like arrowhead etc. You should have a look at LCD Interfacing with Microcontrollers, where I have combined all tutorials related to LCD. So stay tuned and have fun.