#include "reg52.h"
#include "stdio.h"
sbit RS=P2^4;
sbit RW=P2^5;
sbit EN=P2^6;
unsigned char code mima[10]="0123456789";
unsigned char sign[7],count=0,Error_flag;//sign是用来标记运算符的,count是用来进行下标计算的
float a[8];//用来记录数据的
unsigned char h,jia,k;//jia,和k是用来记录数据的个数和符号的个数的
void delay(unsigned char m)//延时约1ms
{
while(--m);
}
void delays(unsigned char t)//延时约1s
{
while(t--)
{
delay(245);
delay(245);
}
}
void write_com(unsigned char com)//LCD的写命令
{
RS=0;
RW=0;
EN=1;
P0=com;
delays(5);
EN=0;
}
void write_dat(unsigned char date)//LCD的写一个数据
{
RS=1;
RW=0;
EN=1;
P0=date;
delays(5);
EN=0;
}
void write_string(unsigned char hangshu,unsigned char weizhi,unsigned char *s)//LCD的写字符串的
{
if(hangshu==1)
{
write_com(0x80+weizhi);
while(*s!='\0')
{
write_dat(*s);
s++;
}
}
if(hangshu==2)
{
write_com(0xc0+weizhi);
while(*s!='\0')
{
write_dat(*s);
s++;
}
}
}
unsigned char keyscanf()//键盘扫描(反转法)
{
unsigned char hang,lie;
P3=0x0f;
hang=P3&0x0f;
if(hang!=0x0f)
{
delays(10);
if((P3&0x0f)!=0x0f)
{
hang=P3&0x0f;
P3=hang|0xf0;
lie=P3&0xf0;
while((P3&0xf0)!=0xf0);
return (hang+lie);//必须是行+列,因为行是高四位,列是低四位,所以才是行+列
}
}
return 0xff;
}
void LCD1602inti()//LCD的初始化
{
write_com(0x38);
delays(5);
write_com(0x38);
delays(5);
write_com(0x38);
delays(5);
write_com(0x38);
write_com(0x06);
write_com(0x01);
write_com(0x08);
delays(5);
write_com(0x0c);
}
unsigned char key()//键盘处理
{
switch(keyscanf())
{
case 0x7e:return 1;break;
case 0x7d:return 2;break;
case 0x7b:return 3;break;
case 0x77:return '+';break;
case 0xbe:return 4;break;
case 0xbd:return 5;break;
case 0xbb:return 6;break;
case 0xb7:return '-';break;
case 0xde:return 7;break;
case 0xdd:return 8;break;
case 0xdb:return 9;break;
case 0xd7:return 'x';break;
case 0xee:return 0;break;
case 0xed:return '.';break;
case 0xeb:return '=';break;
case 0xe7:return '/';break;
default :return 0xff;break;
}
}
void chengfa()//乘法
{
a[count+1]=a[count+1]*a[count+2];
if(count+1>=k-1)
sign[count+1]=0;
else
{
for(h=count+1;h
sign[h]=sign[h+1];
}
for(h=count+2;h a[h]=a[h+1];
jia--;
k--;
}
void chufa()//除法
{
if(a[count+2]==0)
{
Error_flag=1;
}
else
a[count+1]=a[count+1]/a[count+2];
if(count+1>=k-1)
sign[count+1]=0;
else
{
for(h=count+1;h sign[h]=sign[h+1];
for(h=k-1;h<10;h++)
sign[h]=0;
}
for(h=count+2;h a[h]=a[h+1];
k--;
jia--;
}
void main()
{ //readflag是用来判断是否进行等号的读取
unsigned char num,i=0,t[6],flag,shu[8],readflag;//num用来接收键盘的值,i用来记录输入的字符,t用来记录字符,flag是记录输入的运算符的个数,shu是用来作为输出的结果
LCD1602inti();
while(1)
{
num=key();
if(num!=0xff)
{
if(readflag==1)
{
readflag=0;
flag=0;
write_com(0x01);
}//清零
if(num=='+'||num=='-'||num=='x'||num=='/'||num=='=')
{
write_dat(num);
if(i>0)//防止没有数的情况发生
sscanf(t,"%f",&a[jia++]);//将t的数值转化成float类型
else
Error_flag=1;//连着两次出现运算符,中间没有数字的情况,报错
if(num!='=')
sign[k++]=num;//记下此时的符号
for(h=0;h t[h]=0;//清除缓存
flag++;//flag加一
i=0;//数据从零开始计数
if(flag>=1)
{
if(num=='='&&flag==1)//上来就是等号的情况
{
write_string(2,0,t);
k=0;
flag=0;
jia=0;//上来就是等号的情况
readflag=1;i=0;for(h=0;h<10;h++)sign[h]=0;flag=0;
}
else if(num=='='&&flag>1)
{
while(count<=k-1)
{
switch(sign[count])//这是从前往后找
{
case '+':
if(sign[count+1]!='x'&&sign[count+1]!='/')
{
a[count+1]+=a[count];
}
else if(sign[count+1]=='x')
{
while(sign[count+1]=='x')
chengfa();
a[count+1]+=a[count];
}
else if(sign[count+1]=='/')
{
while(sign[count+1]=='/')
chufa();
a[count+1]+=a[count];
}
break;
case '-':
if(sign[count+1]!='x'&&sign[count+1]!='/')
a[count+1]=a[count]-a[count+1];
else if(sign[count+1]=='x')
{
while(sign[count+1]=='x')
{
chengfa();
}
a[count+1]=a[count]-a[count+1];
}
else if(sign[count+1]=='/')
{
while(sign[count+1]=='/')
chufa();
a[count+1]=a[count]-a[count+1];
}
break;
case 'x':
a[count+1]=a[count]*a[count+1];
break;
case '/':
if(a[count+1]==0)//分母为0的情况
{
Error_flag=1;
}
else
a[count+1]=a[count]/a[count+1];
break;
}
if(Error_flag==1)
break;
count++;
}
if(Error_flag==0)
{
sprintf(shu,"%g",a[count]);write_string(2,0,shu);readflag=1;i=0;for(h=0;h<10;h++)sign[h]=0;flag=0;k=0;for(h=0;h<8;h++)a[h]=0;count=0;
}
else
{
write_string(2,0,"Error!");readflag=1;i=0;for(h=0;h<10;h++)sign[h]=0;flag=0;k=0;for(h=0;h<8;h++)a[h]=0;count=0;Error_flag=0;
}
}
}
}//加减乘除判断
else
{
if(num=='.')
{
t[i]='.';
write_dat(t[i]);//判读小数点
}
else
{
t[i]=mima[num];
write_dat(mima[num]);//写入数字
}
i++;
}
}
}
}
关于这个计算器,作为小白的我,辛辛苦苦的写了一星期,遇到的困难是在于数组的空间大小没开辟出来,所以在这我建议大家把keil破解完全。
如果有什么不会的可以私聊我。或加qq1034113547