LCD display of simple calculator based on 51 single chip microcomputer

Posted by culprit on Mon, 20 Sep 2021 16:11:30 +0200

         Sharing a small work is rewritten according to the idea of the code of the simple calculator given by Puzhong single chip microcomputer. The IO port can also correspond to the pin of the upper development board. The program he originally gave can only realize the addition, subtraction, multiplication and division of ten times the difference between two digits, especially the Division A/B   A < B is accurate within ten times. I can change it to 100 times, and the key values are reordered.  

          His experimental matrix keyboard is done by line by line scanning (assignment one by one). I use row and column scanning (self Baidu principle), and judge the key value after all scanning at one time. (figure below)

         The key values are (1, 2, 3, +, 4, 5, 6, -, 7, 8, 9, *, 0, CLR, =, /)

proteus simulation diagram

 

        Talk about the simple principle!! The first time we press the key must be a number, and then we press the special symbol. At this time, we can give him a flag bit to determine which symbol is pressed; The next step is to press the second number. How to judge whether it is the second number? Just judge the number of special symbol flag bits at this time, and then press the equal sign. When we press the equal sign, we can integrate the key values at this time, add, subtract, multiply and divide.

          The following describes the code, which is also modular programming. The LCD display module has a separate C file, and the keyboard and main program are placed in the main.c file  

        The LCD display module is basically the same as the code in the Puzhong experiment (I typed it myself). There is no comment. You can take a look at the video in Puzhong to learn about the preparation of LCD driver. The following is a general explanation of the first section of code, including the header file

#include "reg52.h"
#include "lcd.h"
#define Key_Net   P1uchar code number[ ]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2f-0x30 };        // The corresponding key values are arranged because LCD display will be processed   You can also modify the key position yourself. Here, of course, you need to make relative modifications later.
uchar value;                              
uchar fuhao,TABE;       // Fuhao yes   +,-,*,/, clr,=     Identification of; TABE=   1 is a symbol  = 0 is a number,
float Table_A,Table_B; //Table_A,Table_B stores the two numbers entered

LCD.H file contains macro definitions. See for yourself

 #ifndef _LCD_H
#define _LCD_H

typedef unsigned char uchar;
typedef unsigned int uint;

#define IO P0
sbit RW=P2^5;
sbit RS=P2^6;
sbit EN=P2^7;

void Lcd1602_Write_com(uchar com);
void Lcd1602_Write_dat(uchar dat);
void Lcd_Init();

#endif

The following is the complete code. First, the code comments of the main.c file are very complete. You should be able to understand them. They are basically clear in it

#include "reg52.h"
#include "lcd.h"
#define Key_Net  P1
uchar code number[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2f-0x30 };
uchar value;							  
uchar fuhao,TABE;	 //fuhao storage +, -, *, /, clr= 	; Table identifier 1 is a number, 0 is a number, Table_A,Table_B stores the two numbers entered
float Table_A,Table_B;
long SUM,YU;
void delay10ms()   //Error 0us
{
    unsigned char a,b,c;
    for(c=5;c>0;c--)
        for(b=4;b>0;b--)
            for(a=248;a>0;a--);
}

