51单片机LCD1602实现计算器

整合代码
详细文章(带仿真图)见链接
https://blog.csdn.net/xiantiaoop/article/details/107052493

#include 
#define uc unsigned char 
#define ut unsigned int 
#define kong1  P1 //控制矩阵按键
                  // kong0=P0 发送命令发送数据
uc code  a[]={'0','1','2','3','4','5','6','7','8','9','+','-','*','/','='};

long sum1,sum2;
float sum3 ; //用于除法
long sum4,sum5; //用于除法;
uc addflag,subflag,mulflag,divflag;
uc keyflag; //	在keyvaluechuli()函数中控制
uc flag ;// 控制乘中的sum1;
uc keyvalue=100; 

sbit RS=P2^6;
sbit RW=P2^5;
sbit EN=P2^7;

void delay1ms(ut t);

void LCDcmd(uc cmd);

void LCDdat(uc dat);

void LCDinitial( );
void delay10us(ut t)   //误差 0us
{
       uc a;
        for(;t>0;t--)
        for(a=2;a>0;a--);
}



//判断按键值


void delay1ms(ut t)   //误差 0us
{
    unsigned char a,b;
    for( ;t>0;t--)
        for(b=199;b>0;b--)
 
 
            for(a=1;a>0;a--);
}



void LCDcmd(uc cmd)
{
	 EN=0;
	 RS=0;
	 RW=0;
     kong1=cmd;
	 delay1ms(1);
	 EN=1;
	 delay1ms(5);
	 EN=0;


}


 
void LCDdat(uc dat)
{

  EN=0;
  RS=1;
  RW=0;					  //RS=0; RW=1
  kong1=dat;
  delay1ms(1);
  EN=1;
  delay1ms(5);
  EN=0;

}

 void LCDinitial()
{

   LCDcmd(0x38); //设置功能模式
   LCDcmd(0x0c);// 开显示
   LCDcmd(0x06);//写一位指针加一
   LCDcmd(0x01);//清屏
   LCDcmd(0x80); //初始地址


}

				 
uc  keypanduan() //返回按键值	
{					
	 uc cc;  //cc作为返回值 aa控制强制退出 
     kong1=0xf0;
   if(kong1!=0xf0)  //先判断行
   {
		delay10us(100);	  //1000us
	
	  if(kong1!=0xf0)
	  {

		cc=kong1;
		keyflag=1;

	  }
   }  
   
     kong1=0x0f ;// 判断列
    if(kong1!=0x0f)
	{

	   delay10us(100);
       if(kong1!=0x0f)
	   {
	    cc=cc|kong1; //得到按键值
	   }

	  }

	while(kong1!=0x0f);
	
  return cc;

 }
 
 
 
 //通过对应的按键值对应value 在
 //keyvaluechuli()函数中对value进行处理 
void keyswitch(uc key)
{
  

					
  switch(key){
     
	 case 0xe7:   keyvalue=1;  break;
												 // +  -  *  /
	 case 0xd7:	  keyvalue=2;  break;			 // 3  6  9  清零
												 // 2  5  8  =
	 case 0xb7:   keyvalue=3;  break;			 // 1  4  7  0

	 case 0xeb:   keyvalue=4;  break;
							  
	 case 0xdb:	  keyvalue=5;  break;

	 case 0xbb:	  keyvalue=6;  break;

	 case 0xed:	  keyvalue=7;  break;

	 case 0xdd:	  keyvalue=8;  break;

	 case 0xbd:	  keyvalue=9;  break;

	 case 0xee:   keyvalue=0;  break;

	 case 0x77:	  keyvalue=10; break; //加法
	
	 case 0x7b:   keyvalue=11; break;// 减法		 
     
	 case 0x7d:	  keyvalue=12; break;//乘法

	 case 0x7e:	  keyvalue=13; break;//除法

	 case 0xde:	  keyvalue=14; break;//等于

	 case 0xbe:	  keyvalue=15; break;//	清屏
	 default :break;


  }
 
  
}   




void shujuchuli()  //  0~9
{
   if(keyvalue==15)
   { 
     LCDcmd(0x01);
	 sum1=sum2=0;
	 addflag=0;
	 subflag=0;
	 mulflag=0;
	 divflag=0;	 

   }
   if(keyvalue<10)
   {
     if(flag==1)   //flag在乘中控制使按下一个数据清除sum1
	 {
	  sum1=0;
	  flag=0;
	 }
	  sum1=sum1*10+keyvalue;
	  LCDdat(a[keyvalue]);
   }


}

void jiafa()
{

  addflag++;
  subflag=mulflag=divflag=0;
  if(addflag>1)
  {
  sum1=sum1+sum2;
  }
  sum2=sum1; 
  sum1=0;

 

}


