关于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;
}
}
} 展开
#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;
}
}
} 展开
3个回答
展开全部
你的位选送入是同样的数据,那当然是显示同样的数,你要分清楚位选,是怎么样位选,这样你就可以想那个显示什么数字都可以了。
你的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;
}
你的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;
}
展开全部
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); // 调用数码管扫描
}
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); // 调用数码管扫描
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
在每一次段选显示数字之后 位选开了,一定要关闭,再送下一个数据。段选和位选要分开啊
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询