矩阵按键处理多个键值问题
大神们,帮帮忙呀,我都弄两天了还是不能解决
用状态机……
假设一个4行4列的矩阵键盘,一共需要8条IO,假设使用的P0口的8个脚
那么定时去读取P0口的数据,那一个被按下去,就会有两个脚电平产生变化,然后分辨是那个按键就可以了
注意需要去抖
比如是4*4矩阵按键,检测时可以通过单片机的I/O口送出低电平。检测时,先送出一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平,则我们就能确定是哪个按键被按下了。 你可以看一下下面的代码,希望对你帮助。
uint matrixkeyscan()
{
uchar temp,key;
P3=0xfe; //第一行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xde:
key=1;
break;
case 0xbe:
key=2;
break;
case 0x7e:
key=3;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xfd; //第二行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:
key=4;
break;
case 0xdd:
key=5;
break;
case 0xbd:
key=6;
break;
case 0x7d:
key=7;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xfb; //第三行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:
key=8;
break;
case 0xdb:
key=9;
break;
case 0xbb:
key=10;
break;
case 0x7b:
key=11;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xf7; //第四行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:
key=12;
break;
case 0xd7:
key=13;
break;
case 0xb7:
key=14;
break;
case 0x77:
key=15;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
return key;
}
不懂的话,可以加我好友,大家一起讨论,我也是新手,希望大家能互相进步!
比如是4*4矩阵按键,检测时可以通过单片机的I/O口送出低电平。检测时,先送出一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平,则我们就能确定是哪个按键被按下了。 你可以看一下下面的代码,希望对你帮助。
uint matrixkeyscan()
{
uchar temp,key;
P3=0xfe; //第一行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xde:
key=1;
break;
case 0xbe:
key=2;
break;
case 0x7e:
key=3;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xfd; //第二行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:
key=4;
break;
case 0xdd:
key=5;
break;
case 0xbd:
key=6;
break;
case 0x7d:
key=7;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xfb; //第三行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:
key=8;
break;
case 0xdb:
key=9;
break;
case 0xbb:
key=10;
break;
case 0x7b:
key=11;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xf7; //第四行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:
key=12;
break;
case 0xd7:
key=13;
break;
case 0xb7:
key=14;
break;
case 0x77:
key=15;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
return key;
}
不懂的话,可以加我好友,大家一起讨论,我也是新手,希望大家能互相进步!
比如是4*4矩阵按键,检测时可以通过单片机的I/O口送出低电平。检测时,先送出一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平,则我们就能确定是哪个按键被按下了。 你可以看一下下面的代码,希望对你帮助。 代码的返回值就是哪个按键的值,可以用一个变量进行标记,记录按下的次数。
uint matrixkeyscan()
{
uchar temp,key;
P3=0xfe; //第一行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xde:
key=1;
break;
case 0xbe:
key=2;
break;
case 0x7e:
key=3;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xfd; //第二行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:
key=4;
break;
case 0xdd:
key=5;
break;
case 0xbd:
key=6;
break;
case 0x7d:
key=7;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xfb; //第三行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:
key=8;
break;
case 0xdb:
key=9;
break;
case 0xbb:
key=10;
break;
case 0x7b:
key=11;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
P3=0xf7; //第四行键盘
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10); //消除按键抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:
key=12;
break;
case 0xd7:
key=13;
break;
case 0xb7:
key=14;
break;
case 0x77:
key=15;
break;
}
while(temp!=0xf0) //条件满足时是1;等待按键释放;
{
temp=P3; //这两句是增加程序的稳定性
temp=temp&0xf0;
}
}
}
return key;
}
不懂的话,可以加我好友,大家一起讨论,我也是新手,希望大家能互相进步!
谢谢你的好意,但是我想要的不是这个结果
比如是4*4矩阵按键,在矩阵按键扫描的时候行和列分别送相反电平此时该组IO口有一个8位二进制数值,在按第一个按键时.该组IO口数值有所变化,保持此时按键值,再按下另外按键时,此时该组IO口数值发生第二次变化,弟弟两次按键值,即可判断出第二次按键值。依次对比,就可以判断出后面按键。
- #define Key_4_4_NULL 0xff
- uchar Read_Keyboart_4_4() //4*4键盘
- {
- static uchar Key_Static=0; //状态机变量
- uchar Key_Press; //读取按键值变量
- uchar Key_H=0; //行
- uchar Key_L=0; //列
-
- P1=0x0f;
- Key_H=P1&0x0f;
- switch(Key_Static) //选择按键状态
- {
- case 0:if(Key_H!=0x0f) Key_Static=1;//有按键按下,转到下一状态
- break;
-
- case 1:if(Key_H!=0x0f)
- {
- Key_Static=2;
- Key_H=P1&0x0f;
- P1=Key_H|0xf0;
- Key_L=P1&0xf0;
- Key_Press=Key_H+Key_L; //读取行和列
- return Key_Press;
- }
- else Key_Static=0;
- break;
-
- case 2:if(Key_H==0x0f) Key_Static=0; //判断按键是否松开,松开就返回到0态
- break;
-
- default:Key_Static=0;break;
- }
-
- return Key_4_4_NULL; //返回按键值
- }
- uchar Set_Keyboart_4_4() //每20ms扫描一次,消抖动就是20ms
- {
- uchar Key_Data;
-
- Key_Data=Read_Keyboart_4_4();//读取按键值
- switch(Key_Data)
- {
- case 0xee:return Key_4_4_NULL;break; //
- case 0xde:return Key_4_4_NULL;break; //
- case 0xbe:return Key_4_4_NULL;break; //
- case 0x7e:return Key_4_4_NULL;break; //
-
- case 0xed:return 9;break; //9
- case 0xdd:return 6;break; //6
- case 0xbd:return 3;break; //3
- case 0x7d:return Key_4_4_NULL;break; //
-
- case 0xeb:return 8;break; //8
- case 0xdb:return 5;break; //5
- case 0xbb:return 2;break; //2
- case 0x7b:return 0;break; //0
-
- case 0xe7:return 7;break; //7
- case 0xd7:return 4;break; //4
- case 0xb7:return 1;break; //1
- case 0x77:return Key_4_4_NULL;break; //
-
- default:break;
- }
-
- return Key_4_4_NULL;
- }
自己写的状态机按键程序,看不懂可以多看几次,多想几次,慢慢研究,对实际应用很有价值
真不知道这么多,词不达意的人,怎么当软件工程师的。小编要的是按下第一个按键后,再检测之后的键值,是怎么实现。而不是扫键函数。
时隔一年了,小编,怎么解决问题的,分享下,可以不
你看看这段程序怎么样?我自己写的。
#include <reg51.h>
#define KEY P1
//按键码,按键之间按位或运算
#define KEY1 0x11
#define KEY2 0x12
#define KEY3 0x14
#define KEY4 0x18
#define KEY5 0x21
#define KEY6 0x22
#define KEY7 0x24
#define KEY8 0x28
#define KEY9 0x41
#define KEY10 0x42
#define KEY11 0x44
#define KEY12 0x48
#define KEY13 0x81
#define KEY14 0x82
#define KEY15 0x84
#define KEY16 0x88
void Delay10ms(u8 c)//延时10ms
{
u8 a,b;
for( ; c>0; c--)
for(b=38; b>0; b--)
for(a=130; a>0; a--);
}
u8 GetKeyboard()//获取矩阵键盘按键值,支持多按键
{
u8 key,i;
key = 0xFF;
for(i=KEY_Delay; i>0; i--)//按键延时 KEY_Delay*10ms
{
KEY = 0x0F;
if(KEY == 0x0F) break;
if(KEY != (key & 0x0F))
{
Delay10ms(1);//消抖
if(KEY != (key & 0x0F))
key &= (KEY | 0xF0);
}
KEY = 0xF0;
if(KEY == 0xF0) break;
if(KEY != (key & 0xF0))
{
Delay10ms(1);//消抖
if(KEY != (key & 0xF0))
key &= (KEY | 0x0F);
}
Delay10ms(1);
}
return (~key);
}
本于技术交流原则。请不要用该代码用于商业用途
你这个不是多键值的问题,应该算是多键同时按下的问题,这种情况通常当作按键动作异常处理,是认为当前按键无效的