void Init()	      //Initialization used in main
{ 
	fuhao=0;
	TABE=0;
	Table_A=0;
	Table_B=0;

}
void Keydown()
{								  
	char a,i;
	i=0;
	Key_Net=0x0f;
	if(Key_Net!=0x0f)
	{
		delay10ms();
		if(Key_Net!= 0x0f)
		{
			Key_Net=0x0f;		  // Row and column scanning advanced row and column scanning to determine which column to press
			switch(Key_Net)
			{
				case(0x07) : value = 0 ;break; 		 //First column 
				case(0x0b) : value = 1 ;break;		 //Second column
				case(0x0d) : value = 2 ;break;		 //Third column
				case(0x0e) : value = 3 ;break;		 //Fourth column
			}	
		
			Key_Net = 0xf0;
			delay10ms();
			switch(Key_Net)		   // Row and column scan and then row scan to determine which row to press
			{
				case(0x70) : value = value+0 ;break;  //The first line is 0 1 2 3 keys pressed
				case(0xb0) : value = value+4 ;break;  //Second line
				case(0xd0) : value = value+8 ;break;  //Third line
				case(0xe0) : value = value+12 ;break; //The fourth line here determines which key is pressed and has not been assigned a value to the key
			}
			while((a<100)&&(Key_Net!=0xf0))
			{
				delay10ms();
				a++;
			}
				a=0;
		}					
		    if((0<=value)&&(value<=2)||(4<=value)&&(value<=6)||(8<=value)&&(value<=10)||value==12)	//According to the data designed by your own keyboard, this statement corresponds to the keys corresponding to the numbers 0-9
			{
				TABE=0;
				if(fuhao==0)
				{
					Table_A=Table_A*10+number[value];	 //Press a bit to store in a bit, and then press a bit. The original number * 10 plus the value just pressed

				}
				if((fuhao>0))
				{
					Table_B=Table_B*10+number[value];	 //When the signed bit is pressed, the following value is stored in Table_B medium 

				}
					Lcd1602_Write_dat(0x30+number[value]);	//Displays the value pressed in 0-9
			}
			
			if(value==3)  //  That is, the third bit in the array number 	 Press + on the keyboard to write a SWITCH statement
			{
			  	TABE=1;
				fuhao=1;  // +No. sign
				Lcd1602_Write_dat(0x30+number[value]);	  //The display + sign value==3 is 0x2b-0x30 in the array, and 0x2b is the + sign in the LCD
			}

			if(value==7)  //  That is, the 7th keyboard in the array number is pressed-	
			{
			  	TABE=1;
				fuhao=2;  // -No. sign
				Lcd1602_Write_dat(0x30+number[value]);	   //Similarly, display - No		
			}

			if(value==11)  // That is, the 11th keyboard in the array number is pressed*
			{
			  	TABE=1;
				fuhao=3;   //  *No. sign
				Lcd1602_Write_dat(0x30+number[value]);	   //Similarly, the * sign is displayed	
			}

			if(value==15)  //  Keyboard press/
			{
			  	TABE=1;
				fuhao=4;   //  /No. sign
				Lcd1602_Write_dat(0x30+number[value]);		//Similarly, display / number	
			}

			if(value==13)  //  Keyboard press CLR
			{
			  	TABE=1;
				fuhao=5;   // CLR flag
				Lcd1602_Write_com(0x30+number[value]);
				fuhao=0;
				TABE=0;
				Table_A=0;
				Table_B=0;			
			}

			if(value==14) //  Press the keyboard = directly handle the situation corresponding to various special symbols below
			{
				if(fuhao==1)	//addition
				{	
					SUM=Table_A+Table_B;	 //Calculate SUM
					Lcd1602_Write_com(0Xcf); //Display from the far right of the second line
					Lcd1602_Write_com(0X04); //Control pointer to move left
					while(SUM!=0)			 //Bit by bit display starts from the lowest bit of num
							{
								Lcd1602_Write_dat(0x30+SUM%10);		//The last bit of num is at 0x4f, that is, the far right
								SUM=SUM/10;							//Take another bit of result data	
							}
					Lcd1602_Write_dat(0x3d);						//Write equal sign
				}

				if(fuhao==2)	//subtraction
				{	
					if(Table_A>Table_B)			//First judge the size of a and B 
					{
					 	SUM=Table_A - Table_B;
					}
					else
					{
						SUM=Table_B - Table_A;
					}
						Lcd1602_Write_com(0Xcf);  //Display from the far right of the second line
						Lcd1602_Write_com(0X04);  //Control pointer to move left
						while(SUM!=0)	 	      //Bit by bit display starts from the lowest bit of num
								{
									Lcd1602_Write_dat(0x30+SUM%10);		//The last bit of the display result is at 0x4f
									SUM=SUM/10;							//Take the previous result data	
								}
						if(Table_A < Table_B)	//If a < B, you need to give a negative sign after the result is displayed
						{
							Lcd1602_Write_dat(0x2d);   //lcd display negative sign
						}
						Lcd1602_Write_dat(0x3d);	   //Write equal sign
				}

				if(fuhao==3)	//multiplication
				{	
					SUM=(Table_A)*(Table_B);
					Lcd1602_Write_com(0Xcf);			 //The last digit of the second line is displayed
					Lcd1602_Write_com(0X04);			 //Pointer moves left
					while(SUM!=0)	 		//One by one display
							{
								Lcd1602_Write_dat(0x30+SUM%10);		//The last bit of the display result is at 0x4f
								SUM=SUM/10;							//Take the previous result data	
							}
					Lcd1602_Write_dat(0x3d);						//Write equal sign
				}

				if(fuhao==4)	//division 	  a key!
				{
					uchar i;
					SUM=((Table_A/Table_B)*1000);		  //Sum magnification 1000 times 	 For example, sum=42/2689=0.01561919 zoom in 1000 times sum=15
					Lcd1602_Write_com(0Xcf);			  //The lcd displays from the last bit of the second line
					Lcd1602_Write_com(0X04);			  //Pointer moves left
					if((Table_A < Table_B)&&SUM<100)	  //When the value of two numbers is less than 100 times of the previous number 
					                                      //For example, 42 and 2689 2689 < 4200 calculators can calculate accurate results, or you can try to change them directly
					{
					while(SUM!=0)	 		//One by one display, e.g. sum=42/2689=0.01561919, enlarged by 1000 times sum=15
							{
								i++;
								Lcd1602_Write_dat(0x30+SUM%10);		//The last bit of the display result is at 0x4f
								SUM=SUM/10;							//SUM remainder
								if(i==2)							//At this time, 15 numbers have been output, and the correct value is 0.01561919
								{
								Lcd1602_Write_dat(0x30);			//Write a 0
								Lcd1602_Write_dat(0x2e);			//Write decimal point
								i=0;
								}				
							}
					}
					
					if(Table_A < Table_B)
					{
						Lcd1602_Write_dat(0x30);					 //After the decimal point is written above, write a 0 and output 0.015
					}
					
					if((Table_A > Table_B))	 //A> B there are not so many things. For example, 1589 / 33 = 48.1515 sum is magnified 1000 times sum=48151
					{
					while(SUM!=0)	 		//SUM*1000 is to retain three decimal places 
							{
								i++;
								Lcd1602_Write_dat(0x30+SUM%10);		//The last bit of the display result is at 0x4f
								SUM=SUM/10;
								
								if(i==3)							//When i=3, the decimal point should be output, because the decimal part has been output
								{
								Lcd1602_Write_dat(0x2e);			//Output decimal point
								}
							}
					}	
					if(Table_A < Table_B)
					{
					Lcd1602_Write_dat(0x30);					   //upper
					}

					Lcd1602_Write_dat(0x3d);						//Finally, write the equals sign
				
				}
			}	 

	}	
}

