【星云 Orbit-F4 开发板】03g. 按键玩法七:矩阵键盘单个触发

ops/2025/2/27 13:22:19/

【星云 Orbit-F4 开发板】03g. 按键玩法七:矩阵键盘单个触发


引言

矩阵键盘是一种常见的输入设备,广泛应用于各种嵌入式系统中。通过矩阵键盘,用户可以通过按键输入字符或控制信号。本文将详细介绍如何使用STM32F407的GPIO引脚实现矩阵键盘的单个触发功能。通过本教程,读者将能够掌握矩阵键盘的基本原理以及如何通过HAL库实现单个触发的检测。


硬件准备

在开始编程之前,确保您已经准备好以下硬件:

  1. STM32F407开发板:板载STM32F407VGT6(Cortex-M4/168MHz)作为主控芯片。
  2. 矩阵键盘模块:4x4矩阵键盘模块。
  3. 连接线:用于连接矩阵键盘和开发板。
  4. 限流电阻:若干个220Ω至330Ω的电阻,用于保护电路。

硬件连接

矩阵键盘连接到STM32F407的GPIO引脚:

  1. 连接矩阵键盘的行引脚

    • 矩阵键盘的行引脚(通常标记为R0-R3)连接到STM32F407的PB0-PB3引脚。
  2. 连接矩阵键盘的列引脚

    • 矩阵键盘的列引脚(通常标记为C0-C3)连接到STM32F407的PC0-PC3引脚。
  3. 连接地线

    • 矩阵键盘的地线连接到STM32F407的GND引脚。

GPIO配置

在STM32F407中,GPIO引脚可以配置为多种模式,以适应不同的应用需求。以下是一些常见的GPIO模式:

  1. 输入模式

    • 浮空输入(Floating Input):引脚处于高阻态,适用于不需要上拉或下拉的情况。
    • 上拉输入(Pull-Up Input):引脚内部连接上拉电阻,适用于外部信号为低电平有效的情况。
    • 下拉输入(Pull-Down Input):引脚内部连接下拉电阻,适用于外部信号为高电平有效的情况。
  2. 输出模式

    • 推挽输出(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.cbsp_key.h文件中。

1. 创建KEY目录

  1. 打开文件管理器

    • 导航到STM32F407项目目录下的Drivers/BSP文件夹。
  2. 创建新目录

    • 右键点击空白区域,选择新建文件夹
    • 输入目录名称KEY,并按回车键确认。

2. 创建bsp_key.cbsp_key.h文件

  • 确保bsp_key.cbsp_key.h文件当前位于Drivers/BSP/KEY目录下。

3. 更新项目包含路径

  1. 打开Keil MDK

    • 加载当前的STM32F407项目。
  2. 进入项目设置

    • 右键点击工程名称,选择Options for Target
  3. 添加新的包含路径

    • 在弹出的窗口中,选择C/C++选项卡。
    • Include Paths字段中,添加以下路径:
      Drivers/BSP/KEY
      
    • 确保路径正确无误,点击OK保存设置。

4. 更新main.c文件

  1. 打开main.c文件

    • 在Keil MDK的项目资源管理器中,找到并双击main.c文件。
  2. 包含新的头文件

    • 在文件顶部,添加以下包含语句:
      #include "bsp_key.h"
      
    • 确保路径正确,以便编译器能够找到该头文件。

5. 重新编译项目

  1. 编译工程

    • 点击工具栏中的Build按钮(或按F7键)。
    • 确保编译过程中没有错误和警告。
  2. 处理编译错误

    • 如果出现包含路径错误,请检查Include Paths设置是否正确。
    • 确保bsp_key.h文件位于Drivers/BSP/KEY目录下。

6. 更新项目分组

  1. 添加新的文件夹分组

    • 在Keil MDK的项目资源管理器中,右键点击BSP分组,选择Add Group
    • 输入分组名称KEY,点击OK
  2. 添加文件到分组

    • 右键点击新的KEY分组,选择Add New Item to Group
    • 选择Add Existing File,导航到Drivers/BSP/KEY目录,选择bsp_key.cbsp_key.h文件,点击OK
  3. 确保文件可见性

    • 确保bsp_key.cbsp_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灯或播放声音}}
}

