1 矩阵键盘的结构

下图是一个4*3的矩阵键盘示意图,三条列线连接P1.4-P1.6引脚。四条行线连接P1.0-P1.3引脚
在这里插入图片描述

2 逐行逐列扫描法

首先使三条列线所连接的I/O引脚P14-P16输出低电平,四条行线所连接的I/O引脚P10-P13输出高电平。当没有按键按下时,四条行线所连接的I/O引脚读取到的将全部是高电平;而当有按键按下时,由于该按键所在的行线与列线接通,行线将被下拉到低电平。此时读取行线所连接的引脚P10-P13,将不再全是高电平,由此可以判断出有按键按下。判断有按键按下后,还要用逐行逐列扫描法来获取按键的键值。

逐行逐列扫描法的原理是:逐列将列线依次置低电平,读取行线,如果某一条行线为低电平,则说明该行线与当前置为低电平的列线交叉点处的按键被按下,从而可以获取按键的键值。

    #define keyboard P1  //四条行线三条列线所连接的IO口
	unsigned char Check_Keyboard()
	{
	unsigned char row_scan_code=0x01; //行扫描码
	unsigned char col_scan_code=0xEF;//列扫描码
	unsigned char keycode;  //按键键值
	unsigned char i,x,j;
	//可以做一个消抖处理
	for(i=0;i<3;i++)//逐列扫描,将列线逐列拉低
	{
		keycode=i+1;
		keyboard=col_scan_code;
		x=keyboard; //读取行线状态
		for(j=0;j<4;j++)//逐行扫描
		{
			if(!(x&row_scan_code))//说明对应行的按键按下,使行线被拉低
			{
				keycode+=3*j;
				//如果按键还未释放,则仍有行线被拉至低电平
				while((keyboard&0x0f)!=0x0f);//等待按键释放
				P1=0x0F;     //恢复原状态,为下次按键做准备
				return keycode;     //已检测到按键键码,返回
			}
			else
				row_scan_code=_crol_(row_scan_code,1);
		}
		col_scan_code=_crol_(col_scan_code,1);//左移一位,将下一列线拉低
		row_scan_code=0x01;//重置行扫描码,为下一行扫描作准备
	}
	keycode=0;//没有按键按下,键值记为0
	return keycode;
	}

3 线反法

上面逐行逐列扫描法较为繁琐,在实际的单片机系统中更常用的是线反法。
在这里插入图片描述
线反法的原理为:首先使P1口的高四位输出高电平,P1口低四位输出低电平,这时键盘的行线被拉高,列线被拉低。如果有按键按下,则某一条行线将被拉低,此时读取P1口高四位,读取到的将不再全为高电平,说明有按键按下。(在判断是否有按键按下这一点上,线反法与逐行逐列扫描法是一致的)根据读取到0值的I/O口所连接的行线,就可以判断出按下的按键位于哪一行。接下来使P1口的高四位输出低电平,P1口低四位输出高电平(即与上次输出的电平相反,因此称为线反法)。如果有按键按下,此时读取P1口低四位,读取到的将不再全为高电平,根据读取到0值的I/O口所连接的列线,就可以判断出按下的按键位于哪一列。综合按键所在的行线与列线,即可唯一确定按键所在位置,进而获取按键的键值。

//@brief:判断4*4矩阵键盘是否有键可靠按下,高4位口接行线,低四位口接列线
//@retval:当有键可靠按下时返回1-16的键值,否则返回0
#define keyboard P1
unsigned char Check_Keydown()
{
	unsigned char KeyValue=0;
	keyboard=0x0f;
	if(keyboard!=0x0f)//如果按键按下
	{
		delay_ms(10);//延时10ms消抖
		if(keyboard!=0x0f)//按键确实按下
		{	
			//判断按键所在列,以所在列的第一行的按键键值赋给KeyValue
			keyboard=0X0F;
			switch(keyboard)
			{
				case(0X07):	KeyValue=1;break; //第一列按下
				case(0X0b):	KeyValue=2;break; //第二列按下
				case(0X0d): KeyValue=3;break; //第三列按下
				case(0X0e):	KeyValue=4;break; //第四列按下
			}
			//判断按键所在行
			keyboard=0XF0;
			switch(keyboard)
			{
				case(0X70):	KeyValue=KeyValue;break;  //第一行按下
				case(0Xb0):	KeyValue=KeyValue+4;break;  //第二行按下
				case(0Xd0): KeyValue=KeyValue+8;break;  //第三行按下
				case(0Xe0):	KeyValue=KeyValue+12;break;  //第四行按下
			}
			while(keyboard!=0xf0); //按键松手后退出
				return KeyValue;
		}
		else  //否则认为是信号干扰导致
		{
			return 0;  //认为没有按键按下
		}
	}
	return 0;  //如果没有按键按下返回零
}
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