Protues Simulation Design of Intelligent Calculator Based on 51 SCM

Table of contents

1. Design background

Two, realize the function

3. Hardware Design

3.1 Overall hardware design

​3.2 Design of keyboard circuit

3.3 Display circuit design

 4. Simulation demonstration

 5. Source program

1. Design background

       With the development of society and the advancement of science, people's living standards are gradually improving, especially the development of microelectronics technology, which is like mushrooming changes. It's no surprise that electronics are updated so quickly. Calculator is one of the more common electronic products in people's daily life. How to make the calculator technology more mature, make full use of the existing software and hardware conditions, design a better calculator, so that it can better serve various industries, has become an important research topic in the field of electronics today.

Two, realize the function

     This design is a calculator simulation system design based on the AT89C51 single-chip microcomputer. The input uses a 4×4 matrix keyboard, which can perform addition, subtraction, multiplication, and division of 4-digit signed numbers. The maximum operation is up to 9999*9999, which can be calculated . Negative number, and display the operation process on LCD1602.

3. Hardware Design

3.1 Overall hardware design

In order to better realize the functions of the system, the design of the hardware circuit should follow the following principles:

1. Optimize the hardware circuit

      The combination of software design and hardware design is adopted; although software is used to realize the functions of the hardware system, the response time may be longer than that of hardware alone, and it also takes up the time of the microprocessor (MCU); however, using software The function of the hardware can simplify the hardware structure and improve the reliability of the circuit. Therefore, when designing this system, on the premise of satisfying reliability and real-time performance, hardware functions should be realized through software as much as possible.

2. Reliability and anti-interference design

      According to reliability design theory, the fewer chips used in the system, the longer the mean time between failures of the system. Also, the fewer chips used, the less likely the address and data buses will be disturbed on the board. Therefore, the design philosophy of the system is to strive to use a smaller number of chips while satisfying the functions.

3. Flexible function expansion

     Whether the function expansion is flexible is an important indicator to measure the quality of a system. A design often cannot fully consider all aspects of the system, and the system needs to be continuously improved and upgraded. When performing function expansion, it should be completed on the basis of the original design by modifying the software program and a small amount of hardware. For this system, it is required that the function upgrade and expansion can be completed by modifying the software program under the condition that the system hardware remains unchanged.

     According to the system design scheme proposed in Section 1, combined with the above three principles, the design of the system hardware is determined. The calculator is mainly composed of the following functional modules: non-coding keyboard module, LCD liquid crystal display module, etc.

The figure below shows the overall hardware structure.

3.2 Design of keyboard circuit

       Keyboards can be divided into two categories: coded keyboards and non-coded keyboards. The coding keyboard is a combination of more buttons (more than 20) and a dedicated driver chip. When a button is pressed, it can handle problems such as button vibration and double-clicking, and directly output the code of the button without system software intervention. The standard keyboard used by general-purpose computers is a coded keyboard. In intelligent instruments, the parallel interface chip 8279 or the serial interface chip HD7279 can be used to form a coding keyboard, and at the same time it can also take into account the display drive of the digital tube. The related interface circuit and interface software can be obtained in the chip data. When the system function is more complex and the number of keys is large, the software design can be simplified by using a coded keyboard. From a cost point of view, this design selects a non-coding keyboard. As shown below:

3.3 Display circuit design

       When the system needs to display a small amount of data, it is an economical and practical method to use LCD liquid crystal display to display. Port P0 is used as the data port of the liquid crystal display, and ports P3.5-P3.7 are used as its control ports to control the LCD display to display output data. As shown below:

 4. Simulation demonstration

initial interface

 Add operation

Subtraction

multiplication

Division

 

5. Source program

#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
//--------LCD1602-------------------
//P00-07==== D0-7
sbit rs=P2^7;        //指令or数据
sbit wela=P2^6;      //读or写
sbit lcden=P2^5;	 //使能信号
//--------LCD1602-------------------
//--------KEY-----------------------
//P1口
//--------KEY-----------------------
uchar code table[]= "                ";

long  int data_a,data_b; 	//第一个数和第二个数
long  int data_c;			//计算结果

uchar dispaly[10];         //显示缓冲

