基于C51单片机的简易减法器设计制作
51单片机可实现很多功能,今天笔者介绍一种使用C51编写程序,通过4*4矩阵键盘和8位共阴数码管实现的简易减法器。矩阵键盘以及数码管的原理图如下:
(1)4*4矩阵键盘原理图:
(2)数码管的原理图:
编程代码如下:
#include <reg52.h>
#include "math.h"
#define GPIO_KEY P1
typedef unsigned int u16;
typedef unsigned char u8;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 b[8]={0,0,0,0,0,0,0,0};
u16 l,m,KeyValue,flag;
u8 DisplayData[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0-9(十六进制)数组
void delay(u16 i) //延时函数
{
while(i--);
}
void KeyDown() //按键函数
{
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)
{
delay(1000);
if(GPIO_KEY!=0x0f)
{
//测试列
GPIO_KEY=0X0f;
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}
//测试行
GPIO_KEY=0Xf0;
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): 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)
{
flag=1;
}
else if(KeyValue==10) //S11位减号
{
flag=2;
}
else if(KeyValue==11) //S12为等于号
{
flag=3;
}
while(GPIO_KEY!=0Xf0) //判断按键是否松开
{
delay(5);
}
}
}
void DigDisplay() //在数码管上显示 DisplayData里的元素
{
u8 j;
for(j=0;j<8;j++)
{
switch(j)
{
case(7):
LSA=1;LSB=1;LSC=1;break;//显示第0位
case(6):
LSA=0;LSB=1;LSC=1;break;//显示第1位
case(5):
LSA=1;LSB=0;LSC=1;break;//显示第2位
case(4):
LSA=0;LSB=0;LSC=1;break;//显示第3位
case(3):
LSA=1;LSB=1;LSC=0;break;//显示第4位
case(2):
LSA=0;LSB=1;LSC=0;break;//显示第5位
case(1):
LSA=1;LSB=0;LSC=0;break;//显示第6位
case(0):
LSA=0;LSB=0;LSC=0;break;//显示第7位
}
P0=DisplayData[j];
delay(100);
P0=0x00; //数码管消隐
}
}
void main()
{
u16 i,d,e,f=0,s,g=0,t,z,y,h,am;
u16 lm[8]={0};
while(1)
{
DigDisplay();
KeyDown();
if(flag==1)
{
for(i=7;i>0;i--)
{
b[i]=b[i-1];
}
b[0]=KeyValue;
//减数与被减数判断
if(g==0)
{
l=(b[7]*10000000 + b[6]*1000000 + b[5]*100000 + b[4]*10000 + b[3]*1000 + b[2]*100 + b[1]*10 + b[0]);
}
else
{
m=(b[7]*10000000 + b[6]*1000000 + b[5]*100000 + b[4]*10000 + b[3]*1000 + b[2]*100 + b[1]*10 + b[0]);
}
//判断输入的数的位数
for(e=0;e<8;e++)
{
if(b[e]!=0)
{
f=e+1;
}
}
//由上面得到输入的数的位数,接下来确定哪几个数码管显示
for(d=0;d<f;d++)
{
DisplayData[d]=smgduan[b[d]];
}
flag=100;
}
if(flag==2) //减号
{
for(s=0;s<8;s++) //b数组和DisplayData数组清零
{
b[s]=0;
DisplayData[s]=0x00;
}
DisplayData[0]=0x40; //减号显示,按下减号之后数码管上显示“—”号
flag=100;
g++;
}
if(flag==3) //等于号
{
if(l>m)
{
t=l-m;
lm[7]=t/10000000;
lm[6]=(t%10000000)/1000000;
lm[5]=((t%10000000)%1000000)/100000;
lm[4]=(((t%10000000)%1000000)%100000)/10000;
lm[3]=(((t%10000000)%1000000)%100000)%10000/1000;
lm[2]=(((t%10000000)%1000000)%100000)%10000%1000/100;
lm[1]=(((t%10000000)%1000000)%100000)%10000%1000%100/10;
lm[0]=(((t%10000000)%1000000)%100000)%10000%1000%100%10;
for(z=0;z<8;z++)
{
if(lm[z]!=0)
{
y=z+1;
}
}
for(h=0;h<y;h++)
{
DisplayData[h]=smgduan[lm[h]];
}
for(am=y;am<8;am++)
{
DisplayData[am]=0x00;
}
}
if(l<m)
{
t=m-l;
lm[7]=t/10000000;
lm[6]=(t%10000000)/1000000;
lm[5]=((t%10000000)%1000000)/100000;
lm[4]=(((t%10000000)%1000000)%100000)/10000;
lm[3]=(((t%10000000)%1000000)%100000)%10000/1000;
lm[2]=(((t%10000000)%1000000)%100000)%10000%1000/100;
lm[1]=(((t%10000000)%1000000)%100000)%10000%1000%100/10;
lm[0]=(((t%10000000)%1000000)%100000)%10000%1000%100%10;
for(z=0;z<8;z++)
{
if(lm[z]!=0)
{
y=z+1;
}
}
DisplayData[y]=0x40;
for(h=0;h<y;h++)
{
DisplayData[h]=smgduan[lm[h]];
}
for(am=y+1;am<8;am++)
{
DisplayData[am]=0x00;
}
}
flag=100;
}
DigDisplay();
}
}