#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
uchar code table8[]={0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89}; //最左边显示0-9
uchar code table7[]={0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99}; //左边倒数第二
uchar code table6[]={0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9}; //左边倒数第二
uchar code table5[]={0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9};
uchar code table4[]={0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9};
uchar code table3[]={0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9}; //左边倒数第二
uchar code table2[]={0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9};
uchar code table1[]={0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9};
ulong dat; //数据
ulong datA; //过度数据
uchar addflag; //加法标志位
uchar subflag; //减法标志位
uchar mulflag; //乘法标志位
uchar divflag; //除法标志位
uchar overflow; //溢出标志位
uchar clrflag; //数据处理标志位
uchar illegal; //除法的非法标志位
uchar keynum; //按键键值
uchar keycode; //按键IO口状态值
uchar scanok; //IO口扫描结束
uchar checkok; //键值获取结束
void delay_ms(uint z) //1ms的延时函数
{
uchar x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void scankeyboard() //scankeyboard()函数(用于扫描键值)
{ //反转法测键值。。。
uchar a,b;
P2=0x0f;
keycode=P2;
if(keycode!=0x0f)
{
delay_ms(10); //按键闭合消抖。。
a=keycode;
P2=0xf0;
b=P2;
keycode=a|b;
while(P2!=0xf0);
delay_ms(10);//按键释放消抖。。
P1=keycode;
scanok=1;//键值测完后。。scanok置1。。。
}
}
void checkkeycode(void)
{
if(scanok) //如果键值测完后,则执行以下。。。
{
scanok=0; //scanok清零。。为下次使用准备
switch(keycode) //用开关语句查找键值对应的逻辑功能...
{
case 0xee: keynum=0 ;break; //数字键
case 0xed: keynum=1 ;break;
case 0xdd: keynum=2 ;break;
case 0xbd: keynum=3 ;break;
case 0xeb: keynum=4 ;break;
case 0xdb: keynum=5 ;break;
case 0xbb: keynum=6 ;break;
case 0xe7: keynum=7 ;break;
case 0xd7: keynum=8 ;break;
case 0xb7: keynum=9 ;break;
case 0x77: keynum=10 ;break; // +
case 0x7b: keynum=11 ;break; // -
case 0x7d: keynum=12 ;break; // *
case 0x7e: keynum=13 ;break; // /
case 0xbe: keynum=14 ;break; // =
case 0xde: keynum=15 ;break; //清零
}
checkok=1; //查完后,checkok置1.
}
}
void datpros(void) //数据处理函数。。
{
if(keynum==15) //如果是15 则认为是清零的 进行清零
{
dat=0;
}
else //否则则认为是数字键 进行显示 存贮 并运算
{
if(clrflag) //清除标志为1,则执行以下。
{
dat=0;
clrflag=0; //为下次使用准备。
}
dat=dat*10+(ulong)keynum; //将每次按的数字合成一个整体。。比如按下"1","2","3"后就会把它合成"123"
if(dat>1000000000) overflow=1; //如果输入值大于65535(所用的为int型数据,最大为65535)的话则溢出标志置1,可供显示程序查询并显示"EEEEEEE"
if(divflag&&!dat) illegal=1; //如果做除法时除了零,则非法标志置1,供显示程序查询
}
}
void add(void)
{
addflag++; //加法标志置1。。。
subflag=mulflag=divflag=0; //将其它运算标志清零。。(一次只能作一种运算)
clrflag=1; //清零标标置1,(当按下加号后,再按第二个加数时,这时应该显示第二加数。。所以要清掉第一个加数。)
if(addflag>1) //此处用于边加。。
{ //当连续加的时候。。加号应有等于的功能。。
dat=dat+datA; //算出和
datA=dat; //和保存,用于下一次连加。。
} //说明:比如进行"1+2+3"时,当按第二个加时,应该要显示1+2的和。。
else datA=dat; //如果不是连加,将输入的第一个加数暂存。。(因为显示程序只显示dat变量的值。)
}
void sub(void)
{
subflag++;
addflag=mulflag=divflag=0;
clrflag=1;
if(subflag>1) //连减。。
{
dat=datA-dat;
datA=dat;
}
else datA=dat;
}
void mul(void)
{
mulflag++;
addflag=subflag=divflag=0;
clrflag=1;
if(mulflag>1) //连乘
{
dat=datA*dat;
datA=dat;
}
else datA=dat;
}
void div(void)
{
divflag++;
addflag=subflag=mulflag=0;
clrflag=1;
if(divflag>1)
{
dat=datA/dat;
datA=dat;
}
else datA=dat;
}
void equ(void)
{
if(addflag) //如果些时做加法运算。。
{
dat=dat+datA; //计算各存入dat(显示程序会将dat显示的。。)
}
if(subflag)
{
dat=datA-dat;
}
if(mulflag)
{
dat=datA*dat;
}
if(divflag)
{
dat=datA/dat;
}
addflag=subflag=mulflag=divflag=0; //运算一次完成后将所有运标志清零。为下次运算作准备。。
}
void display(void)
{
uchar ge=0,shi=0,bai=0,qian=0,wan=0,shiwan=0,baiwan=0,qianwan=0;
if(!overflow&&!illegal)
{
ge=dat; //将数据分开然后分别显示
shi=dat0/10;
bai=dat00/100;
qian=dat000/1000;
wan=dat0000/10000;
shiwan=dat00000/100000;
baiwan=dat000000/1000000;
qianwan=dat0000000/10000000;
P0=table1[ge]; //个位显示
delay_ms(2);
P0=table2[shi]; //十位显示
delay_ms(2);
P0=table3[bai]; //百位显示
delay_ms(2);
P0=table4[qian]; //千位位显示
delay_ms(2);
P0=table5[wan]; //wan位显示
delay_ms(2);
P0=table6[shiwan]; //个位显示
delay_ms(2);
P0=table7[baiwan]; //个位显示
delay_ms(2);
P0=table8[qianwan]; //个位显示
delay_ms(2);
P0=0xff;
}
else
{
P0=table1[0];
}
}
void calculate_handle(void)//计算大函数。。
{
if(checkok)//如果检测键值完万。。则执行以下。。
{
checkok=0;//检测完标志清零..
switch (keynum)//如果是+,-,*,/,=则进入相应的函数。。
{
case 10 : add(); break; //如果是按了"+",则进入加法函数。
case 11 : sub(); break; //如果是按了"-",则进入加法函数。
case 12 : mul(); break; //如果是按了"*",则进入加法函数。
case 13 : div(); break; //如果是按了"/",则进入加法函数。
case 14 : equ(); break; //如果是按了"=",则进入加法函数。
default : datpros(); //如果不是,计算符(即为数字),则进入数据处理函数。
}
}
}
void main(void)
{
P0=0xff;
while(1)
{
scankeyboard();
checkkeycode();
calculate_handle();
display();
}
} |