Design a Simple Calculator with 8051 Microcontroller

Hello friends, today's post is about designing a simple calculator with 8051 Microcontroller. In our previous post, we have seen How to Interface keypad with 8051 Microcontroller in Proteus ISIS. Moreover, we have also worked on Interfacing of LCD with 8051 Microcontroller in Proteus ISIS. If you haven't read these two posts then my suggestion is to read them first before going into the details of this post, as we are going to use both keypad and LCD in order to design the simple calculator with 8051 Microcontroller.

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.

Design a Simple Calculator with 8051 Microcontroller

  • The calculator we are going to design in this post is quite basic calculator, it will only perform 4 tasks, which are as follows:
    • When you press the (+) button then it will add the two digits. For example, you want to add 2 and 3 then you need to press 2 + 2 = these four buttons in sequence and when you press the = button it will automatically will give you the sum.
    • When you press (-) button it will subtract the two digits like 3 - 2 = and it will give you the result.
    • When you press (x) button it will multiply the two digits.
    • When you press the (/) button it will simply divide the two digits.
  • Whenever you press the (=) button, it will give you the output depending on the function you used before and if you press (=) in the start then it will give "Wrong Input".
  • Finally, there's (ON/C) button on the Calculator, when you press this it will simply reset the code and will clear the LCD.
  • So, that's how this calculator is gonna work. Moreover, it will always reset when you try to calculate new value.
  • As its a simple calculator, so its only limited to 1 digit, means it will only apply the operation on single digit input like 2+3 but it won't work on more than 1 digit like 12 + 13.
  • I will soon design a more complicated calculator but for this one its only limited to single digit.
  • So, now let's design this calculator, so first we are gonna have a look at the Proteus simulation of Simple calculator with 8051 Microcontroller.
  • After that, we will do the coding part for calculator with 8051 Microcontroller.
  • So, now let's get started with Proteus Simulation.
Proteus Simulation
  • So, you can see we have used the same LCD which is 20x4 and have used the same keypad as did in previous tutorial.
  • You can see this keypad has all the required operations for this project which are (+), (-), (x) and (/).
  • So, now let's have a look at the programming code for calculator with 8051 Microcontroller.
Programming Code
  • We have already seen the programming code for keypad and LCD and I am assuming that you have also read those posts so I am not going into the details of those posts.
  • So,we know that how to print data on LCD and we are also aware of how to get key press from keypad and then display it on LCD.
  • So, now let's move on to adding these functions.
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
				 }                                 
			 }
		 }
     }
   }
  • As you can see in the above function, I have first check for the first key press.
  • When you pressed the first key on keypad then I get this key and converter it to integer.
  • After that I waited for the next key which must be some operation key like + - X or / otherwise it will generate the error message.
  • After that code is waiting for the third key which should be some numerical digit and then I converter it to integer again and if you entered some invalid key then it will generate the error.
  • Finally waiting for the = sign. When you press the = sign it will automatically perform the required operation which I placed in the switch case loop.
  • It will calculate the value and then print out the result and on next key press it will first clear the screen and then get the value and will continue.
  • Below is the detailed code for the project with comments and I hope you wont get into any trouble and will get it clearly.
#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
}

  • The above code is quite self explanatory and the main part I have already explained but still if you get into any troubled then ask in comments and I will resolve them.
  • Now copy this code in your keil uvision 3 and get the hex file.
  • Upload your hex file in Proteus ISIS and run your simulation.
  • The first screen you will get is as follows, which obviously displays our website address :P
  • Now, let's add 3 + 5 and we will get as shown in below figure:
  • Next operation, we are gonna do is the subtract one, so lets do this operation 3-9 = , shown below:
  • Now, lets do the third operation which is multiplication, so let's do this operation 9x9, shown below:
  • Now, finally do the last operation which is division, so I did 6/3 and result is shown below:
  • So, all the operations are shown in above figures, now if you give it wrong number like 2 digit number then it will display error message, as shown below:
  • It has become quite a lengthy post, so let's have the ending part. :)
  • You can download the Proteus Simulation along with hex file and code by clicking the below button.
Download Proteus Simulation and Code

So, that's all with the designing of simple Calculator with 8051 Microcontroller. I will try to work on advanced calculator, if I got time but I am not sure of that. :) So, that's all for today and will meet in next tutorial soon. till than have fun. !!! :)
Syed Zain Nasir

I am Syed Zain Nasir, the founder of <a href=https://www.TheEngineeringProjects.com/>The Engineering Projects</a> (TEP). I am a programmer since 2009 before that I just search things, make small projects and now I am sharing my knowledge through this platform.I also work as a freelancer and did many projects related to programming and electrical circuitry. <a href=https://plus.google.com/+SyedZainNasir/>My Google Profile+</a>

Share
Published by
Syed Zain Nasir