矩阵按键
采用矩阵按键的好处是:使用最少的IO口来控制更多的按键,比如计算器上有很多按键,就可以采用矩阵按键来实现,
如果采用独立按键实现,就会提高很多的IO口
实验:矩阵按键S1-S16共16个按键,按下各个按键,数码管分别显示数字
S1-S4:0-3、S5-S8:4-7、S9-S12:8-B、S13-S16:C-F
效果:
比如:按下S5时,显示:
比如:按下S13时,显示:
其他的按键也可以正常显示对应的数字或字母。
keil代码:
/************************************************************************************** * 矩阵按键实验 * 实现现象:下载程序后数码管显示0,按下矩阵按键上的按键显示对应的数字 S1-S4:0-3 S5-S8:4-7 S9-S12:8-B S13-S16:C-F。 注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。 ***************************************************************************************/ #include <reg52.h> #define u16 unsigned int #define u8 unsigned char #define GPIO_DIG P0 // 数码管要显示的数字的IO口 #define GPIO_KEY P1 // 矩阵按键的IO口 // 数码管的那个LED灯亮 sbit LSA = P2^2; sbit LSB = P2^3; sbit LSC = P2^4; u8 keyValue; // 用来存放读取到的键值,这个值就是数字数组的下表,通过它可以获取对应的数字 // 数码管数字数组 u8 code smgduan[17]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; //显示0-F的值 // 延迟函数 void delay(u16 time) { while(time--); } /******************************************************************************* * 函 数 名 : KeyDown * 函数功能 : 检测有按键按下并读取键值 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ void keyDown(void) { // 按键松手检测变量 u8 a = 0; // 高四位(P17-P14)为低电平0,低四位(P13-P10)为高电平1,即00001111,转换成十六进制就是0x0f GPIO_KEY = 0x0f; // 如果有按键按下,不管是哪个按键按下,根据矩阵按键的原理图可知,低四位P13-P10中一定有低电平出现 if(GPIO_KEY != 0x0f) // 表示有按键按下了 { delay(1000); // 消抖 if(GPIO_KEY != 0x0f) // 再判断是否真有按键按下:表示真有按键按下了 { // 按照行列扫描的原理 // 测试列 GPIO_KEY = 0x0f; switch(GPIO_KEY) { case(0x07): keyValue=0; break; // 按下S1那一列(包括S1、S5、S9、S13) case(0x0b): keyValue=1; break; // 按下S2那一列(包括S2、S6、S10、S14) case(0x0d): keyValue=2; break; // 按下S3那一列(包括S3、S7、S11、S15) case(0x0e): keyValue=3; break; // 按下S4那一列(包括S4、S8、S12、S16) } // 测试行 GPIO_KEY = 0xf0; switch(GPIO_KEY) { case(0x70): keyValue=keyValue; break; // 按下S1那一行(包括S1、S2、S3、S4) case(0xb0): keyValue=keyValue+4; break; // 按下S5那一行(包括S5、S6、S7、S8) case(0xd0): keyValue=keyValue+8; break; // 按下S9那一行(包括S9、S10、S11、S12) case(0xe0): keyValue=keyValue+12; break; // 按下S13那一行(包括S13、S14、S15、S16) } //按键松手检测,设置变量a是为了节约CPU资源 while((a<50) && (GPIO_KEY!=0xf0)) { delay(1000); a++; } } } } //主函数 void main() { // 给一个数码管提供位选 LSA = 0; LSB = 0; LSC = 0; // 数码管LED1 while(1) { // 按键判断函数,会设置全局变量(成员变量)keyValue的值,把这个返回值当成是数字数组的下表 keyDown(); GPIO_DIG = smgduan[keyValue]; } }