基于51单片机简易计算器LCD1602显示

         protues中有KEYPAD-SMALLCALC直接就是4*4的矩阵:

                        ​​​​​​​        基于51单片机简易计算器LCD1602显示_第1张图片

        做完之后才发现了,当时不知道,自己画了一个4*4的矩阵键盘

1.protues仿真图

基于51单片机简易计算器LCD1602显示_第2张图片

2.源程序

        注释我写的很详细

#include "reg52.h"
typedef unsigned int uint;	  //定于无符号int
typedef unsigned char uchar;  //定义无符号char
sbit rw=P2^5;            
sbit rs=P2^6;            
sbit e=P2^7;             

uint fuhao,flag,k,i,j,num;          
uchar disp[]="     ERROR!";//除数为0时,显示 
uchar wel[]="    Welcome!";//初始化时显示 
long a,b,c,x;

void delay(long i)  //延时
{
	while(i--);
}

void Delay1000ms()		//@11.0592MHz   STC-ISP软件延时计算器生成延时一秒函数
{
	unsigned char i, j, k;
	i = 43;
	j = 6;
	k = 203;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void lcdwrc(uint c) //设置LCD写命令
{
	delay(1000);
	rs=0;
	rw=0;
	e=0;
	P0=c;
	e=1;
	delay(1000);
	e=0;
}


void lcdwrd(uint dat) //设置LCD写数据
{
	delay(1000);
	rs=1;
	rw=0;
	e=0;
	P0=dat;
	e=1;
	delay(1000);
	e=0;
	rs=0;
}

void lcdinit()	  //初始化LCD
{
	delay(1500);
	lcdwrc(0x38);
	delay(500);
	lcdwrc(0x38);
	delay(500);
	lcdwrc(0x38);
	delay(500);
	lcdwrc(0x38); //功能设定指令
	lcdwrc(0x08);  //
	lcdwrc(0x01); //清屏
	lcdwrc(0x06);  //设置LCD显示
	lcdwrc(0x0c); //显示开关控制指令
    num=0;
	fuhao=0;
	flag=0;
	a=0;
	b=0;
	c=0;
	x=0;
	k=0;
	j=0;
}

void KeyDown()     //按键函数
{
    k=0;     
	P1=0x0f;   //后列前行 列都为高电平1,行都为低电平0 
	if(P1!=0x0f)//有按键被按下 
	{
		delay(1000);
	  	if(P1!=0x0f)//延时再次判断,软件消抖 
		{
			P1=0x0f;//列都为高电平1,行都为低电平0
			switch(P1)
			{
				case 0x07:      //0000 0111 第一列有按键被按下 
				{
					P1=0xf0;//列都为低电平0,行都为高电平1 
					switch(P1)//判断哪一行的按键被按下 
   				    {
				    	case 0x70: num = 1;k=7;break;    //0111 0000第一列第一行 
				     	case 0xb0: num = 5;k=4;break;    //1011 0000第一列第二行 
					 	case 0xd0: num = 9;k=1;break;    //1101 0000第一列第三行 
					 	case 0xe0: num = 13;break;       //1110 0000第一列第四行 
		        	} 
					if(num!=13)//被按下的按键不是清零键 
					{
						if(fuhao==0)//fuhao==0,表示第一个数a,fuhao==1,表示第二个数b 
							a=a*10+k;
						else
							b=b*10+k;
					}
					lcdwrd(0x30+k);//显示按下的数,0x3y:显示y 
			    	if(num==13)//按下的按键是清零键
					{	 
						lcdwrc(0x01);	//清屏指令			
						lcdinit();//重新初始化LCD1602 
					}						
			    }
			    while(P1!=0xf0);break;//当有按键被按下时,结束此次判断,进行下一次判断 

            	case 0x0b: //0000 1011 第二列有按键被按下 
				{
					P1=0xf0;//列都为低电平0,行都为高电平1
		            switch(P1)//判断哪一行有按键被按下 
		 		    {
						case 0x70: k=8;break;//第二列第一行 
			            case 0xb0: k=5;break;//第二列第二行 
			            case 0xd0: k=2;break;//第二列第三行 
				        case 0xe0: k=0;break;//第二列第四行 
		            }  	
					if(fuhao==0)
						a=a*10+k;
					else
					   b=b*10+k;	
				    lcdwrd(0x30+k);	
				}
				while(P1!=0xf0);break;

			 	case 0x0d: //0000 1101 第三列有按键被按下 
			    {
					P1=0xf0;
		            switch(P1)
		            {
						case 0x70: num=3;k=9;break;//第三列第一行 
			            case 0xb0: num=7;k=6;break;//第三列第二行 
			            case 0xd0: num=11;k=3;break;//第三列第三行 
			            case 0xe0: num=15;break;//第三列第四行 
			        }	
					if(num!=15)
					{	
						if(fuhao==0)
							a=a*10+k;
						else
						    b=b*10+k;	
						lcdwrd(0x30+k);
				 	}
					if(num==15)//按下的键为=键 
					{
						switch(flag)//判断进行哪种运算 
						{
							case 1://+
							{
								c=a+b;//计算结果 
								lcdwrc(0x4f+0x80);//光标置于第二行末尾 
					            lcdwrc(0x04);//设置显示方式:显示后指针减一 
								if(c==0)//若结果为0 
									lcdwrd(0x30);//显示0 
							    while(c!=0)
					            {
									lcdwrd(0x30+c%10);//从最后一位开始显示 
						            c=c/10; 
						        }
								lcdwrd(0x3d);//显示= 
							}
							break;

							case 2://-
							{
								if(a>b)
									c=a-b;
						        else
							        c=b-a;//计算两数相减的绝对值 

								lcdwrc(0x4f+0x80);//将光标置于第二行末尾 
			                    lcdwrc(0x04);//设置显示方式:显示后指针减一 

								if(c==0)//若结果为零 
									lcdwrd(0x30);//显示0 

								while(c!=0) 
					            {
									lcdwrd(0x30+c%10);//从最后一位开始显示
						           	c=c/10;
					           	}
					            if(a0&&x<=9)
						        	    {
											if(k==1)//只有小数点后最后一位
											{	
												lcdwrd(0x30);//0
												lcdwrd(0x30);//0
												lcdwrd(0x30);//0 
												lcdwrd(0x2e);//.
												k=0;
											}
						        	    }
						         	    if(x>9&&x<=99)
						        	    {	
											if(k==2)//只有小数点后最后两位
											{	
												lcdwrd(0x30);//0
												lcdwrd(0x30);//0
												lcdwrd(0x2e);//.
												k=0;
											}
										}
						            	if(x>99&&x<=999)
							            {
											if(k==3)//只有小数点后最后三位
											{
												lcdwrd(0x30);//0
												lcdwrd(0x2e);//.
												k=0;
											}	
										}
						               	else if(k==4)//小数点后四位都有
										{
											lcdwrd(0x2e);//.
											k=0;
										}		
							        }
									if(x<10000)
										lcdwrd(0x30);//若结果小于1,在各位补充0 
									lcdwrd(0x3d);//显示=	  
								} 
							}	
							break;
					    }
					}
				}
				while(P1!=0xf0);
					break;
				case 0x0e: //0000 1110
				{	
					fuhao=1; //有符号键被按下 
					P1=0xf0; //1111 0000
			        switch(P1)
		            {
						case 0x70:/*0111 0000*/flag=4;lcdwrd(0xfd);break;//除号第四列第一行 
				        case 0xb0:/*1011 0000*/flag=3;lcdwrd(0x2a);break;//*   第四列第二行 
			            case 0xd0:/*1101 0000*/flag=2;lcdwrd(0x2d);break;//-   第四列第三行 
			            case 0xe0:/*1110 0000*/flag=1;lcdwrd(0x2b);break;//+   第四列第四行 
		            }	 
	            }  
				while(P1!=0xf0);break;
			}
	 	}
	}
}
	    
void main()
{	
    uint x;
	lcdinit();//LCD1602初始化 
	for(x=0;x<12;x++)
		lcdwrd(wel[x]);//显示欢迎语句:Welcome 
	Delay1000ms();//STC-ISP软件延时计算器1s延时函数 
	lcdwrc(0x01);//LCd1602清屏 
	while(1)		
   		KeyDown();//按键判断函数 
}

你可能感兴趣的:(51单片机,51单片机,单片机,proteus)