计算器 1602 和 矩阵键盘栈实现

奉上全部源代码,功能比较简单,具体的日后补充
/**************************************
	计算器 1602 和矩阵键盘实现
		   
****************************************/

#include<reg52.h>

typedef unsigned int  uint;
typedef unsigned char uchar;



typedef struct	   //定义栈存运算符和运算数,用同一个
{
	long e[16];
	int top;	
}stacks;
typedef stacks *stack;
 

uchar Isempty(stack s);
uchar Isfull(stack s);		 
void Push(long,stack s); 	//入栈
long Pop(stack s);   		//从栈弹出元素,并返回此值
long Top(stack s);	 		//返回栈顶
uchar Isop(long x);  		//判断是否为运算符
uchar Comp(uchar op1,long op2);//比较两个运算符的优先级

 
void init();			//初始化函数
void inita(uint *);	//数组初始化
void delay(uint );			
void wcom(uchar com);	//1602写指令函数
void wdata(uchar dat);	//写数据函数
void wstr(uchar line,uchar *str);  //写字符串
uchar keyscan();	  	//键盘扫描
void calculate();		//计算函数 
void exe(long op);		//四则运算函数
void disp(long result);	//将结果送到1602显示  max 2147483647

sbit  rs=P1^5;	  
sbit  rw=P1^6;	
sbit  e=P1^7;		//lcd使能
sbit  duan=P1^0;    //数码管段 
sbit  wei=P1^1;     //数码管位
sbit  deng=P1^2;    //流水灯
sbit  zhen=P1^3; 	//点阵

bit err=0;			//出错标志,有错为1
uchar exp[16];		//表达式
uchar prkey,key=0;	//上一个键值,本次键值
uchar op[4]= {'+','-','*','/'};
uchar cmparr[4][4]=	//比较矩阵
{{1,1,2,2},
{1,1,2,2},
{0,0,1,1},
{0,0,1,1}};

uchar wlcom[16]={" welcome to use "},
	  warn1[16]={"    overflow!   "};	 //溢出
	  
stacks opr;	 //	运算符栈
stacks num;	 //	运算数栈




//主函数*********************************
main()
{	
	init();
	wcom(0x80);			//显示欢迎
	wstr(1,wlcom);
	delay(800);
	wcom(0x01);
	while(1)
	{ 
		calculate();
		disp(Top(&num));	 
				   
	}
	

}


//初始化函数****************************************
void init()
{
	duan=wei=zhen=1;
	P0=0;
	duan=wei=zhen=0;
	
	deng=1;
	P0=0xff;
	deng=0;
	e=0;
	
		//1602 
	wcom(0x38);
	wcom(0x0c);
	wcom(0x06);
	wcom(0x01);
		//栈初始化
	opr.top=-1;
	num.top=-1;
	
	
}
//数组初始化函数************************
void inita (uchar *a)
{
	uchar i;
	for(i=0;i<16;i++)
	{
		a[i]='=';
	}
}
//延时*********************************
void delay(uint d)
{
	uint i;
	while(d--)
	{
		for(i=0;i<100;i++);
	}
}

//lcd写字符串*******************************
void wstr(uchar line,uchar *str)		  
{
	uchar n;
	if(line==1)
	{	wcom(0x80);
		for(n=0;n<16;n++)
		{
		 wdata(str[n]);
		}
	}
	else
	{
		wcom(0xc0);
		for(n=0;n<16;n++)
		{
		 wdata(str[n]);
		}
	}		
} 
//lcd写命令**********************************
void wcom(uchar com)
{
		rs=0;
		rw=0;
		e=0;
		P0=com;
		e=1;
		delay(5);
		e=0;
}

//lcd写数据************************************
void wdata(uchar dat)
    {
		rs=1;
		rw=0;
		e=0;
		if(dat)
			P0=dat;
		else
			wcom(0x80);
		e=1;
		delay(5);
		e=0;
}
//矩阵键盘扫描 *****************************

