IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32矩阵按键扫描冲突问题 -> 正文阅读

[嵌入式]STM32矩阵按键扫描冲突问题

最近做了一个项目,有个部分用到了矩阵扫描的原理,要检测按键是否按下去执行一个动作。一开始硬件工程师的原理图实现是设计成传统矩阵按键方式,大致原理如下所示:
在这里插入图片描述
这种硬件实现方式当去检测单个按下、一整行按下或一整列按下时是没有问题,但是我们同时按下s0、s1和s4的时候,问题就来了。在这里插入图片描述
当我们按下s0和s1的时候相应的第一行就会导通,结合列的上拉电阻便可检测出s0和s1按键被按下。但是!!!当我们s4按下时第二行也被导通了,并且随着s1按键的按下,第二列也是被导通。所以当我们按下s0、s1和s4按键时,s5按键就会被误检测成被按下,所以这是错误的。经过不懈的努力和查阅相关资料,对以上的电路进行了修改。
在这里插入图片描述
在每一个按键前面加上一个二极管进行阻隔,使得各按键不受列电流的影响,有了电路原理,代码按键扫描检测就简单多了。
先对按键GPIO进行定义,方便后续编写代码。

KEY ROW/
#define KEY_ROW_APB2PERIPH                (RCC_APB2Periph_GPIOA)
#define KEY_ROW_PORT                       GPIOA
#define KEY_ROW1_PIN                      GPIO_Pin_10
#define KEY_ROW2_PIN                      GPIO_Pin_11
#define KEY_ROW3_PIN                      GPIO_Pin_12
#define KEY_ROW4_PIN                      GPIO_Pin_15

KEY COL
#define KEY_COL_APB2PERIPH                (RCC_APB2Periph_GPIOB)
#define KEY_COL_PORT                       GPIOB
#define KEY_COL1_PIN                      GPIO_Pin_3
#define KEY_COL2_PIN                      GPIO_Pin_4
#define KEY_COL3_PIN                      GPIO_Pin_5
#define KEY_COL4_PIN                      GPIO_Pin_6

typedef struct gpio_group {
	GPIO_TypeDef *port;
	uint16_t pin;	
} GPIO_GROUP;

检测流程大致思路:将行的四个引脚作为输出引脚设置成开漏输出,列引脚直接设置成浮空状态。将输出引脚轮流拉低去再去检测每个按键输入引脚的状态。就是说,先将ROW1输出为0,然后当ROW1的某个按键被按下时,浮空引脚便会跟着被拉低就可以检测到输入引脚的高低电平。

static GPIO_GROUP GPIO_LKEY_ROW[4] = {
	{KEY_ROW_PORT, KEY_ROW1_PIN},
	{KEY_ROW_PORT, KEY_ROW2_PIN},
	{KEY_ROW_PORT, KEY_ROW3_PIN},
	{KEY_ROW_PORT, KEY_ROW4_PIN},
};

static GPIO_GROUP GPIO_KEY_COL[4] = {
	{KEY_COL_PORT, KEY_COL1_PIN},
	{KEY_COL_PORT, KEY_COL2_PIN},
	{KEY_COL_PORT, KEY_COL3_PIN},
	{KEY_COL_PORT, KEY_COL4_PIN},
};
/*******************初始化引脚***********************************/
void KEY_Init(void)
{
	//KEY ROW
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(KEY_ROW_APB2PERIPH,ENABLE);
	GPIO_InitStructure.GPIO_Pin = KEY_ROW1_PIN | KEY_ROW2_PIN |
	                              KEY_ROW3_PIN | KEY_ROW4_PIN ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;          
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(KEY_ROW_PORT, &GPIO_InitStructure);   
	
	//KEY COL
	RCC_APB2PeriphClockCmd(KEY_COL_APB2PERIPH,ENABLE);
	GPIO_InitStructure.GPIO_Pin = KEY_COL1_PIN | KEY_COL2_PIN|
	                              KEY_COL3_PIN | KEY_COL4_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(KEY_COL_PORT, &GPIO_InitStructure);                              
}
/*******************控制行输出电压***********************************/
//controller all row
static void activate_all_row(uint8_t status)
{
	int row;
	for (row = 0; row < 4; row++) 
	{
		if (status) 
		{
			GPIO_SetBits(GPIO_LKEY_ROW[row].port, GPIO_LKEY_ROW[row].pin);
		} 
		else 
		{
			GPIO_ResetBits(GPIO_LKEY_ROW[row].port, GPIO_LKEY_ROW[row].pin);
		}
	}
}

//controller  row
static void activate_row(uint8_t row, uint8_t status)
{
	if (status) 
	{
		GPIO_SetBits(GPIO_LKEY_ROW[row].port, GPIO_LKEY_ROW[row].pin);
	} 
	else 
	{
		GPIO_ResetBits(GPIO_LKEY_ROW[row].port, GPIO_LKEY_ROW[row].pin);
	}
}
/********************按键扫描***********************************/
void KEY_Scan(void)
{
	uint8_t row, col,keyScan[4][4]={0};
	activate_all_row(1)
	for(row = 0;row < 4; row ++)
	{
		activate_row(row, 0);
		delay_US(1);
		
		for(col = 0;col < 4;col ++)
		{
			if(GPIO_ReadInputDataBit(GPIO_KEY_COL[col].port,GPIO_KEY_COL[col].pin) == 0)
				keyScan[row][col] = 1;
		}
		activate_row(row, 1);
	}
	activate_all_row(1)
	for(row = 0;row < 4;row ++)
		for(col = 0;col < 4;col ++)
		{
			if(keyScan[row][col] != 0)
			printf("第%d个按键被按下\r\n",(row+1)*(col+1));
		}
}

以上就是矩阵按键扫描的整个思路流程,代码因为是博客上临时修改写的,不知道能不能编译通过,但是思路就是这么个思路,如果有大佬有更好的解决方案也可一起讨论。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:40:08  更:2021-08-01 14:40:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:22:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码