用51单片机制作的简易数码管计算器
- 本次计算器仿真实验中,使用了共阳极的数码管7SEG-MPX4-CA为计算器的显示组件,十六个button按钮为计算器的选择按钮。如果你想显示更多位可以自己选别的,接线方式一样,如若是6位以上的推荐用译码器啥的节省io口(ps用的89c51芯片仿真)
- 本次实验使用P2口控制数码管位选,P3口控制数码管段选,P0口控制矩阵键盘,P0口低四位控制行选择,高四位控制列选择:
int digit[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //共阳极数码管0-9 int box[4]={0}; //用来动态改变digit数组的值 int KeyValue; //用来保存按键的值 int KeySwitch; //用来判断KeyValue是否是0到9的数
-
创建显示函数,即四位数码管数字在极短延时下交错显示,具体代码如下(延时函数自己写一下就好):
void display() { P2=0x01;P3=digit]; delay(10);//初值都为零,上面定义了 P2=0x02;P3=digit];delay(10); P2=0x04;P3=digit];delay(10); P2=0x08;P3=digit];delay(10); }
- 创建矩阵键盘的行列判断函数,先判断列,再判断行,具体代码如下:
//这样给keyvalue赋值,能巧妙的使keyvalue的0~9值对应键盘按键的0~9,方便后面给数码管赋值,行列选择原理是按下按钮后,低电平会拉低高电平,改变端口值 P1=0xf0; if(P1!=0xf0) { delay(20); if(P1!=0xf0) { P1=0xf0; switch(P1) { case(0Xe0): KeyValue=0;break; case(0Xd0): KeyValue=1;break; case(0Xb0): KeyValue=2;break; case(0X70): KeyValue=3;break;} P1=0x0f; switch(P1) { case(0X0e): KeyValue=KeyValue;break; case(0X0d): KeyValue=KeyValue+4;break; case(0X0b): KeyValue=KeyValue+8;break; case(0X07): KeyValue=KeyValue+12;break;}
- 定义数字0~9的按键状态若被按下则keyswitch值为1,目的是为了和后面的运算符号区别开来做判断,具体代码如下:
if(KeyValue==0 || KeyValue==1 || KeyValue==2 || KeyValue==3 || KeyValue==4 || KeyValue==5 || KeyValue==6 || KeyValue==7 || KeyValue==8 || KeyValue==9) { KeySwitch=1; }
- 松开按键判断,因为不做这个判断的话,按下一个数字后,KeySwitch的值一直为1,则会直接使四个数码都显示为同一个数字,具体代码如下:
Int a; a=0; //P1是判断上面的键盘选择的值的 while((a<100)&&(P1!=0x0F)) { delay(100); a++; }
- 4~6的选择判断共同组成矩阵键盘的选择判断函数void KeyDown()
- 主函数中,死循环中需要先调用初始化的显示函数,然后调用KeyDown()函数,然后通过判断已经被赋值的keyswitch判断按下的是否是0~9的数字,是则显示数字,具体代码如下:
display(); //调用显示初值 KeyDown(); if(KeySwitch==1) //判断按下的是否是0~9的数字 { for(i=3;i>0;i--) {box[i]=box[i-1];} //如果按下不止一个数字则把低位数字赋给高位显示,最后按下的永远显示在最低位 box[0]=KeyValue; //利用率keyvalue值和键盘上0~9的对应关系 KeySwitch=0; } //恢复为0,等待第二次值的改变判断
-
当keyswitch不为1时,则按下按键后要通过keyvalue的值来判断实现对应功能,若KeyValue==10,则把四位数码管置零显示,即复位功能按钮,具体代码如下:
if(KeyValue==10) { for(i=0;i<4;i++){box[i]=0; } display(); //赋值后调用显示函数
- 若KeyValue==12,则为运算符加号,此时会利用每一位数码管上的keyvalue值从低位到高位(个位除外)乘10、100、1000后相加后存入a中,同时数码管置零显示,表示可以输入第二个数后。
-
还需要重新使用死循环调用一次8中的语句来判断第二个数值的写入,直到KeyValue==11(即等于号被按下)则跳出第二个死循环,同时把第二个数按第一个数的方法存入b变量中,同时把a和b进行加法进行运算后,通过除10、100、1000取余或来把结果赋值给数码管显示出来。
具体代码如下:
if(KeyValue==12) //判断按下的是加号 {a=box[0]+box[1]*10+box[2]*100+box[3]*1000; for(i=0;i<4;i++){box[i]=0;} //让数码管显示清零 while(1) { display();KeyDown(); if(KeySwitch==1) //再次检测第二个数字的输入,此时不检测 别的运算符输入 { for(i=3;i>0;i--){box[i]=box[i-1];} box[0]=KeyValue; KeySwitch=0;} if(KeyValue==11) break; } //检测是否按下等于号 b=box[0]+box[1]*10+box[2]*100+box[3]*1000; c=a+b; box[0]=c%10; box[1]=c/10%10;box[2]=c/100%10;box[3]=c/1000%10; display();} //运算结果显示在数码管上
-
同样的,若KeyValue==13(减号),KeyValue==14(乘号),KeyValue==15(除号),也是通过加法的代码去实现,只需要把c=a+b中的加号改为对应的运算符即可。
-
对于除法,因为被除数不能为零,所以在上面的运算代码上,还加了按下等于号后,判断被除数b为零则从高位到低位输出ERRO后再运行后面的代码(可有可无,不重要),具体如下:
if(b==0){ P2=0x01;P3=0x86;delay(200); P2=0x02;P3=0x88; delay(200); P2=0x04;P3=0x88;delay(200); P2=0x08;P3=0xC0;delay(200); break; }
-
仿真图,23*9的结果
-
-
代码也是参考网上别人的,完整代码
#include<reg51.h> int digit[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; int box[4]={0}; int i; int KeyValue; int KeySwitch; void delay(int ms) { int x,y; for(x= ms;x>0;x--) for(y=110;y>0;y--); } void display() { P2=0x01; P3=digit]; delay(10); P2=0x02; P3=digit]; delay(10); P2=0x04; P3=digit]; delay(10); P2=0x08; P3=digit]; delay(10); } void KeyDown(void) { int a; a=0; P1=0xf0; if(P1!=0xf0) { delay(20); if(P1!=0xf0) { P1=0xf0; switch(P1) { case(0Xe0): KeyValue=0;break; case(0Xd0): KeyValue=1;break; case(0Xb0): KeyValue=2;break; case(0X70): KeyValue=3;break; } P1=0x0f; switch(P1) { case(0X0e): KeyValue=KeyValue;break; case(0X0d): KeyValue=KeyValue+4;break; case(0X0b): KeyValue=KeyValue+8;break; case(0X07): 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) { KeySwitch=1; } while((a<50)&&(P1!=0x0F)) { delay(100); a++; } } } } void main() { int a,b,c; while(1){ display(); KeyDown(); if(KeySwitch==1) { for(i=3;i>0;i--) {box[i]=box[i-1];} box[0]=KeyValue; KeySwitch=0; } else if(KeyValue==10) { for(i=0;i<4;i++) box[i]=0; display(); } else if(KeyValue==12) { a=box[0]+box[1]*10+box[2]*100+box[3]*1000; for(i=0;i<4;i++) box[i]=0; while(1) { display(); KeyDown(); if(KeySwitch==1) { for(i=3;i>0;i--) {box[i]=box[i-1];} box[0]=KeyValue; KeySwitch=0; } if(KeyValue==11) break; } b=box[0]+box[1]*10+box[2]*100+box[3]*1000; c=a+b; box[0]=c%10; box[1]=c/10%10; box[2]=c/100%10; box[3]=c/1000%10; display(); } else if(KeyValue==13) { a=box[0]+box[1]*10+box[2]*100+box[3]*1000; for(i=0;i<4;i++) box[i]=0; while(1) { display(); KeyDown(); if(KeySwitch==1) { for(i=3;i>0;i--) {box[i]=box[i-1];} box[0]=KeyValue; KeySwitch=0; } if(KeyValue==11) break; } b=box[0]+box[1]*10+box[2]*100+box[3]*1000; c=a-b; box[0]=c%10; box[1]=c/10%10; box[2]=c/100%10; box[3]=c/1000%10; display(); } else if(KeyValue==14) { a=box[0]+box[1]*10+box[2]*100+box[3]; for(i=0;i<4;i++) box[i]=0; while(1) { display(); KeyDown(); if(KeySwitch==1) { for(i=3;i>0;i--) {box[i]=box[i-1];} box[0]=KeyValue; KeySwitch=0; } if(KeyValue==11) break; } b=box[0]+box[1]*10+box[2]*100+box[3]*1000; c=a*b; box[0]=c%10; box[1]=c/10%10; box[2]=c/100%10; box[3]=c/1000%10; display(); } else if(KeyValue==15) { a=box[0]+box[1]*10+box[2]*100+box[3]*1000; for(i=0;i<4;i++) box[i]=0; while(1) { display(); KeyDown(); if(KeySwitch==1) { for(i=3;i>0;i--) {box[i]=box[i-1];} box[0]=KeyValue; KeySwitch=0; } if(KeyValue==11) break; } b=box[0]+box[1]*10+box[2]*100+box[3]*1000; if(b==0){ P2=0x01; P3=0x86; delay(200); P2=0x02; P3=0x88; delay(200); P2=0x04; P3=0x88; delay(200); P2=0x08; P3=0xC0; delay(200); break; } c=a/b; box[0]=c%10; box[1]=c/10%10; box[2]=c/100%10; box[3]=c/1000%10; display(); } } }