//************************************************************************/
// 描述: 延时t us函数
//************************************************************************/
void LCD_Delay_us(unsigned int t)
{
	while(t--);           //t=0,退出
}
//************************************************************************/
// 描述: 延时t ms函数
//************************************************************************/
void LCD_Delay_ms(unsigned int t)
{
	unsigned int i,j;
	for(i=0;i<t;i++)       		//执行t次循环
	for(j=0;j<113;j++)     		//执行113次循环
	;
}
//************************************************************************/
// 描述: 1602液晶写指令
//************************************************************************/
void write_com(uchar com)    	//1602液晶写指令
{
	rs=0;                       //写指令
	lcden=0;                    //使能1602 
	P0=com;                     //写入指令com
	LCD_Delay_ms(1);            //延时1ms
	lcden=1;                    //使能1602
	LCD_Delay_ms(2);            //延时2ms  
	lcden=0;	                //使能1602
}
//************************************************************************/
// 描述:1602液晶写数据 
//************************************************************************/
void write_date(uchar date) //1602液晶写数据
{
	rs=1;                        //写数据
	lcden=0;                     //使能1602 
	P0=date;                     //写入数据date
	LCD_Delay_ms(1);             //延时1ms
	lcden=1;                     //使能1602
	LCD_Delay_ms(2);             //延时2ms
	lcden=0;	                 //使能1602
}
//************************************************************************/
// 描述:指定x,y写入字符函数
//************************************************************************/
 void W_lcd(unsigned char x,unsigned char y,unsigned char Data) 
 {     
	 if (y == 0){write_com(0x80 + x);}   //第一行  
	 else{write_com(0xc0 + x);}          //第二行
	 write_date( Data);                  //写入数据
 }
 //指定x,y写入字符串函数
 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
 {     
 if (y == 0){write_com(0x80 + x);} 		//第一行
 else{write_com(0xC0 + x);}        		//第二行
 while (*s)                        		//
 	{write_date( *s); s++;}      		//写入数据
 }
//************************************************************************/
// 描述:初始化液晶,及画面初始化 
//************************************************************************/
void init_lcd(void)            //初始化液晶,及画面初始化
{
	wela=0;                      //写液晶
	lcden=0;                     //使能1602
	write_com(0x38);             //8 位总线,双行显示,5X7 的点阵字符
	LCD_Delay_us(100);           //延时100us
	write_com(0x0c);             //开显示,无光标,光标不闪烁
	write_com(0x06);             //光标右移动
	write_com(0x01);             //清屏
	write_com(0x80);             //DDRAM 地址归0
}
//************************************************************************/
// 描述: 反转法键盘扫描 
//************************************************************************/
short keycheckdown()				/* 反转法键盘扫描 */
{

	short temp1,temp2,temp,a=0xff;
	P1=0xf0;						/* 输入行值(或列值) */
	LCD_Delay_ms(20);				/* 延时 */
	temp1=P1;						/* 读列值(或行值) */
	P1=0xff;
	LCD_Delay_ms(20);				/* 延时 */
	P1=0x0f;						/* 输入列值(或行值) */
	LCD_Delay_ms(20);				/* 延时 */	
	temp2=P1;						/* 读行值(或列值) */
	P1=0xff;
	temp=(temp1&0xf0)|(temp2&0xf);	/* 将两次读入数据组合 */
	switch(temp)					/* 通过读入数据组合判断按键位置 */
	{


		case 0x77 :a=0x0a;break;//  按键+   
		case 0x7b :a=0x0e; break;// 按键=	
		case 0x7d :a=0;	   break;// 按键0
		case 0x7e :a=0x0f; break;// 按键CE

		case 0xe7 :a=0x0d;break;// 	按键/
		case 0xeb :a=0x9;break; //  按键9
		case 0xed :a=0x8;break; //  按键8 
		case 0xee :a=0x7;break; // 	按键7

		case 0xd7 :a=0x0c;break;//  按键*
		case 0xdb :a=0x6;break; // 	按键6
		case 0xdd :a=0x5;break; // 	按键5
		case 0xde :a=0x4;break; // 	按键4

		case 0xb7 :a=0x0b; break;// 按键-
		case 0xbb :a=3;break;	//  按键3
		case 0xbd :a=2;break;	//  按键2
		case 0xbe :a=1;break;	//  按键1

		default :a=0xff;
	}
	return a;						/* 返回按键值 */
}
void display_a() //显示数据a
{
	dispaly[3]=data_a%10000/1000;    //千
	dispaly[2]=data_a%1000/100;      //百
	dispaly[1]=data_a%100/10;        //十
	dispaly[0]=data_a%10;            //个 

	write_com(0x80+0);               //显示数据a
	if(data_a>999){	write_date('0'+dispaly[3]);}      //显示千位
	if(data_a>99){	write_date('0'+dispaly[2]);}		 //显示百位
	if(data_a>9){	write_date('0'+dispaly[1]);}     //显示十位
	      	        write_date('0'+dispaly[0]);      //显示个位
}

void display_b() //显示数据b
{
	write_com(0x80+7); //第一行
	dispaly[3]=data_b%10000/1000;    //千
	dispaly[2]=data_b%1000/100;      //百
	dispaly[1]=data_b%100/10;        //十
	dispaly[0]=data_b%10;            //个 

if(data_b>999){	write_date('0'+dispaly[3]); }     //显示千位   
if(data_b>99) {	write_date('0'+dispaly[2]); }    //显示百位  
if(data_b>9)  {	write_date('0'+dispaly[1]); }     //显示十位
  			    write_date('0'+dispaly[0]);      //显示个位
}

