#include
#include
#include
unsigned char n;
float idata a,b; //两个操作数
void key_scan(void);//键盘扫描
void init(); //LCD初始化
void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s);//字符串显示
void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat); //字符显示
void write_com(unsigned char com);
sbit lcden=P2^7; //读写控制输入端
sbit rw=P2^6; //读写控制端
sbit rs=P2^5; //指令与数据选择
sbit busy=P0^7; //LCD忙碌标识
void delay(unsigned int i)//延时程序
{
unsigned int n;
for(n=0;n<=i;n++);
}
void main()
{
char idata temp[16]; //临时存储区
char i=0,j=0,fuhao; //i,j分别为temp与LCD的数据指针
bit flag=0,dh=0,fh=0,xsd=0;
//flag=0:操作数1,flag=1:操作数2;dh=1时表示已输入等号;fh负号;xsd小数点
init();//小数点
LCD_dsp_string(4,0,"Welcome!");
do
{
key_scan();
} while(n==17); //等待按键
write_com(0x01); //清屏
while(1)
{
key_scan(); //等待按键
if((dh==1)&(flag==1)&(n!=17)) //一次计算完毕后执行
{
write_com(0x01);//清屏
LCD_dsp_string(0,0,temp); //输出上次计算的结果
j=0;
i=0;
flag=0;
fh=0;
while(temp[i++]!='\0') j++;
//将temp数据指针移向后一个空位,将LCD显示指针移向下一个空位
}
if((i==0)&(n=='-')&(fh==0)) //如果输入的第一个数是负数则执行
{
fh=1; //表示有负号
temp[0]='-'; //保存负号
i++;
LCD_dsp_char(j++,0,n); //输出减号
if(flag==0) continue;
}
if(((n>='0')&(n<='9')|((n=='c')&(xsd==0)))&(dh==0))
{
if(n=='c')
{
n='.';
xsd=1; //防止再次按下c后继续出现小数点
}
temp[i++]=n;//保存输入的数字
LCD_dsp_char(j++,0,n); //显示并将光标移至下一位(光标未显示)
}
if(((n=='+')|(n=='-')|(n=='*')|(n=='/'))&((flag==0)|(dh==1)))
//输入完第一个操作数之后或者完成一次计算之后按下运算符按键时执行
{
flag=1; //之后输入的操作数是第二个操作数
fuhao=n;
temp[i]='\0';//表示为字符串
a=atof(temp);//转换为数据
i=0;
dh=0;
xsd=0; //之后第二个操作数中可以添加一个小数点
switch(n)
{
case '+': LCD_dsp_char(j++,0,n); break;
case '-': LCD_dsp_char(j++,0,n);
fh=0; break;
case '*': LCD_dsp_char(j++,0,n); break;
case '/': LCD_dsp_char(j++,0,n); break;
} //显示运算符
}
if((n=='=')&(flag==1)) //已输入完第二个操作数并按下等号
{
dh=1;
temp[i]='\0';
b=atof(temp);
i=0;
xsd=0;
LCD_dsp_char(j,0,'='); //显示等号
switch(fuhao)
{
case '+': a=a+b; break;
case '-': a=a-b; break;
case '*': a=a*b; break;
case '/': a=a/b; break;
} //计算
if(a>9999)
{
sprintf(temp,"%s","Error");
//若计算结果超过四位数则输出错误信息
LCD_dsp_string(0,1,temp);
n=17;
do
{
key_scan();
}while(n==17); //等待按键
write_com(0x01); //清屏
a=b=0;
fuhao=0;
flag=0;
i=0;
j=0;
dh=0;
xsd=0;
fh=0; //恢复初始化
}
else
{
sprintf(temp,"%g",a); //输出计算结果
LCD_dsp_string(0,1,temp);
}
}
if(n=='c')//按下清除键
{
write_com(0x01); //清屏
a=b=0;
fuhao=0;
flag=0;
i=0;
j=0;
dh=0;
xsd=0;
fh=0; //恢复初始化
}
}
}
void key_scan(void)
{
unsigned char temp;
P1=0xfe;
if(P1!=0xfe)
{
delay(200);
if(P1!=0xfe)
{
temp=P1&0xf0;
switch(temp)
{
case 0xe0:n='c';break;
case 0xd0:n='0';break;
case 0xb0:n='=';break;
case 0x70:n='+';break;
}
}
while(P1!=0xfe);
}
else
{
P1=0xfd;
if(P1!=0xfd)
{
delay(200);
if(P1!=0xfd)
{
temp=P1&0xf0;
switch(temp)
{
case 0xe0:n='1';break;
case 0xd0:n='2';break;
case 0xb0:n='3';break;
case 0x70:n='-';break;
}
}
while(P1!=0xfd);
}
else{
P1=0xfb;
if(P1!=0xfb)
{
delay(200);
if(P1!=0xfb)
{
temp=P1&0xf0;
switch(temp)
{
case 0xe0:n='4';break;
case 0xd0:n='5';break;
case 0xb0:n='6';break;
case 0x70:n='*';break;
}
}
while(P1!=0xfb);
}
else{
P1=0xf7;
if(P1!=0xf7)
{
delay(200);
if(P1!=0xf7)
{
temp=P1&0xf0;
switch(temp)
{
case 0xe0:n='7';break;
case 0xd0:n='8';break;
case 0xb0:n='9';break;
case 0x70:n='/';break;
}
}
while(P1!=0xf7);
}
else n=17;
}}}
}
void check() //判断LCD是否忙碌
{
do
{
P0=0xff;
rs=0;
rw=1;
lcden=0;
delay(100);
lcden=1;
}while(busy==1); //当busy=1,即LCD忙时,等待
}
void write_com(unsigned char com) //写显示命令
{
P0=com;
rs=0;
rw=0;
lcden=0;
check();
lcden=1;
}
void write_data(unsigned char date) //写显示数据
{
P0=date;
rs=1;
rw=0;
lcden=0;
check();
lcden=1;
}
void init() //初始化LCD
{
write_com(0x38); //16x2行显示,5x7点阵,8位数据接口
write_com(0x0c); //开显示,光标不显示、不闪烁
write_com(0x06); //光标自增,画面不动
write_com(0x80); //选择第一行
write_com(0x01); //清屏
}
void LCD_set_xy( unsigned char x, unsigned char y )//设置LCD显示的位置
{
unsigned char address;
if (y == 0) //y=0为第一行
address = 0x80 + x; //x=0为一行的第一个
else //第二行
address =0xc0+ x;
write_com(address);//设置数据指针位置
}
void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat)
//单个字符显示函数
{
LCD_set_xy( x, y ); //设置显示位置
write_data(dat); //写入待显示数据
}
void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s)
//字符串显示函数
{
LCD_set_xy( X, Y );
while (*s) //当字符串未到达结尾('\0')时,循环输出单个字符
{
write_data(*s);
s ++;//指向下一个字符
}
}