奉上全部源代码,功能比较简单,具体的日后补充
/**************************************
计算器 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;
}