void jianfa()
{

   subflag++;
   addflag=mulflag=divflag=0;
  if(subflag==1)
  
  {
   sum2=sum1;
  }
  if(subflag>1)
  {
   sum2=sum2-sum1;
   }
   sum1=0;
}


void chengfa()
{
  mulflag++;
  subflag=addflag=divflag=0;
  flag=1;
  if(mulflag>1)
  {
   sum1=sum1*sum2;

   }
  

   sum2=sum1;
  
}


void chufa()
{
   divflag++;
   subflag=mulflag=addflag=0;
   if(divflag==1)
  
  {
    sum3=sum1;
  }

  if(divflag>1)
  {
  	sum3=sum3/sum1;		   //除法保留3位小数

  }

  sum1=0;
}




void dengyu()
{



 	if(addflag)		  //加法
	{
	    sum2=sum1+sum2;
	   	LCDcmd(0x4f+0x80);
		LCDcmd(0x04);
		while(sum2!=0)
		{

		 LCDdat(0x30+sum2%10); 
		 sum2/=10;

		}
   	  	LCDdat('=');
	
	   	addflag=0;

	}



	if(subflag)		 //减法
	{
	   	sum2=sum2-sum1;
	  	LCDcmd(0x4f+0x80); //从第二行从右向左写数据
		LCDcmd(0x04);
		if(sum2>=0)
		{
		   while(sum2!=0)
		   {

		      LCDdat(0x30+sum2%10);
		       sum2/=10;

		    }
		 
		}
		else
		{
	
			sum2=-sum2;
		    while(sum2!=0)
		   {

		   LCDdat(0x30+sum2%10);
		   sum2/=10;

		    }
	         LCDdat('-');

		}

	        LCDdat('=');
	

	         subflag=0;
	   
	}





   if(mulflag)	    //乘法
   {
	   	sum2=sum1*sum2;	  
	   LCDcmd(0x4f+0x80);
       LCDcmd(0x04);
     while(sum2!=0)
     {
  
	  LCDdat(0x30+sum2%10);
	  sum2/=10;

     }
        LCDdat('=');

	   mulflag=0;
   }


//除法结果小于0.1和等于0.1和等于以上3种情况	
//放大了1000000倍 再通过取余的方法求数据			 
  if(divflag)		 //除法
  {
	   	uc cent=0;
        uc k=0,i=0;
		sum2=(sum3/sum1)*1000000;//保留6位小数	
	   	LCDcmd(0x4f+0x80);
        LCDcmd(0x04);
	


	 if(sum2==100000)
	 {

		    while(sum2!=0)
		{
		   LCDdat(0x30+sum4%10);
		   sum4/=10;

		}
		for(i=0;i<cent;i++)
		{

			 if(i==cent-2)
			 {

				LCDdat(0x30); //0
				LCDdat('.');

			 }
			 else
			  {

				 LCDdat(0x30); //0

			  }

	    }
		cent=0;
	}
	 if(sum2<100000)  
	 {
	 	 sum4=sum2;	
		 sum5=sum2;	 
		 while(sum5<100000)
		 {
			 cent++;
			 sum5*=10;

		 }

	    while(sum4!=0)
		{
		   LCDdat(0x30+sum4%10);
		   sum4/=10;

		}
		for(i=0;i<=cent;i++)
		{

			 if(i==cent-1)
			 {

				LCDdat(0x30); //0
				LCDdat('.');

			 }
			 else
			  {

				 LCDdat(0x30); //0

     	      }

		}
	 
	 }	
    if(sum2>100000)
	{	
				  
	  while(sum2!=0)
	   {
		    k++;	      //k到3时写小数点
		    LCDdat(0x30+sum2%10);
			sum2/=10;
			if(k==6)
			{
			   
			     LCDdat('.');
			    if(sum2==0)
			    {

				 LCDdat(0x30);  //写0

			    }
			}

	   }




		 LCDdat('=');
    	 divflag=0;

   }

   }
  }





void keyvaluechuli()  //对key的值进行处理
{
	 if(keyflag)	   //表明 按键按下 
	 {
	   keyflag=0;  
	  switch(keyvalue)
	  {

  	  case 10:jiafa();	 LCDdat(a[keyvalue]);break;	  
	  case 11:jianfa();	 LCDdat(a[keyvalue]);break;
	  case 12:chengfa(); LCDdat(a[keyvalue]);break;
	  case 13:chufa();	 LCDdat(a[keyvalue]);break;
	  case 14:dengyu();  break;
	  default:shujuchuli( );   // 0~9 和清零						 
     }


	 }
}




void main()
{

 uc yy=0; 
 LCDinitial( );
 while(1)
 {

   yy=keypanduan();	//按键值赋值给yy;
  
   keyswitch(yy);   //得到对应的value值
   keyvaluechuli();  //对value值对应的功能进行处理
  
  

 }



}



你可能感兴趣的:(51单片机,计算器,51单片机,单片机)