矩阵按键

采用矩阵按键的好处是:使用最少的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];
	}
}

 

posted @ 2018-01-26 00:23  半生戎马,共话桑麻、  阅读(1309)  评论(0)    收藏  举报
levels of contents