void main()
{
	Lcd_Init();		//Initialize LCD
    while(1)
	{
	Keydown();
	}
}

Then there is the LCD driver code, which is written in the lcd.c file. There are no comments in this part. You can go to station b university to see the preparation of LCD driver

#include "reg52.h"
#include "lcd.h"
#include "intrins.h"

void delay1ms(void)   //Error 0us
{
    unsigned char a,b;
    for(b=199;b>0;b--)
        for(a=1;a>0;a--);
}
void delay5ms(void)   //Error 0us
{
    unsigned char a,b;
    for(b=185;b>0;b--)
        for(a=12;a>0;a--);
}

void Lcd1602_Write_com(uchar com)
{
	RW=0;
	RS=0;
	_nop_();
	EN=0;
	IO=com;	
	delay1ms();
	EN=1;
	delay5ms();
	EN=0;
}

void Lcd1602_Write_dat(uchar dat)
{
	RW=0;
	RS=1;
	_nop_();
	EN=0;
	IO=dat;	
	delay1ms();
	EN=1;
	delay5ms();
	EN=0;	
}

void Lcd_Init()
{
	Lcd1602_Write_com(0x38);
	Lcd1602_Write_com(0x0c);
	Lcd1602_Write_com(0x06);
	Lcd1602_Write_com(0x01);
	Lcd1602_Write_com(0x80);
}

Then the lcd.h file

#ifndef _LCD_H
#define _LCD_H

typedef unsigned char uchar;
typedef unsigned int uint;

#define IO P0
sbit RW=P2^5;
sbit RS=P2^6;
sbit EN=P2^7;

void Lcd1602_Write_com(uchar com);
void Lcd1602_Write_dat(uchar dat);
void Lcd_Init();



#endif

The above is the whole of this small design. As a reference for the same design, this small program is still not perfect. It can't realize the division of the difference between two numbers that is too many times (I don't want to get ready to learn others). Is it possible to realize more advanced operations, such as continuous addition, subtraction, multiplication and division... Come on, everybody!

Topics: Single-Chip Microcomputer