[应用方案] 单片机接矩阵键盘原理

[复制链接]
948|2
 楼主| dentsgot 发表于 2016-1-28 09:04 | 显示全部楼层 |阅读模式
单片机与矩阵键盘连接如下图:                    
矩阵键盘工作原理:由于按键没有接地,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个键一起按键,程序也有先后检测的顺序,只能检测一个后面的检测不到。

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)



 楼主| dentsgot 发表于 2016-1-28 09:06 | 显示全部楼层
  1. #include

  2. #define uint unsigned int

  3. #define uchar unsigned char

  4. sbit dula = P2^6;

  5. sbit wela = P2^7;

  6. sbit key1= P3^4;

  7. uchar code table []={

  8. 0x3f,0x06,0x5b,0x4f,
  9. 0x66,0x6d,0x7d,0x07,
  10. 0x7f,0x6f,0x77,0x7c,
  11. 0x39,0x5e,0x79,0x71,

  12. 0//加这个0就是什么都不显示

  13. };

  14. uchar num,temp,num1;

  15. void delay(uint z)
  16. {
  17. uint x,y;
  18. for(x=z;x>0;x--)
  19.   for(y=110;y>0;y--);
  20. }

  21. uchar keyscan();//声明一下

  22. //void display(uchar num1);//这里可以做个显示函数,但是我没做。

  23. void main(){

  24.      num = 17;//让它显示0 什么都不显示。 因为函数返回num值

  25.      dula =1 ;

  26.      P0= 0;

  27.      dula =0;

  28.      wela = 1;

  29.      P0= 0xc0;

  30.      wela = 0;



  31.      //以上P0口控制数码管的一上电什么都不显示

  32.    while(1){

  33.                num1 = keyscan();//没按下返回17

  34.                dula =1;

  35.                P0= table[num1-1];//17-1 =16

  36.                dula = 0;

  37.               }



  38. }

  39. //用uchar keyscan() 带返回值的函数 代替整个矩阵键盘  当然显示就不要了 dula  那3行我注释掉了

  40. uchar keyscan(){

  41.         P3= 0xfe; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

  42.        temp =P3;//读回来了

  43.        temp &= 0xf0;//因为我们只是读回来高4位

  44.        while (temp != 0xf0){ //下面的几个while循环判断可以用if好理解。只看到第一行就行了。

  45.                         //这几个while 都是做判断用的

  46.             delay(5);//消除抖动的

  47.             temp=P3;

  48.             temp &= 0xf0;

  49.           while(temp != 0xf0){ //确实不等于0xf0有按键按下

  50.              temp = P3;//我们这个时候只是把P3口的值赋给了temp

  51.              switch (temp){ //检测P3口。

  52.                   case 0xee:

  53.                       num = 1;

  54.                       break;

  55.                  case 0xde:

  56.                      num=2;

  57.                      break;

  58.                  case 0xbe:

  59.                      num=3;

  60.                      break;

  61.                  case 0x7e:

  62.                     num=4;

  63.                     break;

  64.         

  65.              }

  66.               while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测

  67.                 {

  68.                    temp = P3;

  69.                    temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

  70.                         

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

  72.      

  73.         //到这里是把第一行检测了。

  74.         }

  75.      }

  76. //////以下下是其他几行检测的代码

  77.        P3= 0xfd; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

  78.        temp =P3;//读回来了

  79.        temp &= 0xf0;//因为我们只是读回来高4位

  80.        while (temp != 0xf0){

  81.             delay(5);//消除抖动的

  82.             temp=P3;

  83.             temp &= 0xf0;

  84.           while(temp != 0xf0){ //确实不等于0xf0有按键按下

  85.              temp = P3;//我们这个时候只是把P3口的值赋给了temp

  86.              switch (temp){ //检测P3口。

  87.                   case 0xed:

  88.                       num = 5;

  89.                       break;

  90.                  case 0xdd:

  91.                      num=6;

  92.                      break;

  93.                  case 0xbd:

  94.                      num=7;

  95.                      break;

  96.                  case 0x7d:

  97.                     num=8;

  98.                     break;

  99.         

  100.              }

  101.             while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测

  102.                 {

  103.                    temp = P3;

  104.                    temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

  105.                         

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

  107.      

  108.         //到这里是把第2行检测了。

  109.         }

  110.      }

  111.        P3= 0xfb; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

  112.        temp =P3;//读回来了

  113.        temp &= 0xf0;//因为我们只是读回来高4位

  114.        while (temp != 0xf0){

  115.             delay(5);//消除抖动的

  116.             temp=P3;

  117.             temp &= 0xf0;

  118.           while(temp != 0xf0){ //确实不等于0xf0有按键按下

  119.              temp = P3;//我们这个时候只是把P3口的值赋给了temp

  120.              switch (temp){ //检测P3口。

  121.                   case 0xeb:

  122.                       num =9;

  123.                       break;

  124.                  case 0xdb:

  125.                      num=10;

  126.                      break;

  127.                  case 0xbb:

  128.                      num=11;

  129.                      break;

  130.                  case 0x7b:

  131.                     num=12;

  132.                     break;

  133.         

  134.              }

  135.             while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测

  136.                 {

  137.                    temp = P3;

  138.                    temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

  139.                         

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

  141.      

  142.         //到这里是把第3行检测了。

  143.         }

  144.      }

  145.        P3= 0xf7; //高4位是f 等于写了1 1 1 1 也满足了先写1的要求

  146.        temp =P3;//读回来了

  147.        temp &= 0xf0;//因为我们只是读回来高4位

  148.        while (temp != 0xf0){

  149.             delay(5);//消除抖动的

  150.             temp=P3;

  151.             temp &= 0xf0;

  152.           while(temp != 0xf0){ //确实不等于0xf0有按键按下

  153.              temp = P3;//我们这个时候只是把P3口的值赋给了temp

  154.              switch (temp){ //检测P3口。

  155.                   case 0xe7:

  156.                       num =13 ;

  157.                       break;

  158.                  case 0xd7:

  159.                      num=14;

  160.                      break;

  161.                  case 0xb7:

  162.                      num=15;

  163.                      break;

  164.                  case 0x77:

  165.                     num=16;

  166.                     break;

  167.         

  168.              }

  169.             while(temp != 0xf0)//有按键按下可能是不等于的   循环在这里面  松手检测

  170.                 {

  171.                    temp = P3;

  172.                    temp = temp & 0xf0; //这个是松手检测  松手这里就等于了0xf0

  173.                         

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

  175.      

  176.         //到这里是把第4行检测了。

  177.         }

  178.      }

  179. return  num; //其实键盘扫描就需要一个值。

  180. }
芙蓉洞 发表于 2016-1-29 15:21 | 显示全部楼层
这个程序里面感觉没有加入去抖功能
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

164

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部