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博客;