51单片机学习记录(五)矩阵按键

1、矩阵按键的控制原理

独立按键与单片机连接时, 每一个按键都需要单片机的一个 I/O 口, 若某单片机系统需较多按键, 如果用独立按键便会占用过多的 I/O 口资源。 单片机系统中 I/O 口资源往往比较宝贵, 当用到多个按键时为了减少 I/O 口引脚, 引入了矩阵按键。

本开发板上的矩阵按键原理图如下所示:

在这里插入图片描述
可以看到是将16个按键排成4行4列,前面的四行分别连接io口的每一行,后面的四行分别连接io口的每一列,这样就实现了每个io口都连接四个按键,同样通过这样的方式也可以实现3X3,5X5等这样的布局。

那么在检测的时候又是如何实现的呢,这种按键的检测一般是通过扫描来实现的,先使能某一列列为低电平,其余几列全为高电平,之后立即轮流检测一次每行是不是有低电平,如果没有的话,就说明这一行没有按键被按下,如果有低电平,则可以说明该行有被按下的按键,这样的话就通过行列来锁定了按键的位置,这个列的低电平使能也是在轮流进行的,通过这样的方式就可以实现按键的检测了。

2、矩阵按键实现

1、行列式法实现矩阵按键

首先来看下矩阵按键的定义,如下所示:
在这里插入图片描述
下面以第一步的操作为例,首先给我们对应的io口进行赋值,这里赋值为0XF7,就是1111 0111,第一列全都赋值为0,其余的全为1:
在这里插入图片描述
之后在检测第第一行有没有按键被按下,如果有按键被按下应该是下面几种情况,将这几种情况一一进行枚举,结果如下所示:
在这里插入图片描述
下面第二行
在这里插入图片描述
下面第三行
在这里插入图片描述
下面第四行
在这里插入图片描述
在程序中体现出来就是下面的代码部分了:
在这里插入图片描述
完整的代码如下所示:(注:本处代码来自普中科技51单片机例程

u8 key_matrix_ranks_scan(void) //行列式扫描实现矩阵按键检测
{
    
    
	u8 key_value=0;

	KEY_MATRIX_PORT=0xf7;//给第一列赋值0,其余全为1
	if(KEY_MATRIX_PORT!=0xf7)//判断第一列按键是否按下
	{
    
    
		delay_100ms();//消抖
		switch(KEY_MATRIX_PORT)//保存第一列按键按下后的键值	
		{
    
    
			case 0x77: key_value=1;break;
			case 0xb7: key_value=5;break;
			case 0xd7: key_value=9;break;
			case 0xe7: key_value=13;break;
		}
	}
	while(KEY_MATRIX_PORT!=0xf7);//等待按键松开	
	
	KEY_MATRIX_PORT=0xfb;//给第二列赋值0,其余全为1
	if(KEY_MATRIX_PORT!=0xfb)//判断第二列按键是否按下
	{
    
    
		delay_100ms();//消抖
		switch(KEY_MATRIX_PORT)//保存第二列按键按下后的键值	
		{
    
    
			case 0x7b: key_value=2;break;
			case 0xbb: key_value=6;break;
			case 0xdb: key_value=10;break;
			case 0xeb: key_value=14;break;
		}
	}
	while(KEY_MATRIX_PORT!=0xfb);//等待按键松开	
	
	KEY_MATRIX_PORT=0xfd;//给第三列赋值0,其余全为1
	if(KEY_MATRIX_PORT!=0xfd)//判断第三列按键是否按下
	{
    
    
		delay_100ms();//消抖
		switch(KEY_MATRIX_PORT)//保存第三列按键按下后的键值	
		{
    
    
			case 0x7d: key_value=3;break;
			case 0xbd: key_value=7;break;
			case 0xdd: key_value=11;break;
			case 0xed: key_value=15;break;
		}
	}
	while(KEY_MATRIX_PORT!=0xfd);//等待按键松开	
	
	KEY_MATRIX_PORT=0xfe;//给第四列赋值0,其余全为1
	if(KEY_MATRIX_PORT!=0xfe)//判断第四列按键是否按下
	{
    
    
		delay_100ms();//消抖
		switch(KEY_MATRIX_PORT)//保存第四列按键按下后的键值	
		{
    
    
			case 0x7e: key_value=4;break;
			case 0xbe: key_value=8;break;
			case 0xde: key_value=12;break;
			case 0xee: key_value=16;break;
		}
	}
	while(KEY_MATRIX_PORT!=0xfe);//等待按键松开
	
	return key_value;		
}

2、线翻转法实现矩阵按键

线翻转法实现的流程为首先使所有行线为低电平时, 之后检测所有列线是否有低电平, 如果有, 就记录列线值; 然后再翻转, 使所有列线都为低电平, 检测所有行线的值,由于有按键按下, 行线的值也会有变化, 记录行线的值。 从而就可以检测到全部按键。

线翻转法的具体实现流程为:
在这里插入图片描述
完整的代码如下所示:(注:本处代码来自普中科技51单片机例程

u8 key_matrix_flip_scan(void) //线翻转法实现矩阵按键
{
    
    
	static u8 key_value=0;

	KEY_MATRIX_PORT=0x0f;//给所有行赋值0,列全为1
	if(KEY_MATRIX_PORT!=0x0f)//判断按键是否按下
	{
    
    
		delay_100ms();//消抖
		if(KEY_MATRIX_PORT!=0x0f)
		{
    
    
			//测试列
			KEY_MATRIX_PORT=0x0f;
			switch(KEY_MATRIX_PORT)//保存行为0,按键按下后的列值	
			{
    
    
				case 0x07: key_value=1;break;
				case 0x0b: key_value=2;break;
				case 0x0d: key_value=3;break;
				case 0x0e: key_value=4;break;
			}
			//测试行
			KEY_MATRIX_PORT=0xf0;
			switch(KEY_MATRIX_PORT)//保存列为0,按键按下后的键值	
			{
    
    
				case 0x70: key_value=key_value;break;
				case 0xb0: key_value=key_value+4;break;
				case 0xd0: key_value=key_value+8;break;
				case 0xe0: key_value=key_value+12;break;
			}
			while(KEY_MATRIX_PORT!=0xf0);//等待按键松开	
		}
	}
	else
		key_value=0;		
	
	return key_value;		
}

3、按键实战

利用之前的串口函数来进行实现按键打印,代码如下:
在这里插入图片描述
将程序下载到开发板,可以看到如下现象
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_51220742/article/details/125031295