【星云 Orbit-F4 开发板】03g. 按键玩法七:矩阵键盘单个触发
引言
矩阵键盘是一种常见的输入设备,广泛应用于各种嵌入式系统中。通过矩阵键盘,用户可以通过按键输入字符或控制信号。本文将详细介绍如何使用STM32F407的GPIO引脚实现矩阵键盘的单个触发功能。通过本教程,读者将能够掌握矩阵键盘的基本原理以及如何通过HAL库实现单个触发的检测。
硬件准备
在开始编程之前,确保您已经准备好以下硬件:
- STM32F407开发板:板载STM32F407VGT6(Cortex-M4/168MHz)作为主控芯片。
- 矩阵键盘模块:4x4矩阵键盘模块。
- 连接线:用于连接矩阵键盘和开发板。
- 限流电阻:若干个220Ω至330Ω的电阻,用于保护电路。
硬件连接
将矩阵键盘连接到STM32F407的GPIO引脚:
-
连接矩阵键盘的行引脚:
- 将矩阵键盘的行引脚(通常标记为R0-R3)连接到STM32F407的PB0-PB3引脚。
-
连接矩阵键盘的列引脚:
- 将矩阵键盘的列引脚(通常标记为C0-C3)连接到STM32F407的PC0-PC3引脚。
-
连接地线:
- 将矩阵键盘的地线连接到STM32F407的GND引脚。
GPIO配置
在STM32F407中,GPIO引脚可以配置为多种模式,以适应不同的应用需求。以下是一些常见的GPIO模式:
-
输入模式:
- 浮空输入(Floating Input):引脚处于高阻态,适用于不需要上拉或下拉的情况。
- 上拉输入(Pull-Up Input):引脚内部连接上拉电阻,适用于外部信号为低电平有效的情况。
- 下拉输入(Pull-Down Input):引脚内部连接下拉电阻,适用于外部信号为高电平有效的情况。
-
输出模式:
- 推挽输出(Push-Pull Output):引脚可以输出高电平或低电平,适用于直接驱动小电流负载,如LED灯。
- 开漏输出(Open-Drain Output):引脚输出低电平或高阻态,适用于需要外部上拉电阻的场合。
在本教程中,我们将矩阵键盘的行引脚配置为推挽输出模式,列引脚配置为上拉输入模式。
配置GPIO时钟:
在使用GPIO引脚之前,需要先使能相应的GPIO时钟。对于PB0-PB3引脚,需要使能GPIOB时钟;对于PC0-PC3引脚,需要使能GPIOC时钟。
// 使能GPIOB时钟
__HAL_RCC_GPIOB_CLK_ENABLE();// 使能GPIOC时钟
__HAL_RCC_GPIOC_CLK_ENABLE();
配置GPIO引脚:
使用GPIO_InitTypeDef
结构体配置GPIO引脚的模式、上下拉、速度等参数。
GPIO_InitTypeDef GPIO_InitStruct = {0};// 配置PB0-PB3为推挽输出模式
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);// 配置PC0-PC3为上拉输入模式
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
按键扫描模块
为了实现模块化设计,我们将按键的扫描功能封装到bsp/KEY
目录下的bsp_key.c
和bsp_key.h
文件中。
1. 创建KEY
目录
-
打开文件管理器:
- 导航到STM32F407项目目录下的
Drivers/BSP
文件夹。
- 导航到STM32F407项目目录下的
-
创建新目录:
- 右键点击空白区域,选择
新建文件夹
。 - 输入目录名称
KEY
,并按回车键确认。
- 右键点击空白区域,选择
2. 创建bsp_key.c
和bsp_key.h
文件
- 确保
bsp_key.c
和bsp_key.h
文件当前位于Drivers/BSP/KEY
目录下。
3. 更新项目包含路径
-
打开Keil MDK:
- 加载当前的STM32F407项目。
-
进入项目设置:
- 右键点击工程名称,选择
Options for Target
。
- 右键点击工程名称,选择
-
添加新的包含路径:
- 在弹出的窗口中,选择
C/C++
选项卡。 - 在
Include Paths
字段中,添加以下路径:Drivers/BSP/KEY
- 确保路径正确无误,点击
OK
保存设置。
- 在弹出的窗口中,选择
4. 更新main.c
文件
-
打开
main.c
文件:- 在Keil MDK的项目资源管理器中,找到并双击
main.c
文件。
- 在Keil MDK的项目资源管理器中,找到并双击
-
包含新的头文件:
- 在文件顶部,添加以下包含语句:
#include "bsp_key.h"
- 确保路径正确,以便编译器能够找到该头文件。
- 在文件顶部,添加以下包含语句:
5. 重新编译项目
-
编译工程:
- 点击工具栏中的
Build
按钮(或按F7
键)。 - 确保编译过程中没有错误和警告。
- 点击工具栏中的
-
处理编译错误:
- 如果出现包含路径错误,请检查
Include Paths
设置是否正确。 - 确保
bsp_key.h
文件位于Drivers/BSP/KEY
目录下。
- 如果出现包含路径错误,请检查
6. 更新项目分组
-
添加新的文件夹分组:
- 在Keil MDK的项目资源管理器中,右键点击
BSP
分组,选择Add Group
。 - 输入分组名称
KEY
,点击OK
。
- 在Keil MDK的项目资源管理器中,右键点击
-
添加文件到分组:
- 右键点击新的
KEY
分组,选择Add New Item to Group
。 - 选择
Add Existing File
,导航到Drivers/BSP/KEY
目录,选择bsp_key.c
和bsp_key.h
文件,点击OK
。
- 右键点击新的
-
确保文件可见性:
- 确保
bsp_key.c
和bsp_key.h
文件在KEY
分组下可见,并且路径正确。
- 确保
按键扫描模块实现
bsp_key.h
文件
#ifndef __BSP_KEY_H
#define __BSP_KEY_H#include "stm32f4xx_hal.h"#define ROWS 4 // 矩阵键盘的行数
#define COLS 4 // 矩阵键盘的列数/*** @brief 初始化矩阵键盘*/
void KEY_Init(void);/*** @brief 扫描矩阵键盘并检测按键状态* @return 按键状态(0:未按下,1-16:按键编号)*/
uint8_t KEY_Scan(void);#endif /* __BSP_KEY_H */
bsp_key.c
文件
#include "bsp_key.h"static uint8_t key_state = 0;/*** @brief 初始化矩阵键盘*/
void KEY_Init(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};// 使能GPIOB和GPIOC时钟__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();// 配置PB0-PB3为推挽输出模式GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);// 配置PC0-PC3为上拉输入模式GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLUP;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}/*** @brief 扫描矩阵键盘并检测按键状态* @return 按键状态(0:未按下,1-16:按键编号)*/
uint8_t KEY_Scan(void) {static uint8_t row = 0;static uint8_t col = 0;static uint8_t key_pressed = 0;if (key_pressed) {// 检测按键是否释放if (HAL_GPIO_ReadPin(GPIOC, C0_Pin) == GPIO_PIN_SET &&HAL_GPIO_ReadPin(GPIOC, C1_Pin) == GPIO_PIN_SET &&HAL_GPIO_ReadPin(GPIOC, C2_Pin) == GPIO_PIN_SET &&HAL_GPIO_ReadPin(GPIOC, C3_Pin) == GPIO_PIN_SET) {key_pressed = 0;}return 0;}// 扫描行for (row = 0; row < ROWS; row++) {// 激活当前行switch (row) {case 0:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);break;case 1:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);break;case 2:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);break;case 3:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_RESET);break;}// 检测列for (col = 0; col < COLS; col++) {if (HAL_GPIO_ReadPin(GPIOC, (GPIO_PinTypeDef)(GPIO_PIN_0 << col)) == GPIO_PIN_RESET) {// 按键按下key_pressed = 1;return (row * COLS) + col + 1;}}// 禁用当前行switch (row) {case 0:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);break;case 1:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);break;case 2:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);break;case 3:HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, GPIO_PIN_SET);break;}}return 0;
}
主程序实现
#include "stm32f4xx_hal.h"
#include "bsp_key.h"int main(void) {// 系统初始化HAL_Init();SystemClock_Config();// 按键初始化KEY_Init();while (1) {// 扫描按键状态uint8_t key = KEY_Scan();if (key != 0) {// 按键按下,执行相应操作// 在此处添加按键处理代码// 例如,控制LED灯或播放声音}}
}
测试与验证
-
编译与下载:
- 将代码编译并下载到STM32F407开发板中。
-
观察按键状态:
- 连接好硬件后,按下矩阵键盘上的按键,观察是否能够正确检测按键按下事件。如果按键状态没有正确检测,请检查硬件连接和代码配置是否正确。
-
验证单个触发:
- 按下按键,确保每次按下只触发一次响应。如果触发不正常,请检查按键扫描逻辑以及相关处理代码。
总结
通过本教程,您已经掌握了如何使用STM32F407的GPIO引脚实现矩阵键盘的单个触发功能。矩阵键盘的扫描逻辑是关键步骤,选择合适的行和列配置以及扫描逻辑可以确保按键的稳定工作。模块化设计使代码更加清晰和易于维护,为后续的项目扩展奠定了良好的基础。希望本教程对您有所帮助,祝您在嵌入式开发的道路上取得更大的成功!