矩阵按键_单片机_普中

1 矩阵按键介绍

  4*4矩阵按键,又称行列式键盘,它用4条I/O线作为行线,它用4条I/O线作为列线组成键盘。在行线和列线的每一个交叉点上设置一个按键,这样键盘按键就有4*4个,这种行列式键盘结构能够有效的提高单片机系统的I/O口利用率。

矩阵按键_单片机_普中

 

2 功能要求:通过数码管显示矩阵按键S1-S16按下后键值0-F。

3 硬件设计

3.1 系统框图

矩阵按键_单片机_普中

3.2 矩阵按键和数码管电路

矩阵按键_单片机_普中  矩阵按键_单片机_普中矩阵按键_单片机_普中

4 软件设计

4.1 行列式扫描法

即逐行扫描:通过高四位轮流输出低电平来对矩阵按键进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接受到的数据是哪一位为0来判断是哪一个按键被按下。

矩阵按键_单片机_普中
 1 #include "reg52.h"
 2 
 3 typedef unsigned int             u16;
 4 typedef unsigned char    u8;
 5 
 6 #define KEY_MATRIX_PORT     P1          //矩阵按键控制端口
 7 #define SMG_SEG_PORT        P0        //数码管段选控制端口
 8 
 9 u8 gsmg_code[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
10                 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  //0-F的字形码,共阴型数码管
11 
12 //延时函数,ten_us=1时,大约延时10us
13 void delay_10us(u16 ten_us)
14 {
15      while(ten_us--);
16 }
17 
18 //矩阵按键扫描函数,采用行列式扫描法,监测按键是否按下,返回对应值
19 u8 key_matrix_ranks_scan(void)
20 {
21       u8 key_value=0;        //存储按键值
22 
23     //从第一列开始,监测第1、2、3、4行,是否有按键按下
24     KEY_MATRIX_PORT=0xf7;    //0B1111_0111,给第一列赋值0,其余为1
25     if(KEY_MATRIX_PORT!=0xf7)    //判断第一列是否按键按下
26     {
27          delay_10us(1000);        //延时10ms,滤除按下抖动区域
28         switch(KEY_MATRIX_PORT)        //返回第一列按键按下后的键值
29         {
30             case 0x77: key_value=1;break; //0B0111_0111
31             case 0xb7: key_value=5;break; //0B1011_0111
32             case 0xd7: key_value=9;break; //0B1101_0111
33             case 0xe7: key_value=13;break; //0B1110_0111
34         }
35     }
36     while(KEY_MATRIX_PORT!=0xf7);      //等待按键松开
37 
38      
39     //从第二列开始,监测第1、2、3、4行,是否有按键按下
40        KEY_MATRIX_PORT=0xfb;    //0B1111_1011,给第二列赋值0,其余为1
41     if(KEY_MATRIX_PORT!=0xfb)    //判断第二列是否按键按下
42     {
43          delay_10us(1000);        //延时10ms,滤除按下抖动区域
44         switch(KEY_MATRIX_PORT)        //返回第二列按键按下后的键值
45         {
46             case 0x7b: key_value=2;break; //0B0111_1011
47             case 0xbb: key_value=6;break; //0B1011_1011
48             case 0xdb: key_value=10;break; //0B1101_1011
49             case 0xeb: key_value=14;break; //0B1110_1011
50         }
51     }
52     while(KEY_MATRIX_PORT!=0xfb);      //等待按键松开
53 
54     //从第三列开始,监测第1、2、3、4行,是否有按键按下
55     KEY_MATRIX_PORT=0xfd;    //0B1111_1101,给第三列赋值0,其余为1
56     if(KEY_MATRIX_PORT!=0xfd)    //判断第三列是否按键按下
57     {
58          delay_10us(1000);        //延时10ms,滤除按下抖动区域
59         switch(KEY_MATRIX_PORT)        //返回第三列按键按下后的键值
60         {
61             case 0x7d: key_value=3;break;     //0B0111_1101
62             case 0xbd: key_value=7;break;     //0B1011_1101
63             case 0xdd: key_value=11;break;     //0B1101_1101
64             case 0xed: key_value=15;break;     //0B1110_1101
65         }
66     }
67     while(KEY_MATRIX_PORT!=0xfd);      //等待按键松开
68 
69 
70     //从第四列开始,监测第1、2、3、4行,是否有按键按下
71     KEY_MATRIX_PORT=0xfe;        //0B1111_1110,给第一列赋值0,其余为1
72     if(KEY_MATRIX_PORT!=0xfe)    //判断第四列是否按键按下
73     {
74          delay_10us(1000);        //延时10ms,滤除按下抖动区域
75         switch(KEY_MATRIX_PORT)        //返回第四列按键按下后的键值
76         {
77             case 0x7e: key_value=4;break; //0B0111_0111
78             case 0xbe: key_value=8;break; //0B1011_0111
79             case 0xde: key_value=12;break; //0B1101_0111
80             case 0xee: key_value=16;break; //0B1110_0111
81         }
82     }
83     while(KEY_MATRIX_PORT!=0xfe);      //等待按键松开
84 
85     return key_value;
86 }
87 
88 void main()
89 {
90      u8 key=0;
91     while(1)
92     {
93          key=key_matrix_ranks_scan();
94         if(key!=0)
95             SMG_SEG_PORT=gsmg_code[key-1];
96     }
97 }    
key4x4.c

4.2 线翻转法

行列扫描:通过高四位全部输出低电平,低四位输出高电平。当接受到的数据,低四位不全为高电平时,说明有按键按下,然后通过接受的数据值,判断是按一列按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是哪一行有按键按下,这样就能够确定是哪一个按键按下了。

矩阵按键_单片机_普中
 1 #include "reg52.h"
 2 
 3 typedef unsigned int     u16;
 4 typedef unsigned char    u8;
 5 
 6 #define KEY_MATRIX_PORT     P1          //矩阵按键控制端口
 7 #define SMG_SEG_PORT        P0        //数码管段选控制端口
 8 
 9 u8 gsmg_code[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
10                 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  //0-F的字形码,共阴型数码管
11 
12 //延时函数,ten_us=1时,大约延时10us
13 void delay_10us(u16 ten_us)
14 {
15      while(ten_us--);
16 }
17 
18 //矩阵按键扫描函数,采用线翻转扫描方法
19 u8 key_matrix_flip_scan(void)
20 {
21       static u8 key_value=0;        //存储按键值
22     KEY_MATRIX_PORT=0x0f;         //给所有行赋值0,列全为1,即0b0000_1111
23     if(KEY_MATRIX_PORT!=0x0f)      //判断按键是否按下
24     {
25          delay_10us(1000);         //消抖
26         if(KEY_MATRIX_PORT!=0x0f)
27         {
28              //测试列
29             KEY_MATRIX_PORT=0x0f;         //0b0000_1111
30             switch(KEY_MATRIX_PORT)
31             {
32                 case 0x07: key_value=1;break;  //监测到第1列有按键按下
33                 case 0x0b: key_value=2;break;  //监测到第2列有按键按下
34                 case 0x0d: key_value=3;break;  //监测到第3列有按键按下
35                 case 0x0e: key_value=4;break;  //监测到第4列有按键按下
36             }
37 
38             //测试行
39             KEY_MATRIX_PORT=0xf0;         //1111_0000
40             switch(KEY_MATRIX_PORT)
41             {
42                 case 0x70: key_value=key_value;break;          //监测到第1行有按键按下
43                 case 0xb0: key_value=key_value+4;break;      //监测到第2行有按键按下
44                 case 0xd0: key_value=key_value+8;break;      //监测到第3行有按键按下
45                 case 0xe0: key_value=key_value+12;break;      //监测到第4行有按键按下
46             }
47             while(KEY_MATRIX_PORT!=0xf0);
48         }
49     }
50     else 
51         key_value=0;
52     return key_value;
53 }
54 
55 void main()
56 {
57      u8 key=0;
58     while(1)
59     {
60          key=key_matrix_flip_scan();
61         if(key!=0)
62             SMG_SEG_PORT=gsmg_code[key-1];
63     }
64 }
key4x4_flip.c

5 实验现象:当按下S1-S16键,数码管对应显示0-F。

参考资料

(1)(79条消息) 51单片机(V51)———独立按键、4x4矩阵按键_正弦定理的博客-CSDN博客

 

上一篇:LeetCode-最大正方形-动态规划


下一篇:【C语言经典100例】 -- 27 利用递归函数调用方式,将所输入的5个字符,以相反顺序打印出来。