基于STC89C51的计算器的实现
实验器件:STC89C51单片机一个,lcd1602显示屏一个,杜邦线若干
话不多说直接上图
proteus仿真图如下:
依据仿真图实现的实物图如下:
看完效果图,接下来就是项目源代码
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={7,8,9,0,4,5,6,0,1,2,3,0,0,0,0,0};
uchar code table1[]={7,8,9,0x2f-0x30,4,5,6,0x2a-0x30,1,2,3,0x2d-0x30,0x01,0,0x3d-0x30,0x2b-0x30};
uchar code table2[]="Prog is written ";
uchar code table3[]="by dx171-djw&cyl";
uchar table4[16];
char i,j,temp,num;
long a,b,c,d;
uchar flag,fuhao,fuhao_next,k,x,y,m,n;
sbit RS=P2^0;
sbit RW=P2^1;
sbit EN=P2^2;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)
{
RS=0;
EN=0;
P0=com;
delay(1);
EN=1;
delay(1);
EN=0;
}
void write_data(uchar da)
{
RS=1;
EN=0;
P0=da;
delay(1);
EN=1;
delay(1);
EN=0;
}
void init()
{
uchar num;
num=-1;
RW=0;
EN=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
for(num=0;num<16;num++)
{
write_data(table2[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<16;num++)
{
write_data(table3[num]);
delay(5);
}
delay(5000);
write_com(0x01);
i=0;
j=0;
a=0;
b=0;
c=0;
d=0;
flag=0;
fuhao=0;
fuhao_next=0;
m=0;
n=0;
x=0;
y=0;
}
void keyscan()
{
P3=0xfe; //扫描
if(P3!=0xfe)
{
delay(10); //延时,去除按键抖动
if(P3!=0xfe)
{
temp=P3&0xf0;
switch(temp) //判断按键
{
case 0xe0:num=0; break; //"7"
case 0xd0:num=1; break; //"8"
case 0xb0:num=2; break; //"9"
case 0x70:num=3; break; //"÷"
}
}
while(P3!=0xfe);
if(num==0|num==1|num==2) //数字
{
if(j==1) //计算完成(按过"="号)
{
write_com(0x01); //清屏
j=0; //等号标志位清零
}
if(flag==0) //没有按过符号
{
a=a*10+table[num]; //连续存储数字
m=1; //数字输入数量+1
}
else if(flag==1) //按过一次符号
{
b=b*10+table[num];
if(m>=n) //当符号和数字数量比正确时
m=2; //数字输入数量+1
else
m=0; //否则清零,
}
else if(flag==2) //按过两次符号
{
c=c*10+table[num];
if(m>=n)
m=3; //数字输入数量+1
else
m=0;
}
}
else //符号
{
if(j==1) //
{
write_com(0x01); //
j=0; //
}
flag++; //每按一次符号,符号标志位+1
n++; //每按一次符号,符号比较标志位+1
if(flag==1) //第一次按符号
fuhao=4; //符号计算标志位1等于每个符号的对应数字(1"+" 2"-" 3"×" 4"÷")
if(flag==2) //第二次按符号
fuhao_next=4; //符号计算标志位2同样赋值
}
i=table1[num]; //把数组中键盘输入对应的值赋给i
write_data(0x30+i); //打印键盘输入的数字或符号
}
P3=0xfd;
if(P3!=0xfd)
{
delay(10);
if(P3!=0xfd)
{
temp=P3&0xf0;
switch(temp)
{
case 0xe0:num=4; break;
case 0xd0:num=5; break;
case 0xb0:num=6; break;
case 0x70:num=7; break;
}
}
while(P3!=0xfd);
if(num==4|num==5|num==6)
{
if(j==1)
{
write_com(0x01);
j=0;
}
if(flag==0)
{
a=a*10+table[num];
m=1;
}
else if(flag==1)
{
b=b*10+table[num];
if(m>=n)
m=2;
else
m=0;
}
else if(flag==2)
{
c=c*10+table[num];
if(m>=n)
m=3;
else
m=0;
}
}
else
{
if(j==1)
{
write_com(0x01);
j=0;
}
flag++;
n++;
if(flag==1)
fuhao=3;
if(flag==2)
fuhao_next=3;
}
i=table1[num];
write_data(0x30+i);
}
P3=0xfb;
if(P3!=0xfb)
{
delay(10);
if(P3!=0xfb)
{
temp=P3&0xf0;
switch(temp)
{
case 0xe0:num=8; break;
case 0xd0:num=9; break;
case 0xb0:num=10; break;
case 0x70:num=11; break;
}
}
while(P3!=0xfb);
if(num==8|num==9|num==10)
{
if(j==1)
{
write_com(0x01);
j=0;
}
if(flag==0)
{
a=a*10+table[num];
m=1;
}
else if(flag==1)
{
b=b*10+table[num];
if(m>=n)
m=2;
else
m=0;
}
else if(flag==2)
{
c=c*10+table[num];
if(m>=n)
m=3;
else
m=0;
}
}
else
{
if(j==1)
{
write_com(0x01);
j=0;
}
flag++;
n++;
if(flag==1)
fuhao=2;
if(flag==2)
fuhao_next=2;
}
i=table1[num];
write_data(0x30+i);
}
P3=0xf7;
if(P3!=0xf7)
{
delay(10);
if(P3!=0xf7)
{
temp=P3&0xf0;
switch(temp)
{
case 0xe0:num=12; break;
case 0xd0:num=13; break;
case 0xb0:num=14; break;
case 0x70:num=15; break;
}
}
while(P3!=0xf7);
switch(num)
{
case 12:
{
write_com(0x01);
a=0;
b=0;
c=0;
flag=0;
fuhao=0;
fuhao_next=0;
k=0;
x=0;
y=0;
m=0;
n=0;
}
break;
case 13:
{
if(j==1)
{
write_com(0x01);
j=0;
}
if(flag==0)
{
a=a*10;
write_data(0x30);
m=1;
}
if(flag==1)
{
b=b*10;
write_data(0x30);
if(m>=n)
m=2;
else
m=0;
}
if(flag==2)
{
c=c*10;
write_data(0x30);
if(m>=n)
m=3;
else
m=0;
}
}
break;
case 14:
{
j=1; //等号标志位置1
if(m<=n) //当数字数量少于或等于符号时,做出错误提示
{
write_com(0x01); //清屏
write_com(0x80+0x4f); //移动到LCD1602第二行末尾
write_com(0x04); //倒序书写
write_data('!');write_data('R');write_data('O'); //显示ERROR!
write_data('R');write_data('R');write_data('E'); //
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0; //所有变量及标志位清零
}
if(fuhao==1)
{
write_com(0x80+0x4f);
write_com(0x04);
if(((fuhao_next==4)&&(c==0))==0)
{
d=a+b;
if(fuhao_next==1)
d=a+b+c;
else if(fuhao_next==2)
{
if(a+b-c>=0)
d=a+b-c;
else
{
d=c-a-b;
k=1;
}
}
else if(fuhao_next==3)
d=a+b*c;
else if(fuhao_next==4)
{
i=0;
d=(long)((a+(float)b/c)*1000);
if((long float)d/1000<1&(long float)d/1000>0)
y=1;
}
if(d==0|y==1)
x=1;
while(d!=0)
{
write_data(0x30+d%10);
d=d/10;
if(fuhao_next==4)
{
i++;
if(i==3)
write_data(0x2e);
}
}
if(x)
write_data(0x30);
if(k)
write_data(0x2d);
write_data(0x3d);
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0;
}
else
{
write_com(0x01);
write_com(0x80+0x4f);
write_com(0x04);
write_data('!');write_data('R');write_data('O');
write_data('R');write_data('R');write_data('E');
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0;
}
}
else if(fuhao==2)
{
write_com(0x80+0x4f);
write_com(0x04);
if(((fuhao_next==4)&&(c==0))==0)
{
if(a-b>=0)
d=a-b;
else
{
d=b-a;
k=1;
}
if(fuhao_next==1)
{
k=0;
if(a-b+c>=0)
d=a-b+c;
else
{
d=b-a-c;
k=1;
}
}
else if(fuhao_next==2)
{
k=0;
if(a-b-c>=0)
d=a-b-c;
else
{
d=b+c-a;
k=1;
}
}
else if(fuhao_next==3)
{
k=0;
if(a-b*c>=0)
d=a-b*c;
else
{
d=b*c-a;
k=1;
}
}
else if(fuhao_next==4)
{
k=0;
i=0;
if((long)((a-(float)b/c)*1000)>=0)
d=(long)((a-(float)b/c)*1000);
else
{
d=(long)(((float)b/c-a)*1000);
k=1;
}
if((long float)d/1000<1&(long float)d/1000>0)
y=1;
}
if(d==0|y==1)
x=1;
while(d!=0)
{
write_data(0x30+d%10);
d=d/10;
if(fuhao_next==4)
{
i++;
if(i==3)
write_data(0x2e);
}
}
if(x)
write_data(0x30);
if(k)
write_data(0x2d);
write_data(0x3d);
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0;
}
else
{
write_com(0x01);
write_com(0x80+0x4f);
write_com(0x04);
write_data('!');write_data('R');write_data('O');
write_data('R');write_data('R');write_data('E');
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0;
}
}
else if(fuhao==3)
{
write_com(0x80+0x4f);
write_com(0x04);
if(((fuhao_next==4)&&(c==0))==0)
{
d=a*b;
if(fuhao_next==1)
d=a*b+c;
else if(fuhao_next==2)
{
if(a*b-c>=0)
d=a*b-c;
else
{
d=c-a*b;
k=1;
}
}
else if(fuhao_next==3)
d=a*b*c;
else if(fuhao_next==4)
{
i=0;
d=(long)(((float)a*b/c)*1000);
if((long float)d/1000<1&(long float)d/1000>0)
y=1;
}
if(d==0|y==1)
x=1;
while(d!=0)
{
write_data(0x30+d%10);
d=d/10;
if(fuhao_next==4)
{
i++;
if(i==3)
write_data(0x2e);
}
}
if(x)
write_data(0x30);
if(k)
write_data(0x2d);
write_data(0x3d);
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0;
}
else
{
write_com(0x01);
write_com(0x80+0x4f);
write_com(0x04);
write_data('!');write_data('R');write_data('O');
write_data('R');write_data('R');write_data('E');
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0;
}
}
else if(fuhao==4) //当第一个符号为除号时
{
write_com(0x80+0x4f); //移动到LCD1602第二行末尾
write_com(0x04); //倒序书写
if(b!=0&(((fuhao_next==4)&&(c==0))==0)) //当第二个数不为0,且不同时满足第二个符号为除号和第三个数为0时
{
i=0; //小数点保留变量
d=(long)(((float)a/b)*1000); //先将小数点后三位取整
if(fuhao_next==1) //第二个符号为加号
d=(long)(((float)a/b+c)*1000);
else if(fuhao_next==2) //第二个符号为减号
{
if((long)(((float)a/b-c)*1000)>=0) //差为正
d=(long)(((float)a/b-c)*1000);
else //差为负
{
d=(long)((c-(float)a/b)*1000);
k=1; //符号标志位置1
}
}
else if(fuhao_next==3) //第二个符号为乘号
d=(long)(((float)a/b*c)*1000);
else if(fuhao_next==4) //第二个符号为除号
d=(long)(((float)a/b/c)*1000);
if(d==0|(long float)d/1000<1) //如果运算结果为0或者在0和1之间
x=1; //0显示标志位置1
while(d!=0) //运算结果不为0
{
write_data(0x30+d%10); //从小数点最后一位倒序书写
d=d/10; //
i++;
if(i==3) //保留3位
write_data(0x2e); //书写小数点
}
if(x) //输出0
write_data(0x30);
if(k) //输出负号
write_data(0x2d);
write_data(0x3d); //输出"="
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0; //所以变量及标志位清零
}
else //错误提示
{
write_com(0x01);
write_com(0x80+0x4f);
write_com(0x04);
write_data('!');write_data('R');write_data('O');
write_data('R');write_data('R');write_data('E');
a=0;b=0;c=0;flag=0;fuhao=0,fuhao_next=0,k=0,x=0,y=0,m=0,n=0;
}
}
}
break;
case 15:
{
if(j==1)
{
write_com(0x01);
j=0;
}
flag++;
n++;
if(flag==1)
fuhao=1;
if(flag==2)
fuhao_next=1;
write_data(0x30+table1[num]);
}
break;
}
}
}
main()
{
init();
while(1)
{
keyscan();
}
}