标题:
单片机行列式按键及计算器仿真及程序 显示错误 求帮助
[打印本页]
作者:
叹服情
时间:
2020-10-10 20:03
标题:
单片机行列式按键及计算器仿真及程序 显示错误 求帮助
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png
(12.11 KB, 下载次数: 31)
下载附件
2020-10-10 21:15 上传
行列式按键及计算器仿真及程序程序如下
#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)
2020-10-10 20:03 上传
点击文件名下载附件
作者:
xianfajushi
时间:
2020-10-12 08:30
扫描键盘如果不用消抖和检测释放大部分会有问题
作者:
xianfajushi
时间:
2020-10-12 08:31
可参
https://blog.csdn.net/xianfajushi/article/details/80884859
作者:
IdeaMing
时间:
2020-10-12 08:51
授予鱼不如授予渔,你先单独显示,然后加入按键。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1