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

来源:互联网 发布:知乎注册设备id不匹配 编辑:程序博客网 时间:2024/05/21 08:54
奉上全部源代码,功能比较简单,具体的日后补充
/**************************************计算器 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 2147483647sbit  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;//出错标志,有错为1uchar 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;elsewcom(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);}elseexp[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;}

原创粉丝点击