找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 11756|回复: 2
打印 上一主题 下一主题
收起左侧

单片机接矩阵键盘原理

[复制链接]
跳转到指定楼层
楼主
ID:59284 发表于 2014-2-26 19:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
由于按键没有接地,4行  4列正好占用8个I/O  如果4行我们送 P3.0到P3.3送入0 1 1 1 然后去读取 4列的值,如果P3.0的按键按下那么P3.4---P3.7的值等于 0 1 1 1,假如是第2个键按下的话那么读回来的值是 1 0 1 1 ,如果第3个键按下去读回来的值是 1 1 0 1 ,如果第4个键按下去读回来的值是 1 1 1 0 ,如果没有键按下去读回来就是1 1 1 1。  所以我们就根据读回来的值来判断按下去的是那个键。当然这是对P3.0这一行,因为矩阵键盘是扫描的,所以下次把P3.0 给1  P3.1 给0对第2行,陆续的第3 行第4行, 0111 1011 1101 1110  而每次都去从新扫描一遍列值列有4个值,以确定是那个键按下。无论何时任何一个时间有一个按键被按下就跳出循环。当然不可能有2个键刚好一起按下你的手没有这么好的力度,就算有2个键一起按键,程序也有先后检测的顺序,只能检测一个后面的检测不到。


用P1 口 P1.0---P1.3 接4行   P1.4--P1.7 接4列

P3 = 0XFE; //第一行给0
temp ;定义个变量
temp = P3 ;读回来  由于读需要先写1  因为P3= FE  已经把高4位给1了  所以能读了
temp & oxf0   如果没有按键按下结果还是0xf0 .如果有键按下结果就不是0xf0了。
num   然后我们再定义一个变量 让它赋值给这个按下去的按键值。
一次类推把第一行赋值0 扫描一遍 然后把第2行赋值0扫描一遍..............共扫描16遍。
只要有键按下 就会得到一个值 num 就从1排到16. 共16个按键 4*4 的矩阵键盘。

我再总结下思路:
首先 低4位是行 共4行  分别把每行给0 低电平   就4次 0 1 1 1 、1 0 1 1 、 1 1 0 1 、1 1 1 0 对吧
然后去检测高4位  4列啊 先不考虑极端情况,4列就4个按键只要按下一个 P3口的高4位就会有一个值。根据这个值就能判断是那个键了。
如:P3= 1111 1110   低四位是行先把第一行给0

