#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x00,0x90,0xbf,0xff};//段选
uchar code wei[]={
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//段选
uchar bb[8],i,j;
uchar code aa[]={
0xfe,0xfd,0xfb,0xf7};//p3口的送值 ,用于矩阵键盘扫描
long int a,b; // 两个二进制数寄存器
uchar enblescan,flag,sign;
long int count(uchar sign,long int a,long int b);//运算函数
long int sum(uchar bb[]); //bb[]数组的求和函数
void showone(long int count); //任意数的显示函数
uchar keyscan();//矩阵键盘扫描函数
uchar keyval(uchar temp);//返回键盘的键值函数
void show(uchar); // 计算器的显示函数
void init();//初始化函数
void main()
{
init();//初始化
show(keyval(keyscan()));//显示的初始化
while(1) //主函数的大循环
{
if(enblescan==1)//有键按下,进行扫描
{
show(keyval(keyscan()));//由扫描得到的键得到键值,再将键值显示
enblescan=2;//扫描屏蔽
}
}
}
/***************************************************
初始化程序用于对全局变量的初始化和中断寄存器的初始化
****************************************************/
void init() //初始化函数
{
enblescan=0;//允许检测是否有键按下
sign=0;
flag=0;
i=0;
j=0;
TMOD=0x01;//设置中断模式字
TH0=(65536-1000)/256;//设置定时中断时间
TL0=(65536-1000)%256;
EA=1;//开总中断
ET0=1;//开t0中断
TR0=1;//定时中断开始
}
/************************************************
中断程序用于数码管的动态显示和键盘按下与否的检测;
全局变量enblescan用于对键盘扫描函数的控制
************************************************/
display() interrupt 1
{
uchar temp;
TH0=(65536-1000)/256;//中断初值重装
TL0=(65536-1000)%256;
if(i==8)
i=0;
P2=wei[i]; //动态扫描显示设位选
P1=table[bb[i]];//动态扫描显示设段选
i++;
if(enblescan==0) //如果允许检测有键按下
{
P3=0XF0;
temp=P3;
if(temp!=0xf0) //如果有键按下
j++;
else j=0;
if(j==10)
{
j=0;
enblescan=1;//将enblescan设成扫描允许
}
}
if(enblescan==2) //如果键盘已经扫描完,检测键是否弹起
{
P3=0XF0;
temp=P3;
if(temp==0xf0) //如果键已经弹起
j++;
else j=0;
if(j==100)
{
j=0;
enblescan=0;//将enblescan设位扫键允许
}
}
}
/*************************************
键盘扫描函数用于在enblescan==1的条件下
对键的位置进行确认。
**************************************/
uchar keyscan()//矩阵键盘扫描函数
{
uchar temp,temp1,k;
for(k=0;k<4;k++)
{
P3=aa[k];
temp1=P3;
temp1=temp1&0xf0;
if(temp1!=0xf0)
{
enblescan=1;
temp=P3;
}
}
return temp;
}
/*******************************************
键值函数用于将键盘扫描函数得到键的位置转化我
们想要的键盘值。其中全局变量flag,sign分别用
于显示模式和运算法则的选择。
*******************************************/
uchar keyval(uchar temp)//返回键盘的键值函数
{
uchar num;
switch(temp)
{
case 0xee:num=7;
flag++;
break;
case 0xde:num=8;
flag++;
break;
case 0xbe:num=9;
flag++;
break;
case 0x7e:sign=4; //除法
flag=0;
break;
case 0xed:num=4;
flag++;
break;
case 0xdd:num=5;
flag++;
break;
case 0xbd:num=6;
flag++;
break;
case 0x7d:sign=3; //乘法
flag=0;
break;
case 0xeb:num=1;
flag++;
break;
case 0xdb:num=2;
flag++;
break;
case 0xbb:num=3;
flag++;
break;
case 0x7b:sign=2;//减法
flag=0;
break;
case 0xe7: //清零
flag=0;
a=0;
b=0;
break;
case 0xd7:num=0;
flag++;
break;
case 0xb7:flag=9;//等号
break;
case 0x77:sign=1; //加法
flag=0;
break;
default:break;
}
return num;
}
/*************************************************
显示函数用于对键入值进行实时显示和对特权键进行处理。
其中,
**************************************************/
void show(uchar temp)
{ uchar k;
switch(flag)
{
case 0: if(sign!=0)//如果是在按了功能键后
a=sum(bb);//算出bb[]中的值
bb[7]=0;//只显示一个零
for(k=0;k<7;k++)
bb[k]=11;
break;
case 1:bb[7]=keyval(temp); //按了一个数字键
break;
case 2:bb[6]=bb[7]; //按了两个数字键
bb[7]=keyval(temp);
break;
case 3:bb[5]=bb[6]; //按了三个数字键
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 4:bb[4]=bb[5]; //....
bb[5]=bb[6];
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 5:bb[3]=bb[4]; //.....
bb[4]=bb[5];
bb[5]=bb[6];
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 6:bb[2]=bb[3]; //....
bb[3]=bb[4];
bb[4]=bb[5];
bb[5]=bb[6];
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 7:bb[1]=bb[2]; //按了七个数字键
bb[2]=bb[3];
bb[3]=bb[4];
bb[4]=bb[5];
bb[5]=bb[6];
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 8: if(flag!=0)//如果按的还是数字键
flag=7;
break;
case 9:b=sum(bb);//算出bb[]中的值
showone(count(sign,a,b));//显示最后结果
break;
default:break;
}
}
/***************************************
求和函数用于当按下特殊键时对数组bb[]求和
****************************************/
long int sum(uchar bb[])
{
long int b;
uchar k=1;
while(bb[k]==11) //对前面的空格键清零
{
bb[k]=0;
k++;
}
b=bb[7]+bb[6]*10+bb[5]*100+bb[4]*1000+
bb[3]*10000+bb[2]*100000+bb[1]*1000000;
return b;
}
/*************************************************
求值函数用于当按下等号键时对a,b寄存区的数求和
**************************************************/
long int count(uchar sign,long int a,long int b)
{
switch(sign)
{
case 1:a=a+b;
break;
case 2:a=a-b;
break;
case 3:a=a*b;
break;
case 4:a=a/b;
break;
default:break;
}
return a;
}
/*************************************************
任意数的显示函数用于对任意一个数转化成bcd码
**************************************************/
void showone(long int count)
{
uchar k=1;
bb[1]=count/1000000; //转化成bcd码
bb[2]=count%1000000/100000;
bb[3]=count%100000/10000;
bb[4]=count%10000/1000;
bb[5]=count%1000/100;
bb[6]=count%100/10;
bb[7]=count%10;
while(bb[k]==0) //把数前面的零转换成空格
{
bb[k]=11;
k++;
}
}
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x00,0x90,0xbf,0xff};//段选
uchar code wei[]={
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//段选
uchar bb[8],i,j;
uchar code aa[]={
0xfe,0xfd,0xfb,0xf7};//p3口的送值 ,用于矩阵键盘扫描
long int a,b; // 两个二进制数寄存器
uchar enblescan,flag,sign;
long int count(uchar sign,long int a,long int b);//运算函数
long int sum(uchar bb[]); //bb[]数组的求和函数
void showone(long int count); //任意数的显示函数
uchar keyscan();//矩阵键盘扫描函数
uchar keyval(uchar temp);//返回键盘的键值函数
void show(uchar); // 计算器的显示函数
void init();//初始化函数
void main()
{
init();//初始化
show(keyval(keyscan()));//显示的初始化
while(1) //主函数的大循环
{
if(enblescan==1)//有键按下,进行扫描
{
show(keyval(keyscan()));//由扫描得到的键得到键值,再将键值显示
enblescan=2;//扫描屏蔽
}
}
}
/***************************************************
初始化程序用于对全局变量的初始化和中断寄存器的初始化
****************************************************/
void init() //初始化函数
{
enblescan=0;//允许检测是否有键按下
sign=0;
flag=0;
i=0;
j=0;
TMOD=0x01;//设置中断模式字
TH0=(65536-1000)/256;//设置定时中断时间
TL0=(65536-1000)%256;
EA=1;//开总中断
ET0=1;//开t0中断
TR0=1;//定时中断开始
}
/************************************************
中断程序用于数码管的动态显示和键盘按下与否的检测;
全局变量enblescan用于对键盘扫描函数的控制
************************************************/
display() interrupt 1
{
uchar temp;
TH0=(65536-1000)/256;//中断初值重装
TL0=(65536-1000)%256;
if(i==8)
i=0;
P2=wei[i]; //动态扫描显示设位选
P1=table[bb[i]];//动态扫描显示设段选
i++;
if(enblescan==0) //如果允许检测有键按下
{
P3=0XF0;
temp=P3;
if(temp!=0xf0) //如果有键按下
j++;
else j=0;
if(j==10)
{
j=0;
enblescan=1;//将enblescan设成扫描允许
}
}
if(enblescan==2) //如果键盘已经扫描完,检测键是否弹起
{
P3=0XF0;
temp=P3;
if(temp==0xf0) //如果键已经弹起
j++;
else j=0;
if(j==100)
{
j=0;
enblescan=0;//将enblescan设位扫键允许
}
}
}
/*************************************
键盘扫描函数用于在enblescan==1的条件下
对键的位置进行确认。
**************************************/
uchar keyscan()//矩阵键盘扫描函数
{
uchar temp,temp1,k;
for(k=0;k<4;k++)
{
P3=aa[k];
temp1=P3;
temp1=temp1&0xf0;
if(temp1!=0xf0)
{
enblescan=1;
temp=P3;
}
}
return temp;
}
/*******************************************
键值函数用于将键盘扫描函数得到键的位置转化我
们想要的键盘值。其中全局变量flag,sign分别用
于显示模式和运算法则的选择。
*******************************************/
uchar keyval(uchar temp)//返回键盘的键值函数
{
uchar num;
switch(temp)
{
case 0xee:num=7;
flag++;
break;
case 0xde:num=8;
flag++;
break;
case 0xbe:num=9;
flag++;
break;
case 0x7e:sign=4; //除法
flag=0;
break;
case 0xed:num=4;
flag++;
break;
case 0xdd:num=5;
flag++;
break;
case 0xbd:num=6;
flag++;
break;
case 0x7d:sign=3; //乘法
flag=0;
break;
case 0xeb:num=1;
flag++;
break;
case 0xdb:num=2;
flag++;
break;
case 0xbb:num=3;
flag++;
break;
case 0x7b:sign=2;//减法
flag=0;
break;
case 0xe7: //清零
flag=0;
a=0;
b=0;
break;
case 0xd7:num=0;
flag++;
break;
case 0xb7:flag=9;//等号
break;
case 0x77:sign=1; //加法
flag=0;
break;
default:break;
}
return num;
}
/*************************************************
显示函数用于对键入值进行实时显示和对特权键进行处理。
其中,
**************************************************/
void show(uchar temp)
{ uchar k;
switch(flag)
{
case 0: if(sign!=0)//如果是在按了功能键后
a=sum(bb);//算出bb[]中的值
bb[7]=0;//只显示一个零
for(k=0;k<7;k++)
bb[k]=11;
break;
case 1:bb[7]=keyval(temp); //按了一个数字键
break;
case 2:bb[6]=bb[7]; //按了两个数字键
bb[7]=keyval(temp);
break;
case 3:bb[5]=bb[6]; //按了三个数字键
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 4:bb[4]=bb[5]; //....
bb[5]=bb[6];
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 5:bb[3]=bb[4]; //.....
bb[4]=bb[5];
bb[5]=bb[6];
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 6:bb[2]=bb[3]; //....
bb[3]=bb[4];
bb[4]=bb[5];
bb[5]=bb[6];
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 7:bb[1]=bb[2]; //按了七个数字键
bb[2]=bb[3];
bb[3]=bb[4];
bb[4]=bb[5];
bb[5]=bb[6];
bb[6]=bb[7];
bb[7]=keyval(temp);
break;
case 8: if(flag!=0)//如果按的还是数字键
flag=7;
break;
case 9:b=sum(bb);//算出bb[]中的值
showone(count(sign,a,b));//显示最后结果
break;
default:break;
}
}
/***************************************
求和函数用于当按下特殊键时对数组bb[]求和
****************************************/
long int sum(uchar bb[])
{
long int b;
uchar k=1;
while(bb[k]==11) //对前面的空格键清零
{
bb[k]=0;
k++;
}
b=bb[7]+bb[6]*10+bb[5]*100+bb[4]*1000+
bb[3]*10000+bb[2]*100000+bb[1]*1000000;
return b;
}
/*************************************************
求值函数用于当按下等号键时对a,b寄存区的数求和
**************************************************/
long int count(uchar sign,long int a,long int b)
{
switch(sign)
{
case 1:a=a+b;
break;
case 2:a=a-b;
break;
case 3:a=a*b;
break;
case 4:a=a/b;
break;
default:break;
}
return a;
}
/*************************************************
任意数的显示函数用于对任意一个数转化成bcd码
**************************************************/
void showone(long int count)
{
uchar k=1;
bb[1]=count/1000000; //转化成bcd码
bb[2]=count%1000000/100000;
bb[3]=count%100000/10000;
bb[4]=count%10000/1000;
bb[5]=count%1000/100;
bb[6]=count%100/10;
bb[7]=count%10;
while(bb[k]==0) //把数前面的零转换成空格
{
bb[k]=11;
k++;
}
}