STM32的矩阵键盘扫描及处理

    科技2022-07-13  128

    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语句可以有更快地执行效率。

    Processed: 0.015, SQL: 8