关于51单片机矩阵键盘移位输入的疑问,为什么我这样写在低四位数码管显示的都是同一个按下的对应数字??

为什么我这样写在低四位数码管显示的都是同一个按下的对应数字??也就是同时显示1111或者4444等等,是否移位部分写错了???该怎么修改才能实现输入移位?哪位大哥能帮帮,... 为什么我这样写在低四位数码管显示的都是同一个按下的对应数字??也就是同时显示1111或者4444等等,是否移位部分写错了???该怎么修改才能实现输入移位?哪位大哥能帮帮,谢谢。。。。
#include <STC12c5a60s2.H>
#define uchar unsigned char
#define uint unsigned int

unsigned char code Bit_Table[8]={0xFE,0xFD,0xFB,0xF7};
unsigned char code Seg_Table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,
0x7d,0x07,0x7f,0x6f, 0x00};

unsigned char LedBuf[8]={10,10,10,10,10,10,10,10};

uchar KeyDownFlag = 0;
uchar KeyValue = 0;
uchar KeyValueTemp = 0;
uchar Key20msDelay = 0;
uchar k;
sbit P23 = P2^3;
sbit P22 = P2^2;
sbit P21 = P2^1;
sbit P20 = P2^0;

void KeyScan(void)
{
uchar TestKeyCode;
uchar ScanKeyCode;
uchar i;

ScanKeyCode = 0x00;
for(i=0;i<4;i++)
{
TestKeyCode = 0x80;//1000 0000
TestKeyCode >>=i; //0010 0000
TestKeyCode = ~TestKeyCode; //0xdf

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;
}

}
if(ScanKeyCode)
{
if(!KeyDownFlag)
{
if(Key20msDelay)
{
Key20msDelay++;
if(Key20msDelay>8)
{
if(KeyValueTemp == ScanKeyCode)
{
KeyDownFlag = 1;
k++;
KeyValue = KeyValueTemp;
Key20msDelay = 0;
}
else
{
Key20msDelay = 1;
KeyValueTemp = ScanKeyCode;
}
}
}
else
{
Key20msDelay = 1;
KeyValueTemp = ScanKeyCode;
}
}
}
else
{
if(Key20msDelay)
{
Key20msDelay++;
if(Key20msDelay>8)
{
Key20msDelay = 0;
}
}
else
{
KeyDownFlag = 0;
}
}
}

void main(void)
{
EA = 1;
TH0 = 0xf7;//2.5ms
TL0 = 0x00;
TMOD = 0x01;
TR0 =1;
ET0 =1;
while(1);
}

void T0_interrupt(void) interrupt 1
{
static unsigned char data i = 0x00;

TH0 = 0xf7; //2.5ms
TL0 = 0x00;

KeyScan();
P0 = 0x00;
P1 = Bit_Table[i];
P0 = Seg_Table[LedBuf[i]];
i++;
if(i > 4 ) i = 0x00;
if(KeyDownFlag)
{
if(k<4)
{
LedBuf[3]=LedBuf[2];
LedBuf[2]=LedBuf[1];
LedBuf[1]=LedBuf[0];
LedBuf[0]=KeyValue;
}

}
}
展开
 我来答
xingqigongmeng
2010-12-02 · TA获得超过180个赞
知道答主
回答量:204
采纳率:0%
帮助的人:123万
展开全部
你的位选送入是同样的数据,那当然是显示同样的数,你要分清楚位选,是怎么样位选,这样你就可以想那个显示什么数字都可以了。
你的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;
}
查志强2010
2010-12-02 · TA获得超过574个赞
知道小有建树答主
回答量:102
采纳率:0%
帮助的人:84.3万
展开全部
1.位定义最好用有意义的英文(哪怕拼音也好),方便检查和阅读
2.矩阵键盘的扫描有这么几种:行列扫描,反转扫描,中断扫描;按下时要去抖,功能实现一般要等键按完(弹起来)后才去实现功能
3.数码管的动态扫描的程序设计你没有掌握,而且动态扫描还要注意消影
4.数码管的动态扫描配合键盘时,要注意闪烁问题,解决闪烁有两个方法:
第一个方法:键盘消抖不用延时函数,而用数码管动态扫描函数
第二个方法:用中断的方法每2ms调用一次数码管动态扫描函数,因为中断不受按键影响
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define DataPort P0
#define KeyPort P3
sbit dula=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;

dula=1;
DataPort=tempData[i];
dula=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); // 调用数码管扫描
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
zyj1739
2010-12-02 · TA获得超过140个赞
知道小有建树答主
回答量:238
采纳率:0%
帮助的人:190万
展开全部
在每一次段选显示数字之后 位选开了,一定要关闭,再送下一个数据。段选和位选要分开啊
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(1)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式