独闷闷网

 找回密码
 立即注册
搜索
查看: 4030|回复: 2
打印 上一主题 下一主题
收起左侧

[原创] 矩阵按键的翻转法识别原理是什么样的?鸿哥除了惊叹它的巧妙外还有什么担忧?已解答。

[复制链接]
跳转到指定楼层
楼主
发表于 2015-2-1 21:27:56 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
本帖最后由 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-茂名:
以下是我看到的第三种按键方法:
  1. uchar Keys_Scan()
  2. {        
  3.     uchar X,Y,Z;
  4.         P1=0xf0; //先对P3置数 行扫描
  5.    if(P1!=0xf0) //判断是否有键按下
  6.    {
  7.         delayms(200); //延时,软件去干扰
  8.          if(P1!=0xf0) //确认按键按下X = P3;
  9.     {
  10.                 X=P1&0xf0; //保存行扫描时有键按下时状态
  11.                 P1=0x0f; //列扫描
  12.                 Y=P1&0x0f; //保存列扫描时有键按下时状态
  13.                 Z=X|Y; //取出键        
  14.                 /*****将按键值用10进制表示***/
  15.                 switch(Z)
  16.                 {
  17.                   case 0xe7: keynum=0;break;
  18.                   case 0xeb: keynum=1;break;
  19.                   case 0xed: keynum=2;break;
  20.                   case 0xee: keynum=3;break;
  21.                   case 0xd7: keynum=4;break;
  22.                   case 0xdb: keynum=5;break;
  23.                   case 0xdd: keynum=6;break;
  24.                   case 0xde: keynum=7;break;
  25.                   case 0xb7: keynum=8;break;
  26.                   case 0xbb: keynum=9;break;
  27.                   case 0xbd: keynum=10;break;
  28.                   case 0xbe: keynum=11;break;
  29.                   case 0x77: keynum=12;break;
  30.                   case 0x7b: keynum=13;break;
  31.                   case 0x7d: keynum=14;break;
  32.                   case 0x7e: keynum=15;break;
  33.                 }               
  34.    return keynum;
  35.    }
  36.    }
  37. }
复制代码


鸿哥-深圳:
这个不是第三种,这个就是翻转法。

yuor self-茂名:
所以我说就是你们刚才讨论的那种咯

鸿哥-深圳:
对。





乐于分享,勇于质疑!
沙发
发表于 2015-2-1 22:00:25 | 只看该作者
沙发
乐于分享,勇于质疑!
回复

使用道具 举报

板凳
发表于 2015-2-2 01:06:13 | 只看该作者
本帖最后由 f晨星 于 2015-2-2 01:10 编辑

我给第一段代码加上注释  有不对的请指出

//其中的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;          //  xxxx  0000  或 0000 xxxx  取出其中按下的
                }
        }        
        return tm2 ;
}
乐于分享,勇于质疑!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )

GMT+8, 2024-4-21 00:34 , Processed in 0.360524 second(s), 19 queries .

快速回复 返回顶部 返回列表