矩阵按键的翻转法识别原理是什么样的?鸿哥除了惊叹它的巧妙外还有什么担忧?已解答。
本帖最后由 jianhong_wu 于 2016-7-17 14:30 编辑MCU编程-华力:
这是我从别处看到的一种新型的矩阵按键翻转识别法:
鸿哥-深圳:
我刚刚仔细看了你上面矩阵按键翻转法的检测思路,确实非常巧妙,识别按键的速度比传统的矩阵按键识别要快。先搁置上述程序中有个delay_ms(5)延时去抖不议,它跟传统的矩阵按键识别原理有以下区别:
(1)传统的矩阵按键识别,固定是4个IO口输出,4个IO口输入,所以只需要输入口接4个上拉电阻就可以。
(2)翻转的矩阵按键识别,没有固定谁是输出谁是输入,它们是分时切换两种状态的:当前面4个IO是输出时,后面4个IO就是输入。反之,当前面4个IO是输入时,后面4个IO就是输出。只需要知道前面4个IO口哪个是低电平,再结合后面4个IO口哪个是低电平就可以快速识别到哪个按键被按下。所以需要8个上拉电阻。
鸿哥在惊叹如此巧妙的翻转识别方法的同时,也有以下一点小担忧:
如果用翻转法,如果是PIC,AVR,STM32等单片机,它们的IO口不是准双向口,除了必须用8个上拉电阻之外,还意味着每次翻转IO口状态时,就要及时设置IO口寄存器来设置它的输入输出方向,每次切换的时候,往往需要插入几个指令的空延时然后再读取,但是最让我担忧的是,如此频繁的在输入口和输出口之间切换,会不会影响单片机的寿命?会不会影响系统的稳定性?这个是我有点担忧的,这种担忧只是来自我个人的一种感觉。所以在实际做项目的时候,我个人还是喜欢坚持选用传统的矩阵按键扫描方式。
yuor self-茂名:
以下是我看到的第三种按键方法:
uchar Keys_Scan()
{
uchar X,Y,Z;
P1=0xf0; //先对P3置数 行扫描
if(P1!=0xf0) //判断是否有键按下
{
delayms(200); //延时,软件去干扰
if(P1!=0xf0) //确认按键按下X = P3;
{
X=P1&0xf0; //保存行扫描时有键按下时状态
P1=0x0f; //列扫描
Y=P1&0x0f; //保存列扫描时有键按下时状态
Z=X|Y; //取出键
/*****将按键值用10进制表示***/
switch(Z)
{
case 0xe7: keynum=0;break;
case 0xeb: keynum=1;break;
case 0xed: keynum=2;break;
case 0xee: keynum=3;break;
case 0xd7: keynum=4;break;
case 0xdb: keynum=5;break;
case 0xdd: keynum=6;break;
case 0xde: keynum=7;break;
case 0xb7: keynum=8;break;
case 0xbb: keynum=9;break;
case 0xbd: keynum=10;break;
case 0xbe: keynum=11;break;
case 0x77: keynum=12;break;
case 0x7b: keynum=13;break;
case 0x7d: keynum=14;break;
case 0x7e: keynum=15;break;
}
return keynum;
}
}
}
鸿哥-深圳:
这个不是第三种,这个就是翻转法。
yuor self-茂名:
所以我说就是你们刚才讨论的那种咯
鸿哥-深圳:
对。
沙发:lol:lol 本帖最后由 f晨星 于 2015-2-2 01:10 编辑
我给第一段代码加上注释:lol有不对的请指出
//其中的DATA是一组IO口
u8 keyscan()
{
u8 tm , tm2;
DATA = 0XOF; // 输出值为0000 1111
tm = DATA; // 读回DATA的实际值保持(我觉得这一句可以省去)
if(DATA != 0X0F) //发现有按键按下时,这时DATA 不在是0000 1111 而是0000 xxxx\\\解释看下面
{
dalay_ms(5);
tm = DATA; //读回DATA的实际值保存现在的DATA值,,可能是0000 xxxx
// 其中值可能是 0000 0111\\0000 1011\\\0000 1101\\\0000 1110
if(DATA != 0X0F)// 再次判读是否真的按下
{
tm2 = tm & 0x0f; // 去除高4位中的变化值 tm2= 0000 xxxx
//为什么不吧tm直接赋值给tm2呢..是防止高四位中出现1的状况,屏蔽掉高4位可能出现的1
DATA = 0xf0; //DATA输出1111 0000 因为被按下 DATA读回来实际值是xxxx 0000\\x中其中一个是0 同上的解释
tm = DATA; //读回DATA的实际值保存 因为被按下 DATA读回来的实际实际值是xxxx 0000\\x中其中一个是0 同上的解释
tm2|=tm; //xxxx0000或 0000 xxxx取出其中按下的
}
}
return tm2 ;
}
页:
[1]