仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
行列式按键及计算器仿真及程序程序如下
- #include"at89x51.h" // C计时器参考
-
- unsigned int da1=0, da2=0, resu=0;
- unsigned char fh=0, zhuangtai=0, key, keyzhi, jianzhi;
- unsigned char code tv[]={0xfe,0xfd,0xfb,0xf7}; //位选数组
- unsigned char code a[]={0x3f,0x06,0x5b,0x4f,
- 0x66,0x6d,0x7d,0x07,0x7f,
- 0x6f,0x77,0x7c,0x39,0x5e,
- 0x79,0x71,0x00}; //显示是P0口的值对应的数组
- unsigned char data led[4] = {0, 16, 16, 16}; //将首位定义成零,在计算器的初始显示的时候右边有‘0’表示计算器已经开始工作
- //函数名:delay 时间:
- //作用:在显示函数中延时
- //说明:延时的时间不用太长即i的峰值不要定太大
- //作者:ymx
- void delay()
- {
- unsigned char i;
- for (i=0; i<200; i++)
- {
- ;
- }
- }
- //函数名:keydeal 时间:
- //作用:扫描键盘,通过低电位会将高电位拉成低电位的原理,分别判断出按键的横纵坐标并将jianzhi传递到jianhao函数
- //说明:传递0x0f判断纵坐标,传递0xf0判断横坐标
- //作者:ymx
- unsigned char keydeal()
- {
- unsigned char x, y;
- P3 = 0xff;
- P3 = 0x0f;
- x = P3;
- P3 = 0xff;
- P3 = 0xf0;
- y = P3;
- jianzhi = x + y;
- return jianzhi;
- }
- //函数名:jisuan 时间:
- //作用:根据记录的运算符号和两个数的值计算出结果
- //说明:
- //作者:ymx
- jisuan(void)
- {
- switch(fh)
- {
- case '+':
- resu = da1+da2;
- break;
- case '-':
- resu = da1-da2;
- break;
- case '*':
- resu = da1*da2;
- break;
- case '/':
- resu = da1/da2;
- break;
- }
- fh=0; //将符号清零
- }
- //函数名:jianhao 时间:
- //作用:通过keydeal传递的数值判断按下的按键分别代表的意义,如数字,运算符号等。并根据按键和按下键盘前的状态来切换此时的状态
- //说明:
- //作者:ymx
- void jianhao()
- {
- key = keydeal();
- switch(key)
- {
- case 0xff: keyzhi=16; break; //什么键都没有按下
- case 0xd7: keyzhi=0; break;
- case 0xeb: keyzhi=1; break;
- case 0xdb: keyzhi=2; break;
- case 0xbb: keyzhi=3; break;
- case 0xed: keyzhi=4; break;
- case 0xdd: keyzhi=5; break;
- case 0xbd: keyzhi=6; break;
- case 0xee: keyzhi=7; break;
- case 0xde: keyzhi=8; break;
- case 0xbe: keyzhi=9; break;
- case 0xe7:
- keyzhi=10; da1=0; da2=0; fh=0; resu=0; zhuangtai=0;
- led[1]=led[2]=led[3]=16; led[0]=0;break; //按下no键时将所有的值与状态复位,显示清零
- case 0xb7: keyzhi=11; zhuangtai=3; break; //按下等号键将状态换为3
- case 0x77: keyzhi=12; break;
- case 0x7b: keyzhi=13; break;
- case 0x7d: keyzhi=14; break;
- case 0x7e: keyzhi=15; break;
- }
- //如果按下的键在0~9的时候
- if (keyzhi<10)
- {
- if(zhuangtai==1)//如果前一状态为1。表示完成运算符号的记录,应当记录第二个数。状态切换为2
- {
- zhuangtai=2;
- }
- else if(zhuangtai==3) //如果前一状态为3,表示已经进行过一次运算并且得出了结果。此时将结果和原有数据清零进行新的运算。状态切换为0.
- {
- da1=da2=resu=0;
- zhuangtai=0;
- }
- }
- //如果按下的键在12~15的时候
- if (keyzhi>11 && keyzhi<16)
- {
- if (zhuangtai==0) //如果前一状态为0,表示记录好第一个数,此时应当记录运算符号。状态切换为1
- {
- zhuangtai=1;
- }
- else if(zhuangtai==3)//如果前一状态为3,即表示按下运算符号表示要利用原有结果进行运算。将结果值赋给da1并将
- {
- da1=resu; //并将结果值赋给da1,resu和da2清零。否则原有的值会影响第二次的运算结果。并将状态切换为1,记录下运算符号。
- da2=resu=0;
- zhuangtai=1;
- }
- else if(zhuangtai==2)//如果前一状态为2,即表示已经完成了da1和运算符和da2的记录。现在不按下等号进行连续运算(如1+2+3)。
- {
- jisuan(); //先计算出前面两个数的结果
- da1=resu; //将结果赋给da1
- da2=0; //结果和da2清零,并且将状态切换为1
- resu=0;
- zhuangtai=1;
- }
- }
- }
- //函数名:ysf 时间:
- //作用:记录下在状态1时所按下的运算符号
- //说明:
- //作者:ymx
- void ysf()
- {
- switch(keyzhi)
- {
- case 12:
- fh='+';
- break;
- case 13:
- fh='-';
- break;
- case 14:
- fh='*';
- break;
- case 15:
- fh='/';
- break;
- default:
- break;
- }
-
- }
- void move()
- {
- unsigned int linshi=0;
- linshi = keyzhi; //保存下按下的数值
- while(keyzhi != 16)
- {
- jianhao();
- }
- if(led[0]==0&&led[1]==16&&led[2]==16&&led[3]==16&&linshi!=16) //if里的条件表示初始的只是0的时候
- {
- led[0]=linshi; //移位时要将原有的0替换掉否则数显示的数的前面都会有一个零如:0123
- }
- else
- {
- if(linshi!=16) //如果按下了键才开始移位,否则会有空白
- {
- led[3] = led[2];
- led[2] = led[1];
- led[1] = led[0];
- led[0] = linshi;
- }
- }
- if(zhuangtai==0) //状态为0时记录第一个数
- {
- da1=da1*10+linshi;
- }
- if(zhuangtai==2) //状态为2时记录第二个数
- {
- da2=da2*10+linshi;
- }
- }
- //函数名:jieguo 时间:
- //作用:将结果转化为可以显示的形式
- //说明:
- //作者:ymx
- void jieguo() //计算出的结果是 一个整型的书,数码管并不能直接显示,需要把它替换成单个的数赋给显示的led数组
- {
- if(resu<10000) //如果显示的结果小于5位才显示
- {
- if (resu>999)
- {
- led[3]=resu/1000; //记录下千位的值
- }
- else
- {
- led[3]=16;
- }
- if(resu>99)
- {
- led[2]=(resu/100)%10; //记录下百位的值
- }
- else
- {
- led[2]= 16;
- }
- if(resu>9)
- {
- led[1]=(resu/10)%10;
- }
- else
- {
- led[1]=16;
- }
- if(resu>0)
- {
- led[0]=resu%10;
- }
- else
- {
- led[0]=0;
- }
- }
- else //如果不是小于5位的话,则显示‘E’表示错误
- {
- led[0]=14;
- }
- }
- //函数名:xianshi 时间:
- //作用:位选和显示不同的数时所对应的P0口的电位值
- //说明:
- //作者:ymx
- void xianshi()
- {
- unsigned char i, k;
- for (i=0; i<4; i++)
- {
- k = led[i];
- P0 = a[k];
- P2 = tv[3-i];
- delay();
- }
- }
- //函数名:main 时间:
- //作用:完成整个程序的循环
- //说明:main函数中除了记录数值得两个状态之外剩下的的状态里的jianhao函数均是用于切换状态和复位用的
- // zhuangtai=0表示记录第一个数,1表示记录运算符号,2表示记录第二个数,3表示计算结果并显示
- //作者:ymx
-
- void main(void)
- {
- while(1)
- {
- while(zhuangtai==0)
- {
- resu=0;
- jianhao();
- if(keyzhi<=9)//判断是按下的是否是数,是得话才移位和显示数值否则显示不变。下面状态2同
- {
- move();
- }
- xianshi();
- resu=0;
- }
- while(zhuangtai==1)
- {
- led[0]=led[1]=led[2]=led[3]=16;//将显示清零
- jianhao();
- ysf(); //记录下运算符号
- }
- while(zhuangtai==2)
- {
- resu=0;
- jianhao();
- if(keyzhi<=9)
- {
- move();
- }
- xianshi();
- }
- while(zhuangtai==3)
- {
- jianhao();
- jisuan();
- jieguo();
- xianshi();
- }
- }
- }
复制代码
全部资料51hei下载地址:
行列式按键及计算器.rar
(46.07 KB, 下载次数: 9)
|