如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?
作者:卡卷网发布时间:2024-11-30 16:08浏览数量:111次评论数量:0次
矩阵键盘本质:
矩阵键盘本质是使用8个IO口来进行16个按键的控制读取,可以减小IO口的使用,用4条I/O线作为行线,4条I/O线作为列线组成的键盘。在行线和列线的每个交叉点上,设置一个按键。而这样的按键中按键的个数是4 X 4个。
这样的行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。节约单片机的资源,其本质和独立按键类似,就是进行逐行扫描和逐列扫描,然后判断是第几行的第几列的按键,进而进行整体按键值得确定。
具体实物图如下:
矩阵键盘扫描的方式有两种: 1.行列扫描,2.逐行/逐列扫描
行列扫描:适用于8个IO口接到了单片机8个连续的IO口,可以使用行列扫描
逐行/逐列扫描:适用于矩阵键盘接到了任意的IO口,则使用逐行,逐列扫描
本文主要说明逐行扫描的方式
逐行/列扫描:
逐行,逐列扫描的本质和行列扫描比较类似,本质是给某一行/某一列,低电平,其余七个全部为高电平,这时候读取电平变换,有电平变低表示按键按下,即可读取按键数据。
逐行扫描:
- 置第1行为低电平,其余N-1行和N列为高电平,
- 读取列线数据,列线有低电平表示此行有按键按下,比如按下的是1行三列(1x3),那么第三列的列线IO口就为低电平。
- 置第2行为低电平,其余N-1行和N列为高电平,,读取列线数据,列线有低电平表示此行有按键按下。
- 以此类推,进行逐行扫描。
- 根据行线列线的电平不同可以识别是否有按键按下,哪一个按键按下,获取按键号。(N) 根据按键号跳转至对应的按键处理程序。
硬件连接
行线与列线:在硬件上,4条行线连接到微控制器的输出引脚,而4条列线连接到微控制器的输入引脚。
按键位置:每个按键位于行线和列线的交叉点上。
GPIO初始化
行线:
通常设置为输出模式,用于向列线发送扫描信号。
扫描信号:
行线的主要功能是向列线发送扫描信号。当某一行线被设置为低电平时,与之相交的列线会被检测(若相对应的按键被按下,列线被检测为低电平)以判断是否有按键被按下。
确定按键行
通过依次将每一行线设置为低电平(可以逐行扫描键盘)。当检测到列线上有低电平时,可以确定被按下的按键位于当前选中的行上。若列线上无低电平,那么将此行线设置为高电平,下一行设置为低电平,进行新一轮按键检测。
列线
设置为输入模式,用于读取按键状态。
读取按键状态
列线的主要功能是读取按键状态。(STM32就靠列线来确认按键状态)当某一行线被选中(设置为低电平)时,微控制器会读取所有列线的电平状态,以判断是否有按键被按下。
注意事项
在实际应用中,还需要考虑去抖处理、中断处理等因素,以确保按键检测的准确性和稳定性。
Cube MX配置GPIO
使用stm32CubeMX软件配置GPIO:
PA0-PA3的配置是一样的(做行线,设置为输出模式)
PA4-PA7的配置是一样的(做列线,设置为输入模式)
有用到OLED模块,故配置SCL,SDA,做通讯线
时钟频率的话,可以选择默认的
配置完GPIO的相关资源后,就可以在Keil5软件里编写功能模块
(代码中用到的Delay模块和OLED模块是外部导入的)
(Delay也可以用HAL库自带的,OLED可以网上找找)
#include <main.h>
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
*/
void GPIOAallset()
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
}
uint8_t MatrixKey(void)
{
uint8_t KeyNumber=0;
GPIOAallset(); //把PA0-PA7全置为高电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); //PA0置0,开始检测第一行
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4));
//当按钮处于被按下的状态的时候,程序一直卡在循环读取按钮的状态,避免多按钮同时按下时读取错误
Delay_ms(10);
KeyNumber=1;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5));
Delay_ms(10);
KeyNumber=2;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6));
Delay_ms(10);
KeyNumber=3;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7));
Delay_ms(10);
KeyNumber=4;
}
GPIOAallset(); //把PA0-PA7全置为高电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); //PA1置0,开始检测第二行
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4));
//当按钮处于被按下的状态的时候,程序一直卡在循环读取按钮的状态,避免多按钮同时按下时读取错误
Delay_ms(10);
KeyNumber=5;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5));
Delay_ms(10);
KeyNumber=6;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6));
Delay_ms(10);
KeyNumber=7;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7));
Delay_ms(10);
KeyNumber=8;
}
GPIOAallset(); //把PA0-PA7全置为高电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); //PA2置0,开始检测第三行
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4));
//当按钮处于被按下的状态的时候,程序一直卡在循环读取按钮的状态,避免多按钮同时按下时读取错误
Delay_ms(10);
KeyNumber=9;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5));
Delay_ms(10);
KeyNumber=10;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6));
Delay_ms(10);
KeyNumber=11;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7));
Delay_ms(10);
KeyNumber=12;
}
GPIOAallset(); //把PA0-PA7全置为高电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); //PA3置0,开始检测第四行
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4));
//当按钮处于被按下的状态的时候,程序一直卡在循环读取按钮的状态,避免多按钮同时按下时读取错误
Delay_ms(10);
KeyNumber=13;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5));
Delay_ms(10);
KeyNumber=14;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6));
Delay_ms(10);
KeyNumber=15;
}
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==0)
{
Delay_ms(10);
while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7));
Delay_ms(10);
KeyNumber=16;
}
return KeyNumber;
}
主函数部分:
while (1)
{
OLED_ShowString(2, 1,"NUM:");
num = MatrixKey();
if(num)
{
OLED_ShowNum(2, 5, num, 2);
}
}
仿真图片:
免责声明:本文由卡卷网编辑并发布,但不代表本站的观点和立场,只提供分享给大家。
相关推荐

你 发表评论:
欢迎