//计算结果
void display_c(x)
{

	if(data_c<100000000&&data_c>-1)//溢出时显示错误
	{	

		dispaly[8]=data_c%1000000000/100000000;    	//万万
		dispaly[7]=data_c%100000000/10000000;    	//千万
		dispaly[6]=data_c%10000000/1000000;    		//百万
		dispaly[5]=data_c%1000000/100000;    		//十万
		dispaly[4]=data_c%100000/10000;    			//万
		dispaly[3]=data_c%10000/1000;    			//千
		dispaly[2]=data_c%1000/100;      			//百
		dispaly[1]=data_c%100/10;        			//十
		dispaly[0]=data_c%10;            			//个 
		write_com(0x80+6+0x40); //第一行
		if(x==4)
		{    
			if(data_c>99999999)	{	write_date('0'+dispaly[8]);}    //显示万万
			if(data_c>9999999)	{	write_date('0'+dispaly[7]);}   //千万
			if(data_c>999999)	{	write_date('0'+dispaly[6]);}    //百万
			if(data_c>99999)	{	write_date('0'+dispaly[5]);}    //十万
			if(data_b!=0)		{
									write_date('0'+dispaly[4]);    //万
									write_date('.');
									write_date('0'+dispaly[3]);    //千
									write_date('0'+dispaly[2]);    //百
									write_date('0'+dispaly[1]);    //十
									write_date('0'+dispaly[0]);    //个 
								}
		}
	else{
		if(data_c>99999999)	{	write_date('0'+dispaly[8]);}    //显示万万
		if(data_c>9999999)	{	write_date('0'+dispaly[7]);}    //千万
		if(data_c>999999)	{	write_date('0'+dispaly[6]);}    //百万
		if(data_c>99999)	{	write_date('0'+dispaly[5]);}    //十万
		if(data_c>9999)		{	write_date('0'+dispaly[4]);}    //万
		if(data_c>999)		{	write_date('0'+dispaly[3]);}    //千
		if(data_c>99)		{	write_date('0'+dispaly[2]);}    //百
		if(data_c>9)		{	write_date('0'+dispaly[1]);}    //十
								write_date('0'+dispaly[0]);    //个 
		}
	}
//	else  //溢出时显示错误
//	{
//		write_com(0x80+11+0x40); //第一行
//		write_date('E');         //显示 E 
//		write_date('r');         //显示R
//		write_date('r');		 //显示R
//		write_date('o');		 //显示O
//		write_date('r');		 //显示E
//	}
}

void eql(uchar x)//加减乘除运算
{
	switch(x)		/*功能键选择*/
			{   
				case 1:data_c=data_a+data_b;break; 		  //加  /* + S=1 */ /* 数值转换函数 */									
				case 2:if(data_a>=data_b){data_c=data_a-data_b;} /* - S=2 *///减
                       else{data_c=data_b-data_a;W_lcd(5,1,'-');} //负数符号
					   break;  	 
				case 3:data_c=(data_a*data_b);break;		  /* * S=3 *///乘
				case 4:if(data_b==0){LCD_Write_String(0,1,"Error !         ");}else{data_c=(data_a*10000)/data_b;}break;		  /* / S=4 *///除//溢出时显示错误
				case 0:break;
			}	  

}

void main()
{
	uchar   key=0xff;               //键值初始化
	uchar   n=0;		 			//第1个数可以按1-4次
	uchar   m=5; 					//第2个数可以按1-4次
	uchar   x=0; 
	data_a=0;                       //前一个数
	data_b=0;                       //后一个数
	data_c=0;                       //结果 
	init_lcd();  					//1602液晶初始化
	display_a();
    while(1)
	  {
	  	key=keycheckdown();			/*动态扫描键盘,返回按键对应值,赋给j        key=0到f */
		if(0xff!=key)				/*若返回值有效,进入内部处理程序*/
		{ 
		  if(key<10)
		  {
		  	if(key==0&&n==0) ;
			else
			{
				if(n<4){data_a=data_a*10+key;m=5;display_a();}n++;  //首先输入第一个数	
			}
	        if(key==0&&m==0) ;
			else
			{
				if(m<4){data_b=data_b*10+key;n=5;display_b();}m++;  //必须按了+-*/才能输入第二个数	
			}
		  }
          else
          {	switch(key)		/*功能键选择*/
					{
						case 0xa:n=5;m=0;x=1;W_lcd(5,0,'+');break; //加  /* + S=1 */ /* 数值转换函数 */									
						case 0xb:n=5;m=0;x=2;W_lcd(5,0,'-');break;		  /* - S=2 *///减
						case 0xc:n=5;m=0;x=3;W_lcd(5,0,'*');break;		  /* * S=3 *///乘
						case 0xd:n=5;m=0;x=4;W_lcd(5,0,'/');break;		  /* / S=4 *///除
						case 0xe:n=5;m=5;eql(x);W_lcd(12,0,'=');display_c(x);break; 	  /* = */
						case 0xf:n=0;x=0;m=5; data_a=0;data_b=0;data_c=0;LCD_Write_String(0,0,table);LCD_Write_String(0,1,table);W_lcd(0,0,'0');break; /*     C*/
					}	  		  
		  }
			do{P1=0xf0;}while(P1!=0xf0);		/*等待按键松开*/
	  	}//(0xff!=key)	  
	  }//while
}//main

Guess you like

Origin blog.csdn.net/weixin_53402301/article/details/129518350