简介:
使用的单片机型号为"STC89C52",使用的模块为独立键盘和矩阵键盘,LED,蜂鸣器,数码管这些较基础的模块。
具体功能:
可以实现两个数字的加减乘除运算(两个数字为整数,位数可调,区分正负),结果保留整数,区分正负。在输入错误时有删除键,可以一位一位的删除(比如输入34,按下删除键后就变为3)。数码管显示时,需要用到的点亮,不需要用到的没有被点亮(个人认为这样比较舒服~)。
计算器的按键分布:
7 8 9 +
4 5 6 -
1 2 3 *
D 0 = ÷
F T W R
(D为删除键,F为关机键,T为开机键,W为存储键,R为读取键)
另外自己加的小功能:
在得到结果后,还设置有结果的保存键和读取键,按下后可以储存结果和读取结果。另外设置有不掉电的伪开机和伪关机键,按下后可以实现显示的关闭和打开。每按下一次键盘后LED灯都会循环点亮,并且蜂鸣器会发出短暂的声音。
完整的代码如下:
#include <reg52.h>
#include <intrins.h>
typedef unsigned int uint;
typedef unsigned char uchar;
sbit DU=P2^6;
sbit WE=P2^7;
sbit Beep=P2^3;
uchar code SMGduan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//数码管0-9
uchar code LED[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//数码管位选
int num;
int n1=0,n2=0;//数据传递的中间变量
uchar flag;//运算符号标志位
uchar F,T;//输入负数的标志位
uchar i=0;//LED灯移位标志位
uchar j=0;//计算器开关标志位
uchar A=0;//储存结果数组变量
uchar C=0;//读取结果数组变量
int tabel5[20]={0};//计算器计算结果储存数组
//数码管动态显示
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=114;y>0;y--);
}
void display(int i)
{
if(i>=0)
{
if(i<10)
{
P0=0XFF;
WE=1;
P0=0XFE;
WE=0;
DU=1;
P0=SMGduan[i];
DU=0;
delay(8);
}
if(i>=10&&i<99)
{
P0=0XFF;
WE=1;
P0=0XFE;
WE=0;
DU=1;
P0=SMGduan[i/10];
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XFd;
WE=0;
DU=1;
P0=SMGduan[i%10];
DU=0;
delay(8);
}
if(i>=100&&i<999)
{
P0=0XFF;
WE=1;
P0=0XFE;
WE=0;
DU=1;
P0=SMGduan[i/100];
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XFd;
WE=0;
DU=1;
P0=SMGduan[i%100/10];
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XFb;
WE=0;
DU=1;
P0=SMGduan[i%10];
DU=0;
delay(8);
}
}
else
{
i=-i;
if(i<9)
{
P0=0XFF;
WE=1;
P0=0XFE;
WE=0;
DU=1;
P0=0x40;
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XFd;
WE=0;
DU=1;
P0=SMGduan[i];
DU=0;
delay(8);
}
if(i>=10&&i<99)
{
P0=0XFF;
WE=1;
P0=0XFe;
WE=0;
DU=1;
P0=0x40;
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XFd;
WE=0;
DU=1;
P0=SMGduan[i/10];
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XFb;
WE=0;
DU=1;
P0=SMGduan[i%10];
DU=0;
delay(8);
}
if(i>=100&&i<999)
{
P0=0XFF;
WE=1;
P0=0XFe;
WE=0;
DU=1;
P0=0x40;
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XFd;
WE=0;
DU=1;
P0=SMGduan[i/100];
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XFb;
WE=0;
DU=1;
P0=SMGduan[i%100/10];
DU=0;
delay(8);
P0=0XFF;
WE=1;
P0=0XF7;
WE=0;
DU=1;
P0=SMGduan[i%10];
DU=0;
delay(8);
}
}
}
//也可以用中断来实现
//矩阵键盘的扫描
void keyscan()
{
uchar temp;
P3=0XFF;
P3=0XFE;
temp=P3&0XF0;
if(temp!=0xf0)
{
delay(20);
P3=0XFE;
temp=P3&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1+7;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-7;num=n1;F=1;i++;break;
}
case 0xde: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1+8;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-8;num=n1;F=1;i++;break;
}
case 0xbe: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1+9;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-9;num=n1;F=1;i++;break;
}
case 0x7e: Beep=0;
delay(20);
Beep=1;
n2=n1;
n1=0;
flag=1;
WE=1;
P0=0XFF;
WE=0;
T=0;
F=0;
i++;
break;
}//+
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
P3=0XFF;
}
}
P3=0XFF;
P3=0XFD;
temp=P3&0xf0;
if(temp!=0xf0)
{
delay(20);
P3=0XFD;
temp=P3&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1+4;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-4;num=n1;F=1;i++;break;
}
case 0xdd: Beep=0;
delay(10);
Beep=1;
if(T==0)
{
n1=10*n1+5;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-5;num=n1;F=1;i++;break;
}
case 0xbd: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1+6;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-6;num=n1;F=1;i++;break;
}
case 0x7d: Beep=0;
delay(20);
Beep=1;
if(F==1)
{
n2=n1;
n1=0;
flag=2;
WE=1;
P0=0XFF;
WE=0;
T=0;
F=0;
i++;
break;
}//-
if(F==0)
{
T=1;
break;
}//负号
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
P3=0XFF;
}
}
P3=0XFF;
P3=0XFB;
temp=P3&0xf0;
if(temp!=0xf0)
{
delay(20);
P3=0XFB;
temp=P3&0XF0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1+1;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-1;num=n1;F=1;i++;break;
}
case 0xdb: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1+2;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-2;num=n1;F=1;i++;break;
}
case 0xbb: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1+3;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1-3;num=n1;F=1;i++;break;
}
case 0x7b: Beep=0;
delay(20);
Beep=1;
n2=n1;
n1=0;
flag=3;
WE=1;
P0=0XFF;
WE=0;
T=0;
F=0;
i++;
break;
}// X
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
P3=0XFF;
}
}
P3=0XFF;
P3=0XF7;
temp=P3&0xf0;
if(temp!=0xf0)
{
delay(20);
P3=0XF7;
temp=P3&0xf7;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7: Beep=0;
delay(20);
Beep=1;
i++;
n1=n1/10;
num=n1;
break;
case 0xd7: Beep=0;
delay(20);
Beep=1;
if(T==0)
{
n1=10*n1;num=n1;F=1;i++;break;
}
if(T==1)
{
n1=10*n1;num=n1;F=1;i++;break;
}
case 0xb7: Beep=0;
delay(20);
Beep=1;
if(flag==1) num=n2+n1;
if(flag==2) num=n2-n1;
if(flag==3) num=n2*n1;
if(flag==4) num=n2/n1;
n1=0;
WE=1;
P0=0XFF;
WE=0;
F=0;//一次计算完成后重置标志位
i++;
break;//=
case 0x77: Beep=0;
delay(20);
Beep=1;
n2=n1;
n1=0;
flag=4;
WE=1;
P0=0XFF;
WE=0;
T=0;
F=0;
i++;
break;//÷
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
P3=0XFF;
}
}
P3=0XFF;
if(P3==0XFB)
{
delay(20);
if(P3==0XFB)
{
tabel5[A]=num;
C=A;//将数组变量赋给读取数组的变量
A++;
n1=0;
num=0;
if(A>9)
{
for(A=9;A>-1;A--)
{
tabel5[A]=0;
}
A=0;
}//存满后自动清零
while(P3==0XFB);
}
}
if(P3==0XF7)
{
delay(20);
if(P3==0XF7)
{
num=tabel5[C];
C--;
while(P3==0XF7);
}
}
}
void keyscan1()//部分独立键盘判断
{
if(P3==0XFE)
{
delay(10);
if(P3==0XFE)
{
j=1;
WE=1;
P0=0xFF;
WE=0;
num=0;
n1=0;
Beep=0;
delay(20);
Beep=1;
P1=0XFF;
while(P3==0XFE);
}
}
P3=0XFF;
if(P3==0XFD)
{
delay(20);
if(P3==0XFD)
{
j=0;
Beep=0;
delay(20);
Beep=1;
while(P3==0XFD);
}
}
}
void main()
{
while(1)
{
if(j==1)
{
keyscan1();
}
if(j==0)
{
keyscan();
display(num);
P1=LED[i];
if(i>7)
{
i=0;
}
keyscan1();
}
}
}
已经通过编译测试,代码可以正常使用。个人认为写的还比较好理解,毕竟我学单片机也没多久(=。=)。
代码可能看起来比较冗余,欢迎各位大神提出意见,我看到后会努力精简的!
第一次尝试在CSDN平台发布自己写的代码,希望读到本文的各位多多鼓励哈~相信我们很快会再次见面的!