测试与验证

  1. 编译与下载

    • 将代码编译并下载到STM32F407开发板中。
  2. 观察按键状态

    • 连接好硬件后,按下矩阵键盘上的按键,观察是否能够正确检测按键按下事件。如果按键状态没有正确检测,请检查硬件连接和代码配置是否正确。
  3. 验证单个触发

    • 按下按键,确保每次按下只触发一次响应。如果触发不正常,请检查按键扫描逻辑以及相关处理代码。

总结

通过本教程,您已经掌握了如何使用STM32F407的GPIO引脚实现矩阵键盘的单个触发功能。矩阵键盘的扫描逻辑是关键步骤,选择合适的行和列配置以及扫描逻辑可以确保按键的稳定工作。模块化设计使代码更加清晰和易于维护,为后续的项目扩展奠定了良好的基础。希望本教程对您有所帮助,祝您在嵌入式开发的道路上取得更大的成功!


http://www.ppmy.cn/ops/161682.html

相关文章

【Triton 教程】triton.heuristics

Triton 是一种用于并行编程的语言和编译器。它旨在提供一个基于 Python 的编程环境&#xff0c;以高效编写自定义 DNN 计算内核&#xff0c;并能够在现代 GPU 硬件上以最大吞吐量运行。 更多 Triton 中文文档可访问 →https://triton.hyper.ai/ triton.heuristics(values)用于…

青少年编程与数学 02-010 C++程序设计基础 12课题、输入输出

青少年编程与数学 02-010 C程序设计基础 12课题、输入输出 一、输入输出1. 控制台输入输出1.1 标准输入&#xff08;std::cin&#xff09;读取单个字符读取字符串读取数值读取多行字符串 1.2 标准输出&#xff08;std::cout&#xff09;输出单个字符输出字符串输出数值格式化输…

http 协议和 https 协议的区别在哪里?【详情解答】

HTTP&#xff08;超文本传输协议&#xff09;和HTTPS&#xff08;超文本传输安全协议&#xff09;都是用于在网络上传输数据的协议&#xff0c;二者存在多方面的区别&#xff0c;具体如下&#xff1a; 安全性&#xff1a;这是HTTP和HTTPS最主要的区别。HTTP协议是明文传输数据…

从头再来!社招找工作——算法题复习十:双指针/前缀和/滑动窗口

从头再来&#xff01;社招找工作——算法题复习十&#xff1a;双指针/前缀和/滑动窗口 双指针/前缀和/滑动窗口双指针判断是否为回文字符串&#xff08;Easy&#xff09;盛水最多的容器&#xff08;Middle&#xff09; 前缀和数组的平均数值&#xff08;Easy&#xff09;除自身…

Origin 2024绘图与数据分析下载|附安装包+学习教程

如大家所了解的&#xff0c;Origin是一款图形可视化和数据分析软件&#xff0c;它是为初学者提供了使用的界面&#xff0c;并且随着用户对应用程序的日益熟还可以执行高等自定义。软件具有大量2D和3D绘图模板。 Origin主要应用&#xff1a; 绘图 凭借100多种内置和扩展的图表…

[AI概念域] AI 大模型是如何被训练出来的?(通俗解读)

说明&#xff1a;这里使用 学生成长五部曲 比喻带你理解大模型如何从零开始学会思考。 AI大模型的训练过程可分为四个核心阶段&#xff1a; 首先进行海量数据收集与清洗&#xff0c;如同为“学生”准备涵盖各领域知识的教材库&#xff1b;接着通过预训练让模型完成“填空题”…

DeepSeek教unity------UI框架

/****************************************************文件&#xff1a;BasePanel.cs作者&#xff1a;Edision日期&#xff1a;#CreateTime#功能&#xff1a;面板基类 *****************************************************/using UnityEngine;public class BasePanel : Mo…

AI DEV 人工智能能做的工作,在开发运维安全方面以及企业成本降低方面所起的作用和相应的提示词。

这个查询是用中文提出的&#xff0c;询问人工智能在开发、运维、安全方面以及企业成本降低方面的作用和相应的提示词。我应该用中文回答&#xff0c;并涵盖以下几个方面&#xff1a; AI在软件开发中的应用AI在IT运维中的应用AI在网络安全中的应用AI如何帮助企业降低成本针对这…