有按键下的话 temp = P3 读回来  1101 1110 然后temp &  0xf0  与运算下就判断下还等于oxf0吗?如还等于就没有按下,如果不等于就肯定有按键按下。定义个变量让它等于这个不是0XF0的值,做个标记。依次类推。
然后用这个思路写个程序吧!写的不太好看的不是很清楚只是做个参考吧,只要把思路理清楚就行了。
是这样我们分别按这16个按键让它分别显示是第几个 比如 按下第一个数码管就显示1 第2个数码管就显示2,依次类推。一直到 F  (为了方便让所有的数码管显示同一个数0---F)
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula = P2^6;
sbit wela = P2^7;
sbit key1= P3^4;
uchar code table []={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0//加这个0就是什么都不显示
};
uchar num,temp,num1;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
  for(y=110;y>0;y--);
}
uchar keyscan();//声明一下
//void display(uchar num1);//这里可以做个显示函数,但是我没做。
void main(){
     num = 17;//让它显示0 什么都不显示。 因为函数返回num值
     dula =1 ;
     P0= 0;
     dula =0;
     wela = 1;
     P0= 0xc0;
     wela = 0;

     //以上P0口控制数码管的一上电什么都不显示
   while(1){
               num1 = keyscan();//没按下返回17
               dula =1;
               P0= table[num1-1];//17-1 =16
               dula = 0;
              }

}
//用uchar keyscan() 带返回值的函数 代替整个矩阵键盘  当然显示就不要了 dula  那3行我注释掉了
uchar keyscan(){
        P3= 0xfe; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求
       temp =P3;//读回来了
       temp &= 0xf0;//因为我们只是读回来高4位
       while (temp != 0xf0){ //下面的几个while循环判断可以用if好理解。只看到第一行就行了。
                        //这几个while 都是做判断用的
            delay(5);//消除抖动的
            temp=P3;
            temp &= 0xf0;
          while(temp != 0xf0){ //确实不等于0xf0有按键按下
             temp = P3;//我们这个时候只是把P3口的值赋给了temp
             switch (temp){ //检测P3口。
                  case 0xee:
                      num = 1;
                      break;
                 case 0xde:
                     num=2;
                     break;
                 case 0xbe:
                     num=3;
                     break;
                 case 0x7e:
                    num=4;
                    break;

             }
              while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测
                {
                   temp = P3;
                   temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

                }//下面就显示一下  退出整个一行的循环,不加松手检测会退不出去循环

        //到这里是把第一行检测了。
        }
     }
//////以下下是其他几行检测的代码
       P3= 0xfd; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求
       temp =P3;//读回来了
       temp &= 0xf0;//因为我们只是读回来高4位
       while (temp != 0xf0){
            delay(5);//消除抖动的
            temp=P3;
            temp &= 0xf0;
          while(temp != 0xf0){ //确实不等于0xf0有按键按下
             temp = P3;//我们这个时候只是把P3口的值赋给了temp
             switch (temp){ //检测P3口。
                  case 0xed:
                      num = 5;
                      break;
                 case 0xdd:
                     num=6;
                     break;
                 case 0xbd:
                     num=7;
                     break;
                 case 0x7d:
                    num=8;
                    break;

             }
            while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测
                {
                   temp = P3;
                   temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

                }//下面就显示一下  退出整个2行的循环。不加松手检测会退不出去循环

        //到这里是把第2行检测了。
        }
     }
       P3= 0xfb; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求
       temp =P3;//读回来了
       temp &= 0xf0;//因为我们只是读回来高4位
       while (temp != 0xf0){
            delay(5);//消除抖动的
            temp=P3;
            temp &= 0xf0;
          while(temp != 0xf0){ //确实不等于0xf0有按键按下
             temp = P3;//我们这个时候只是把P3口的值赋给了temp
             switch (temp){ //检测P3口。
                  case 0xeb:
                      num =9;
                      break;
                 case 0xdb:
                     num=10;
                     break;
                 case 0xbb:
                     num=11;
                     break;
                 case 0x7b:
                    num=12;
                    break;

             }
            while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测
                {
                   temp = P3;
                   temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

                }//下面就显示一下  退出整个3行的循环。  不加松手检测会退不出去循环     

        //到这里是把第3行检测了。
        }
     }
       P3= 0xf7; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求
       temp =P3;//读回来了
       temp &= 0xf0;//因为我们只是读回来高4位
       while (temp != 0xf0){
            delay(5);//消除抖动的
            temp=P3;
            temp &= 0xf0;
          while(temp != 0xf0){ //确实不等于0xf0有按键按下
             temp = P3;//我们这个时候只是把P3口的值赋给了temp
             switch (temp){ //检测P3口。
                  case 0xe7:
                      num =13 ;
                      break;
                 case 0xd7:
                     num=14;
                     break;
                 case 0xb7:
                     num=15;
                     break;
                 case 0x77:
                    num=16;
                    break;

             }
            while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测
                {
                   temp = P3;
                   temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

                }//下面就显示一下  退出整个4行循环。不加松手检测会退不出去循环

        //到这里是把第4行检测了。
        }
     }
return  num; //其实键盘扫描就需要一个值。
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:61875 发表于 2014-7-12 07:26 | 只看该作者
楼主辛苦好资料拜读了。
回复

使用道具 举报

板凳
ID:64075 发表于 2014-9-16 10:54 | 只看该作者
thanks fr your share
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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