uchar keyscan()
{		
 	uchar temp,col,row;	
	P2=0xf0;
	temp=P2;
	while(temp==0xf0)	//等待按键按下
	{
		temp=P2;
		temp=temp&0xf0;
	}
	prkey=key;  	 //储存上一个键值
	temp=P2;
	temp=temp&0xf0;
	if(temp!=0xf0)
	{
		delay(20);
		if(temp!=0xf0)
		{
			row=P2&0xf0;
			P2=row|0x0f;
			col=P2&0x0f;
			switch(row+col)
			{
				case 0x7e: key='1';break;
				case 0xbe: key='2';break;
				case 0xde: key='3';break;
				case 0xee: key='+';break;
				case 0x7d: key='4';break;
				case 0xbd: key='5';break;
				case 0xdd: key='6';break;
				case 0xed: key='-';break;
				case 0x7b: key='7';break;
				case 0xbb: key='8';break;
				case 0xdb: key='9';break;
				case 0xeb: key='*';break;	
				case 0x77: key='0';break;	
				case 0xb7: key='D';break;	//功能删除上一个输入	
				case 0xd7: key='=';break;	
				case 0xe7: key='/';break;					 
			}

		}
	}
	P2=0xf0;
	delay(50);
	while(temp!=0xf0)		//等待按键弹起
	{
		temp=P2;
		temp=temp&0xf0;
	}
	if(key!='='&&key!='D')
	{	
		if(prkey=='=')	   //第二次计算开始,清屏,清错
		{	
			wcom(0x01);
			err=0;
		}

		wdata(key);
	}	   
   return(key);   //返回键值

}
//四则运算函数******************************************
void exe(long op)		 
{
	long a,b,re;
	a=Pop(&num);
	b=Pop(&num);	 
   	switch(op)
   {
   	case '+': re=b+a;
			  if(re-a!=b)		  //判断是否溢出
			  {wstr(2,warn1);
			  	err=1;}break;
	case '-': re=b-a;
			  if(re+a!=b)
			  {wstr(2,warn1);
			  	err=1;}break;
	case '*': re=b*a;
			  if(re/a!=b)
			  {wstr(2,warn1);
			  	err=1;}break;
	case '/': re=b/a;
			  if(re*a!=b)
			  {wstr(2,warn1);
			  	err=1;}break;
   }
   
	Push(re,&num);
		
}

//计算函数******************************************

void calculate()
{
	long tmp=0;
	uchar m=0,n=0,i=0;
	
	inita(exp);			//初始化表达式
	 
	keyscan();			//扫描键盘,更新key值
	while(key!='=')		//将键盘输入转换成字符数组表达式exp
	{	
		if(key=='D')
			{
				exp[--i]='=';
				wcom(0x10);
				wdata(0xfe);
				wcom(0x10);
			}
		else
			exp[i++]=key;
		keyscan();		 //扫描键盘,更新key值
	}
	
	i=0;
	while(exp[i]!='=')
	{
		while(!Isop(exp[i])&&exp[i]!='=')	//转换成十进制
		{
			tmp=tmp*10+(exp[i++]-'0');
		}
		Push(tmp,&num);		  //数入栈
	
		tmp=0;				  
		if(Isempty(&opr))
			Push(exp[i++],&opr);
		else if(exp[i]!='=') 
			switch(Comp(exp[i],Top(&opr)))	 //比较读到的运算符与栈顶的运算符优先级
			{
			   case '>':Push(exp[i++],&opr);break;

			   case '=':exe(Pop(&opr));
			   			Push(exp[i++],&opr);break;

			   case '<':while(!Isempty(&opr))
			   			{
						 	exe(Pop(&opr));	
						}
			   			Push(exp[i++],&opr);break;	
			}
		 else
		 	while(!Isempty(&opr))		  //当读到‘=’,把栈内剩下的都计算完毕
			{										
				exe(Pop(&opr));
			}
			

	}
	
	 	
											 
}
//将十进制结果送到lcd显示
void disp(long result)
{  
	uchar n=0,sign;
	wcom(0xcf);	//从第二行最后开始显示
	wcom(0x04);	//AC自动减一
	sign=result<0;	//sign为正负标记位,
	if(sign)	
		result=~result+1;  
	if(err==0)  //无错才显示
	{	
		do
		{	
			wdata((result%10)+'0');
			n++;	
		}while((result=result/10)!=0);
		if(sign)		   //如果是负数,写负号
		{
			wdata('-');
		}
	}
/*	stacks r;
	r.top=-1;	// 栈r初始化

	
	do
	{
		Push(result%10,&r);						
	}while((result=result/10)!=0);
	
	while(!Isempty(&r))
	{
		 wdata(Pop(&r)+'0');
	}
*/	
	  
}
//栈相关函数*******************************
uchar  Isempty(stack s)		   //判空
{
	return  s->top==-1;
}

uchar Isfull(stack s)			//判满
{
	return s->top==15;
} 

void Push(long x,stack s)	 //元素入栈
{
	if(!Isfull(s))
		s->e[++s->top]=x;	
}

long Pop(stack s)				//出栈
{
	if(!Isempty(s))
	{	s->top--;
		return s->e[s->top+1];
	}
}
long Top(stack s)			 //返回栈顶
{
	if(!Isempty(s))
		return s->e[s->top];
}

uchar Isop(uchar x)		 //判断是否为运算符
{
	uchar i;
	for(i=0;i<5;i++)
	{
		if(x==op[i])
		return 1;	
	}
	return 0;	
}
//比较函数************************************
uchar Comp(uchar op1,long op2)	   //op1输入运算符,op2栈顶运算符
{
	uchar i,m,n,p;
	for(i=0;i<4;i++)
	{
		if(op1==op[i])
			m=i;
		if(op2==op[i])
			n=i;
	}	
	switch(cmparr[m][n])
	{
	case 0: p='>';break;
	case 1: p='=';break;
	case 2: p='<';break;
	}		
	return p;	
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值