关于51单片机矩阵键盘移位输入的疑问,为什么我这样写在低四位数码管显示的都是同一个按下的对应数字??
发布网友
发布时间:2023-03-22 22:13
我来回答
共3个回答
热心网友
时间:2023-10-12 06:09
你的位选送入是同样的数据,那当然是显示同样的数,你要分清楚位选,是怎么样位选,这样你就可以想那个显示什么数字都可以了。
你的P2口,你想要用独立按键或是矩阵按键,都要写捡测是否有键按下,这个你应该是知道的了,在这里,你的P2口打开,你这样写不是很好,你写的格式,要分好点,不然到你检查的时候就很难检查得到,还有你这里没有去抖,当按键按下时,会出错,
P2 = TestKeyCode;
if(!P23)
{
ScanKeyCode = 4*i + 1;
break;
}
else if(!P22)
{
ScanKeyCode = 4*i + 2;
break;
}
else if(!P21)
{
ScanKeyCode = 4*i + 3;
break;
}
else if(!P20)
{
ScanKeyCode = 4*i + 4;
break;
}
热心网友
时间:2023-10-12 06:09
1.位定义最好用有意义的英文(哪怕拼音也好),方便检查和阅读
2.矩阵键盘的扫描有这么几种:行列扫描,反转扫描,中断扫描;按下时要去抖,功能实现一般要等键按完(弹起来)后才去实现功能
3.数码管的动态扫描的程序设计你没有掌握,而且动态扫描还要注意消影
4.数码管的动态扫描配合键盘时,要注意闪烁问题,解决闪烁有两个方法:
第一个方法:键盘消抖不用延时函数,而用数码管动态扫描函数
第二个方法:用中断的方法每2ms调用一次数码管动态扫描函数,因为中断不受按键影响
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define DataPort P0
#define KeyPort P3
sbit la=P2^2;//段选
sbit wela=P2^1;//位选
uchar tempData[8];
uchar code DuanMa[]= //段码
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
uchar code WeiMa[]= //位码
{
0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f
};
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void display(uchar firstBit,uchar disCount)
{
static uchar i;
wela=1;//为了消影
DataPort=0xff;
wela=0;
la=1;
DataPort=tempData[i];
la=0;
DataPort=0xff;//为了消影
wela=1;
DataPort=WeiMa[i+firstBit];
wela=0;
i++;
if(i==disCount)
i=0;
}
uchar keyscan()
{
uchar value;
KeyPort=0xfe;//采用行列扫描
if((KeyPort&0xf0)!=0xf0)
{
delay(10);//消抖
if((KeyPort&0xf0)!=0xf0)
{
value=KeyPort;
while((KeyPort&0xf0)!=0xf0);
return value;
}
}
KeyPort=0xfd;
if((KeyPort&0xf0)!=0xf0)
{
delay(10);
if((KeyPort&0xf0)!=0xf0)
{
value=KeyPort;
while((KeyPort&0xf0)!=0xf0);
return value;
}
}
KeyPort=0xfb;
if((KeyPort&0xf0)!=0xf0)
{
delay(10);
if((KeyPort&0xf0)!=0xf0)
{
value=KeyPort;
while((KeyPort&0xf0)!=0xf0);
return value;
}
}
KeyPort=0xf7;
if((KeyPort&0xf0)!=0xf0)
{
delay(10);
if((KeyPort&0xf0)!=0xf0)
{
value=KeyPort;
while((KeyPort&0xf0)!=0xf0);
return value;
}
}
return 0xff;
}
unsigned char KeyPro(void)
{
switch(keyscan())
{
case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
case 0x7d:return 1;break;//1
case 0x7b:return 2;break;//2
case 0x77:return 3;break;//3
case 0xbe:return 4;break;//4
case 0xbd:return 5;break;//5
case 0xbb:return 6;break;//6
case 0xb7:return 7;break;//7
case 0xde:return 8;break;//8
case 0xdd:return 9;break;//9
case 0xdb:return 10;break;//a
case 0xd7:return 11;break;//b
case 0xee:return 12;break;//c
case 0xed:return 13;break;//d
case 0xeb:return 14;break;//e
case 0xe7:return 15;break;//f
default:return 0xff;break;
}
}
void init()
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
TH0=(65536-2000)/256; //重新赋值 2ms
TL0=(65536-2000)%256;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
void main()
{
uchar num,i,j;
init();
while(1)
{
num=KeyPro();
if(num!=0xff)
{
if(i<8)
{
tempData[i]=DuanMa[num];
i++;
}
else
{
i=0;
for(j=0;j<8;j++)
tempData[j]=0;
}
}
}
}
void timer0(void) interrupt 1
{
TH0=(65536-2000)/256; //重新赋值 2ms
TL0=(65536-2000)%256;
display(0,8); // 调用数码管扫描
}
热心网友
时间:2023-10-12 06:10
在每一次段选显示数字之后 位选开了,一定要关闭,再送下一个数据。段选和位选要分开啊