STM32的矩阵键盘扫描及处理

STM32的矩阵键盘扫描及处理

前言

由于最近帮做一个毕业设计需要用到直接输入目标值去控制输出,所以才写这么一个按键处理的程序。对于一个才接触单片机没多久的大学生菜鸟来说,实现毕设里的每一项功能都有一定的挑战。接下来就分享一下我在写这按键扫描及处理中的一些经验吧。
整个工程所需要的输出值可通过键盘任意控制,有一位小数。

一、按键扫描

1.矩阵按键的原理图

矩阵键盘原理图示意图,具体键值根据自己需求设置

这里只是键盘示意图,具体键值需根据自己需求设置

2、按键扫描代码

总体思路:先设置两个初始化函数,KeyPad_Init1()是高四位初始化为下拉输入、低四位为上拉输入(相当于就是给高四位低电平,低四位为高电平);KeyPad_Init2()是高四位初始化为上拉输入、低四位为下拉输入(相当于就是给高四位高电平,低四位为高电平)。程序首先使用KeyPad_Init1(),如果读取低8位引脚不是0x0f,就说明有按键被按下,然后短暂延时消抖后再次检测到低8位引脚不是0x0f,就储存高四位的的值然后进行初始化KeyPad_Init2(),然后又读取低8位引脚不是0x0f,储存其中的低四位的值,然后将高低四位值加起来就对应了一个键值。
在这段扫描程序里面,由于扫描出的键值后面还需要处理,所以只有当有键按下后才返回才是有效的键值,没有按键按下就返回的是个无效值-1,目的是为了对每一次按键按下值进行处理,没有按下就不去处理。

//函数名:扫描函数
//返回值:有效键值或-1
//功能:矩阵按键扫描,返回一个值
short KeyPad_Scan(void)
{
	short num = -1; //保持按键值返回
	
	u16 readvalue = 0;
	u16 re=0;
	u16 re1=0;
	u16 re2=0;
	KeyPad_Init1();					//低4位引脚上拉输入,高4位引脚下拉输入
	readvalue = GPIO_ReadInputData(GPIOA);	//读GPIOA引脚电平
	readvalue &= 0x00ff;				//保留低8位的值(PA7-PA0)
	if(readvalue != 0x000f) 				//高4位引脚有一个被按下
	{
		delay_ms(10);//消抖10ms
		readvalue = GPIO_ReadInputData(GPIOA);	//读GPIOA引脚电平
		if(readvalue != 0x000f)
		{
			re1 = GPIO_ReadInputData(GPIOA);	//再次读取状态
			re1 &= 0x00f0;  				//保留PA4-PA7的值

			KeyPad_Init2();  				//低4位引脚下拉输入,高4位引脚上拉输入
			delay_ms(50);//经我测试,这里延迟50ms反应最快而很少出现不反应的状况
			re2 = GPIO_ReadInputData(GPIOA);	//再次读取状态
			re2 &= 0x000f;				//保留PA0-PA3的值
			
			re=re1|re2;					//相与,就知道哪一行哪一列被按下啦
			
			switch(re)
			{
			case 0x0011: num = 12;break;  
			case 0x0012: num = 8;break;  
			case 0x0014: num = 4;break; 
			case 0x0018: num = 0;break;  
			case 0x0021: num = 13;break;  
			case 0x0022: num = 9;break; 
			case 0x0024: num = 5;break;  
			case 0x0028: num = 1;break;  
			case 0x0041: num = 14;break;  
			case 0x0042: num = 10;break;  
			case 0x0044: num = 6;break;  
			case 0x0048: num = 2;break;  
			case 0x0081: num = 15;break;  
			case 0x0082: num = 11;break;  
			case 0x0084: num = 7;break;  
			case 0x0088: num = 3;break;  
			}
			return num;
		}
	}
	return -1;
}

二、键值处理

1、键值处理代码

在这段程序中我要的是按下【确定】键按下后返回确定键按下前所输入的键值(0-99.9),返回更高的值也行,不过小数点后面只能有一位数。

/****************
//按键值处理函数,返回最后需要的目标值,
返回-1,按键没有按下
返回-2或0,有按键按下,无效可适当延时
返回其他,键值处理后的值
*******************/
float Key_value_processing(void)		
{
	
	float key=0.0;	
	int key_flag = -1;
	static int key2 = 0;		//按键扫描返回值暂存处		
	static u8		key1 = 0;

	static int		Point_flag=0;		//判断‘.’是否按下标志,(Point_flag=2表示按下,Point_flag=1表示按下后进行了一次小数后一位赋值)
	static int		key1_temp = 0;				//缓存key1值
	

				key_flag=KEYPAD_Scan();		//
		 
		 if(-1 == key_flag)			//如果按键没有按下
			{
			 return -1;
			}
		 else if(0 <= key_flag && key_flag <= 9)		//返回数字键,根据小数点是否按下,对数字进行
			{
					key1 = key_flag+key1*10;	//如有多位值,进行累加
					key1_temp = key1;		
				if(2 == Point_flag)
				{
					printf("xiaoshudianhou:%d \r\n",key1);
					OLED_ShowNum(103,16,key1,1,16);
					OLED_Refresh();
					Point_flag	=	1;
				}
				else if(1 == Point_flag)		//点按下
				{
					key1=key_flag;
				}
				else
				{
					printf("shuqian:%d \r\n",key1);
					OLED_ShowNum(63,16,key1,2,16);
					OLED_Refresh();
				}
				return -2;
			}
			/***无效按键**/	
			else if(10 <= key_flag && key_flag <= 13)		//暂时没有用的值,不处理
			{
				printf("无效值::%d \r\n",key_flag);
				return -2;
			}
		 else if(Point == key_flag)		//
			{
			 key2 = key1_temp;
			 Point_flag=2;
			 key1=0;
			 printf("float-----\r\n");
			 OLED_ShowString(83,16,":",16); 
				OLED_Refresh();
				return -2;
			}
		 else if(Sure == key_flag)		//确定键按下后,返回处理好的值
			{
				if(1==Point_flag)
				{
					key = key2 + (float)key1/10.0;
					Point_flag=0;
				}
			 else 
			 {
				 key=key1;
			 }
			 printf(":%f \r\n",key);
			 key_flag = -1,key1 = 0,key2 = 0;
			 return key;
			}	
			return -1;
}	

三、总结

学习这个专业来第一次对自己所学的知识进行总结,虽然是一个做完后看起来很简单的一个知识点,在键值处理的过程中还是遇到了很多的问题。多亏了学长的帮忙才算比较轻松的完成了。这其中发现了自己以前很多的盲点,比如对于数据类型把握得不是很清楚,还有就是if else语句与if if语句的使用,在这之前写有关单片机的代码都是只用if语句,没考虑到当有多个条件时可以用if else语句可以有更快地执行效率。

相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页