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语句可以有更快地执行效率。
本文档详细介绍了如何在STM32单片机上实现矩阵键盘的扫描和处理,包括初始化函数、按键扫描算法以及键值处理。在键值处理中,实现了对输入数字的处理,确保小数点后只有一位。通过按键扫描函数,检测到按键按下后返回相应的键值,未按下时返回-1。此外,还分享了在编程过程中遇到的问题和解决方案,强调了ifelse语句在提高代码执行效率上的作用。
3688

被折叠的 条评论
为什么被折叠?



