目录
百度云盘链接:https://pan.baidu.com/s/1qm8czv8ibf5QabGxxgYC0A?pwd=y4lc 提取码:y4lc
1 设计说明
在proteus仿真stc89c51,通过控制按键,显示在数码管上实现计算器的加减乘除
百度云盘链接:https://pan.baidu.com/s/1qm8czv8ibf5QabGxxgYC0A?pwd=y4lc 提取码:y4lc
2 硬件设计
1 动态数码管
首先数码管是一种常见的数码显示器件,它由8个LED(发光二极管)组成,分段选和共选,其中又分共阴极和共阳极,其实就是共选是8个led共同使用一个阴极或阳极。8个led用于显示数字、字母或符号。每个LED都代表一个特定的数字段或符号段,可以通过控制这些LED的亮灭状态来显示所需的内容。通常,8位数码管的排列方式如下图所示:
这个排列方式中,每个数字或符号的显示都被分成了8个不同的段,分别用数字0到7表示,加上小数点(如果有的话),用数字7表示。根据需要显示的数字或符号,点亮相应的LED段就可以了。为了控制8位数码管显示内容,需要使用多路开关(比如BCD码或二进制编码器)来控制每个数字段的LED。这些开关根据输入信号的不同,打开或关闭相应的LED,从而显示不同的数字或符号。般来说,要控制一个8位数码管,需要至少8个输出引脚来分别控制每个LED段的亮灭状态。这些引脚通过微控制器或其他逻辑电路来控制,根据需要显示的数字或符号,输出相应的信号。
而八个数码管显示的原理其实是一种视角的错位感觉,其实在一个时间点只有一个数码管亮,但是在第一个亮之后的极端时间内(微妙级别)第二个亮,然后以此反复就会形成我们肉眼看到的全部都亮的情况
2 16矩阵的扫描
行列扫描法是一种按键检测方法,它通过依次扫描键盘的行和列来确定按下的按键。首先,我们将其中一列设为低电平,而其他几列都设置为高电平。接着,我们逐行检测是否有按键被按下,如果某一行检测到低电平,说明这是被按下的行。然后,我们再逐列扫描,将每一列设为低电平,检测各行的电平状态,从而确定按下的按键是哪一行哪一列的。通过这样的扫描方式,我们可以检测到整个键盘上是否有按键被按下。
3 Proteus的连接
3 代码的实现
#include <REGX51.H>
unsigned char a[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
unsigned char b[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 } ;
unsigned char d[]={~0x21,~0x12,~0x22,~0x42,~0x14,~0x24,~0x44,~0x18,~0x28,~0x48};
unsigned char e[]={~0x01,~0x02,~0x04,~0x08,~0x81};
unsigned char c[8];
unsigned int i,j,k,l,n,nm,ny;
unsigned int y1,y2,y3,y4,y5,y6,y7,y8;
unsigned int x,x1,x2;
unsigned int q;
void delay(unsigned int x)
{
x--;
}
void shuguan(unsigned int m)
{
P0=0xff;
switch(j)
{
case 0 :P2=b[j];if(m>=10000000)P0=a[m/10000000%10];else P0=0xff;break;
case 1:P2=b[j];if(m>=1000000)P0=a[m/1000000%10];else P0=0xff;break;
case 2:P2=b[j];if(m>=100000)P0=a[m/100000%10];else P0=0xff;break;
case 3:P2=b[j];if(m>=10000)P0=a[m/10000%10];else P0=0xff;break;
case 4:P2=b[j];if(m>=1000)P0=a[m/1000%10];else P0=0xff;break;
case 5:P2=b[j];if(m>=100)P0=a[m/100%10];else P0=0xff;break;
case 6:P2=b[j];if(m>=10)P0=a[m/10%10];else P0=0xff;break;
case 7:P2=b[j];if(x2==0)P0=a[m%10];if(x2==1)P0=0x88;if(x2==2)P0=0x83;if(x2==3)P0=0xc6;if(x2==4)P0=0xa1;break;
}
j++;if(j==8)j=0;
delay(300);
}
void anj()
{
for(i=0;i<4;i++)
{
P1=e[i];
if(P1!=e[i])
{
y2=i ;
for(nm=0;nm<10;nm++)
{
if(P1==d[nm])
{
ny=nm;
y1=1;
}
}
if(P1==e[4]) //~0x81,不可以,???
{
y3=1;
}
if(P1==~0x41)
{
y4=1 ;
}
if(P1==(0xff-0x82))
{
y5=1;
}
if(P1==(0xff-0x84))
{
y6=1;
}
if(P1==(0xff-0x88))
{
y7=1;
}
if(P1==(0xff-0x11))
{
y8=1;
}
}
if(i==y2)
{
if(P1==e[i]&&y1==1)
{
x=x*10+ny;
x2=0;
y1=0;
}
if(P1==e[i]&&y3==1)
{
if(q==0)x1=x;
if(q==1)x1=x1+x;if(q==2)x1=x1-x;if(q==3)x1=x1*x;if(q==4)x1=x1/x;
q=1;
x2=1;
x=0;
y3=0;
}
if(P1==e[i]&&y6==1)
{
if(q==0)x1=x;
if(q==1)x1=x1+x;if(q==2)x1=x1-x;if(q==3)x1=x1*x;if(q==4)x1=x1/x;
q=3;
x2=3;
x=0;
y6=0;
}
if(P1==e[i]&&y7==1)
{
if(q==0)x1=x;
if(q==1)x1=x1+x;if(q==2)x1=x1-x;if(q==3)x1=x1*x;if(q==4)x1=x1/x;
q=4;
x2=4;
x=0;
y7=0;
}
if(P1==e[i]&&y5==1)
{
if(q==0)x1=x;
if(q==1)x1=x1+x;if(q==2)x1=x1-x;if(q==3)x1=x1*x;if(q==4)x1=x1/x;
q=2;
x2=2;
x=0;
y5=0;
}
if(P1==e[i]&&y4==1)
{
if(q==0)x1=x;
if(q==1)x1=x1+x;if(q==2)x1=x1-x;if(q==3)x1=x1*x;if(q==4)x1=x1/x;
q=0;
if(q==0)x=x1;
x2=0;
y4=0;
}
if(P1==e[i]&&y8==1)
{
x=0;
x1=0;
x2=0;
y8=0;
}
}
}
}
void main()
{
x=0;
while(1)
{
shuguan(x);
anj();
}
}
4 结果演示
遗留了一个小问题(不影响程序)
如图
在程序里取反~0x81无法达到效果,换成0xff-0x81却可以,但是有的取反却可以用,比如~0x41,很诡异,我在板子上烧录也有这个问题。