c51单片机简单计算器
前言
利用51单片机和八位数码管以及矩阵键盘制作一个简单的计算器。
本文代码在下文博主给出的代码基础上进行了修改,关于硬件的介绍可以参考该博主的文章。
版权声明:本文为CSDN博主「开天辟地之大菠萝三」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_47060099/article/details/106664393
代码
#include"reg51.h"
typedef unsigned char u8; //对数据类型进行声明定义
typedef unsigned int u16;
sbit LSA=P2^2; //74HC138译码器数码管位选
sbit LSB=P2^3;
sbit LSC=P2^4;
#define GPIO_KEY P1
#define GPIO_DIG P0
u16 KeyValue; //用来存放读取到的键值
u16 keyflag,i; //用来判断按下的数字还是运算符或清空键
u8 code smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00}; //显示0~F、负号‘-’、不显示
u16 wei[8]={0,17,17,17,17,17,17,17}; //用来存放每一位数码管数字的数组
void delay(u16 i)//延时函数
{
while(i--);
}
void display() //扫描显示动态数码管
{
LSA=0; LSB=0; LSC=0; GPIO_DIG=smgduan[wei[0]];delay(50); GPIO_DIG=0x00; //消隐
LSA=1; LSB=0; LSC=0; GPIO_DIG=smgduan[wei[1]];delay(50); GPIO_DIG=0x00;
LSA=0; LSB=1; LSC=0; GPIO_DIG=smgduan[wei[2]];delay(50); GPIO_DIG=0x00;
LSA=1; LSB=1; LSC=0; GPIO_DIG=smgduan[wei[3]];delay(50); GPIO_DIG=0x00;
LSA=0; LSB=0; LSC=1; GPIO_DIG=smgduan[wei[4]];delay(50); GPIO_DIG=0x00;
LSA=1; LSB=0; LSC=1; GPIO_DIG=smgduan[wei[5]];delay(50); GPIO_DIG=0x00;
LSA=0; LSB=1; LSC=1; GPIO_DIG=smgduan[wei[6]];delay(50); GPIO_DIG=0x00;
LSA=1; LSB=1; LSC=1; GPIO_DIG=smgduan[wei[7]];delay(50); GPIO_DIG=0x00;
}
void KeyDown(void)//检测有按键按下并读取键值
{
u16 a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)//读取按键是否按下
{
delay(1000);//延时10ms进行消抖
if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
{
//测试列
GPIO_KEY=0x0f;
switch(GPIO_KEY)//行列扫描法
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}
//测试行
GPIO_KEY=0xf0;
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
if(KeyValue==0 || KeyValue==1 || KeyValue==2 || KeyValue==3 || KeyValue==4 || KeyValue==5 || KeyValue==6 || KeyValue==7 || KeyValue==8 || KeyValue==9)
{
keyflag=1;
}
while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测
{
delay(1000);
a++;
}
}
}
}
void main()
{
u16 a=0,b=0,c=0,k=0,t=0;
while(1)
{
display(); /* 第一个数字输入*/
KeyDown();
if(keyflag==1)
{
for(i=7;i>0;i--) //输入一位,数字向左移动一位
{wei[i]=wei[i-1];}
for(i=7;i>0;i--)
if(wei[i]==17&&wei[i-1]==0)k=i-1;
wei[k]=17;
k=100;
wei[0]=KeyValue;
keyflag=0;
}
else if(KeyValue==14)
{
wei[0]=0;
for(i=1;i<8;i++)
wei[i]=17; //对数码管清零
display();
}
else if(KeyValue==10)//加法运算
{ for(i=7;i>0;i--)
if(wei[i]==17)wei[i]=0;
a=wei[0]+wei[1]*10+wei[2]*100+wei[3]*1000+wei[4]*10000+wei[5]*100000+wei[6]*1000000+wei[7]*10000000; //计算a的值
wei[0]=0;
for(i=1;i<8;i++)
wei[i]=17;
while(1) //输入第二个数
{
display();
KeyDown();
if(KeyValue==15) break;//当读到等于号,既,KeyValue=15时,停止输入
if(keyflag==1)
{
for(i=7;i>0;i--) //输入一位,数字向左移动一位
{wei[i]=wei[i-1];}
for(i=7;i>0;i--)
if(wei[i]==17&&wei[i-1]==0)k=i-1;
wei[k]=17;
k=100;
wei[0]=KeyValue;
keyflag=0;
}
}
for(i=7;i>0;i--)
if(wei[i]==17)wei[i]=0;
b=wei[0]+wei[1]*10+wei[2]*100+wei[3]*1000+wei[4]*10000+wei[5]*100000+wei[6]*1000000+wei[7]*10000000; //计算b的值
c=a+b;
wei[0]=c%10; //计算C的各个位的数字
wei[1]=c/10%10;
wei[2]=c/100%10;
wei[3]=c/1000%10;
wei[4]=c/10000%10;
wei[5]=c/100000%10;
wei[6]=c/1000000%10;
wei[7]=c/10000000%10;
if(wei[7]==0&&wei[6]==0&&wei[5]==0&&wei[4]==0&&wei[3]==0&&wei[2]==0&&wei[1]==0&&wei[0]==0)
for(i=7;i>0;i--)wei[i]=17;
for(i=7;i>0;i--)
if(wei[i]==0&&wei[i-1]!=0)
{k=i;break;}
for(i=k;i<8;i++)wei[i]=17;
display();
}
else if(KeyValue==11)//减法运算
{ for(i=7;i>0;i--)
if(wei[i]==17)wei[i]=0;
a=wei[0]+wei[1]*10+wei[2]*100+wei[3]*1000+wei[4]*10000+wei[5]*100000+wei[6]*1000000+wei[7]*10000000;
wei[0]=0;
for(i=1;i<8;i++)
wei[i]=17;
while(1)
{ //输入第二个数
display();
KeyDown();
if(KeyValue==15) break;
if(keyflag==1)
{
for(i=7;i>0;i--) //输入一位,数字向左移动一位
{wei[i]=wei[i-1];}
for(i=7;i>0;i--)
if(wei[i]==17&&wei[i-1]==0)k=i-1;
wei[k]=17;
k=100;
wei[0]=KeyValue;
keyflag=0;
}
}
for(i=7;i>0;i--)
if(wei[i]==17)wei[i]=0;
b=wei[0]+wei[1]*10+wei[2]*100+wei[3]*1000+wei[4]*10000+wei[5]*100000+wei[6]*1000000+wei[7]*10000000; //计算b的值
if(a>=b)
{
c=a-b;
wei[0]=c%10; //计算C的各个位的数字
wei[1]=c/10%10;
wei[2]=c/100%10;
wei[3]=c/1000%10;
wei[4]=c/10000%10;
wei[5]=c/100000%10;
wei[6]=c/1000000%10;
wei[7]=c/10000000%10;
}
if(a<b)
{
c=b-a;
wei[0]=c%10; //计算C的各个位的数字
wei[1]=c/10%10;
wei[2]=c/100%10;
wei[3]=c/1000%10;
wei[4]=c/10000%10;
wei[5]=c/100000%10;
wei[6]=c/1000000%10;
wei[7]=c/10000000%10;
for(i=7;i>0;i--) //标记负号位置
if(wei[i]==0&&wei[i-1]!=0)
{t=i;break;}
wei[t]=16;
}
if(wei[7]==0&&wei[6]==0&&wei[5]==0&&wei[4]==0&&wei[3]==0&&wei[2]==0&&wei[1]==0&&wei[0]==0)
for(i=7;i>0;i--)wei[i]=17;
for(i=7;i>0;i--)
if(wei[i]==0&&wei[i-1]!=0)
{k=i;break;}
for(i=k;i<8;i++)wei[i]=17;
display();
}
else if(KeyValue==12)//乘法运算
{ for(i=7;i>0;i--)
if(wei[i]==17)wei[i]=0;
a=wei[0]+wei[1]*10+wei[2]*100+wei[3]*1000+wei[4]*10000+wei[5]*100000+wei[6]*1000000+wei[7]*10000000;
wei[0]=0;
for(i=1;i<8;i++)
wei[i]=17;
while(1)
{ //输入第二个数
display();
KeyDown();
if(KeyValue==15) break;
if(keyflag==1)
{
for(i=7;i>0;i--) //输入一位,数字向左移动一位
{wei[i]=wei[i-1];}
for(i=7;i>0;i--)
if(wei[i]==17&&wei[i-1]==0)k=i-1;
wei[k]=17;
k=100;
wei[0]=KeyValue;
keyflag=0;
}
}
for(i=7;i>0;i--)
if(wei[i]==17)wei[i]=0;
b=wei[0]+wei[1]*10+wei[2]*100+wei[3]*1000+wei[4]*10000+wei[5]*100000+wei[6]*1000000+wei[7]*10000000; //计算b的值
c=a*b;
wei[0]=c%10; //计算C的各个位的数字
wei[1]=c/10%10;
wei[2]=c/100%10;
wei[3]=c/1000%10;
wei[4]=c/10000%10;
wei[5]=c/100000%10;
wei[6]=c/1000000%10;
wei[7]=c/10000000%10;
if(wei[7]==0&&wei[6]==0&&wei[5]==0&&wei[4]==0&&wei[3]==0&&wei[2]==0&&wei[1]==0&&wei[0]==0)
for(i=7;i>0;i--)wei[i]=17;
for(i=7;i>0;i--)
if(wei[i]==0&&wei[i-1]!=0)
{k=i;break;}
for(i=k;i<8;i++)wei[i]=17;
display();
}
else if(KeyValue==13)//除法运算
{ for(i=7;i>0;i--)
if(wei[i]==17)wei[i]=0;
a=wei[0]+wei[1]*10+wei[2]*100+wei[3]*1000+wei[4]*10000+wei[5]*100000+wei[6]*1000000+wei[7]*10000000;
wei[0]=0;
for(i=1;i<8;i++)
wei[i]=17;
while(1) //输入第二个数
{
display();
KeyDown();
if(KeyValue==15) break;
if(keyflag==1)
{
for(i=7;i>0;i--) //输入一位,数字向左移动一位
{wei[i]=wei[i-1];}
for(i=7;i>0;i--)
if(wei[i]==17&&wei[i-1]==0)k=i-1;
wei[k]=17;
k=100;
wei[0]=KeyValue;
keyflag=0;
}
}
for(i=7;i>0;i--)
if(wei[i]==17)wei[i]=0;
b=wei[0]+wei[1]*10+wei[2]*100+wei[3]*1000+wei[4]*10000+wei[5]*100000+wei[6]*1000000+wei[7]*10000000; //计算b的值
c=a/b;
wei[0]=c%10; //计算C的各个位的数字
wei[1]=c/10%10;
wei[2]=c/100%10;
wei[3]=c/1000%10;
wei[4]=c/10000%10;
wei[5]=c/100000%10;
wei[6]=c/1000000%10;
wei[7]=c/10000000%10;
if(wei[7]==0&&wei[6]==0&&wei[5]==0&&wei[4]==0&&wei[3]==0&&wei[2]==0&&wei[1]==0&&wei[0]==0)
for(i=7;i>0;i--)wei[i]=17;
for(i=7;i>0;i--)
if(wei[i]==0&&wei[i-1]!=0)
{k=i;break;}
for(i=k;i<8;i++)wei[i]=17;
display(); //显示最终结果
}
}
}
可以进行简单的加减乘除运算。
缺点
不支持负数运算,未考虑小数点。