【星云 Orbit-F4 开发板】03a. 按键玩法一:独立按键定时中断扫描法

server/2025/2/26 11:12:36/

【星云 Orbit-F4 开发板】03b. 按键玩法一:独立按键中断扫描法

概述

本教程基于STM32F407 HAL库,实现模块化的定时中断按键扫描功能,采用去抖动算法与自锁机制确保稳定检测。代码分为按键模块、蜂鸣器模块、定时器模块及主程序,结构清晰,便于移植扩展。


目录结构

Project/  
├── Inc/  
│   ├── key.h          // 按键模块头文件  
│   ├── beep.h         // 蜂鸣器模块头文件  
│   ├── timer.h        // 定时器模块头文件  
├── Src/  
│   ├── key.c          // 按键模块实现  
│   ├── beep.c         // 蜂鸣器模块实现  
│   ├── timer.c        // 定时器模块实现  
│   ├── main.c         // 主程序  

模块化代码实现

1. 按键模块 (key.h/key.c)

功能:封装按键初始化与扫描逻辑,支持多按键独立检测。

// key.h
#ifndef __KEY_H
#define __KEY_H#include "stm32f4xx_hal.h"#define KEY_NUM         2       // 按键数量
#define DEBOUNCE_TIME   20      // 去抖动时间阈值(单位:ms)// 按键结构体
typedef struct {GPIO_TypeDef *port;         // GPIO端口uint16_t pin;               // GPIO引脚uint8_t is_pressed;         // 当前按键状态(1:按下, 0:释放)uint8_t lock;               // 自锁标志uint16_t debounce_cnt;      // 去抖动计数器
} Key_TypeDef;// 全局按键数组声明(在key.c中定义)
extern Key_TypeDef keys[KEY_NUM];void KEY_Init(void);            // 按键初始化
void KEY_Scan(void);            // 按键扫描(需在定时中断中调用)#endif
// key.c
#include "key.h"// 定义两个按键的硬件配置
Key_TypeDef keys[KEY_NUM] = {{GPIOA, GPIO_PIN_0, 0, 0, 0}, // Key1: PA0(下拉输入){GPIOA, GPIO_PIN_1, 0, 0, 0}  // Key2: PA1(下拉输入)
};// 按键初始化
void KEY_Init(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};// 使能GPIOA时钟__HAL_RCC_GPIOA_CLK_ENABLE();// 配置按键引脚为下拉输入GPIO_InitStruct.Pin = keys[0].pin | keys[1].pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_PULLDOWN;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}// 按键扫描函数(需在1ms定时中断中调用)
void KEY_Scan(void) {for (uint8_t i = 0; i < KEY_NUM; i++) {uint8_t current_state = HAL_GPIO_ReadPin(keys[i].port, keys[i].pin);if (current_state == GPIO_PIN_SET) { // 检测到高电平(按键按下)if (keys[i].lock == 0) {         // 首次检测到按下keys[i].debounce_cnt++;if (keys[i].debounce_cnt >= DEBOUNCE_TIME) {keys[i].is_pressed = 1;  // 标记按键按下keys[i].lock = 1;        // 自锁,防止重复触发keys[i].debounce_cnt = 0;}}} else { // 按键释放keys[i].lock = 0;keys[i].debounce_cnt = 0;keys[i].is_pressed = 0;         // 清除按下标记}}
}

2. 蜂鸣器模块 (beep.h/beep.c)

功能:控制蜂鸣器鸣叫时间,支持短鸣触发。

// beep.h
#ifndef __BEEP_H
#define __BEEP_H#include "stm32f4xx_hal.h"#define BEEP_PORT       GPIOB
#define BEEP_PIN        GPIO_PIN_0
#define BEEP_SHORT_MS   40      // 短鸣持续时间(ms)void BEEP_Init(void);           // 蜂鸣器初始化
void BEEP_Trigger(uint16_t duration_ms);  // 触发蜂鸣器#endif
// beep.c
#include "beep.h"static volatile uint16_t beep_counter = 0;  // 蜂鸣器计时器// 蜂鸣器初始化
void BEEP_Init(void) {GPIO_InitTypeDef GPIO_InitStruct = {0};// 使能GPIOB时钟__HAL_RCC_GPIOB_CLK_ENABLE();// 配置蜂鸣器引脚为推挽输出GPIO_InitStruct.Pin = BEEP_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(BEEP_PORT, &GPIO_InitStruct);HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET); // 初始关闭
}// 触发蜂鸣器(duration_ms: 持续时间)
void BEEP_Trigger(uint16_t duration_ms) {beep_counter = duration_ms;HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_SET); // 启动蜂鸣器
}// 更新蜂鸣器状态(需在1ms定时中断中调用)
void BEEP_Update(void) {if (beep_counter > 0) {beep_counter--;if (beep_counter == 0) {HAL_GPIO_WritePin(BEEP_PORT, BEEP_PIN, GPIO_PIN_RESET); // 关闭}}
}

3. 定时器模块 (timer.h/timer.c)

功能:配置TIM3定时器,提供1ms中断用于按键扫描与蜂鸣器控制。

// timer.h
#ifndef __TIMER_H
#define __TIMER_H#include "stm32f4xx_hal.h"void TIMER_Init(void);  // 定时器初始化#endif
// timer.c
#include "timer.h"
#include "key.h"
#include "beep.h"TIM_HandleTypeDef htim3;// 定时器初始化
void TIMER_Init(void) {TIM_ClockConfigTypeDef sClockSourceConfig = {0};TIM_MasterConfigTypeDef sMasterConfig = {0};htim3.Instance = TIM3;htim3.Init.Prescaler = 84 - 1;       // 84MHz / 84 = 1MHzhtim3.Init.CounterMode = TIM_COUNTERMODE_UP;htim3.Init.Period = 1000 - 1;       // 1ms中断周期 (1MHz / 1000)htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;HAL_TIM_Base_Init(&htim3);sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);HAL_TIM_Base_Start_IT(&htim3); // 启动定时器中断
}// 定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {if (htim->Instance == TIM3) {KEY_Scan();     // 按键扫描BEEP_Update();  // 更新蜂鸣器状态}
}

4. 主程序 (main.c)

功能:模块初始化与按键服务处理。

#include "main.h"
#include "key.h"
#include "beep.h"
#include "timer.h"int main(void) {HAL_Init();KEY_Init();     // 初始化按键BEEP_Init();    // 初始化蜂鸣器TIMER_Init();   // 初始化定时器while (1) {// 检测按键触发for (uint8_t i = 0; i < KEY_NUM; i++) {if (keys[i].is_pressed) {BEEP_Trigger(BEEP_SHORT_MS); // 触发蜂鸣器keys[i].is_pressed = 0;      // 清除按键状态}}}
}

逻辑详解

  1. 模块化设计

    • 按键模块:封装GPIO配置与扫描逻辑,支持多按键独立检测。
    • 蜂鸣器模块:提供触发接口与状态更新,分离控制逻辑。
    • 定时器模块:统一管理中断,确保1ms精准调度。
  2. 去抖动机制

    • KEY_Scan()中,通过debounce_cnt累计中断次数,超过阈值后标记按键按下,避免抖动误触发。
  3. 自锁标志

    • 按键按下后设置lock标志,防止长按重复触发;释放后自动复位。
  4. 蜂鸣器控制

    • 触发时设置beep_counter,定时中断中递减至0后关闭,确保鸣叫时间精确。

总结

本代码通过模块化设计,将按键扫描、蜂鸣器控制与定时器管理分离,提升了代码可读性与可维护性。采用HAL库标准接口,便于移植到其他STM32系列。实际应用中,可根据需求调整按键数量、去抖动时间及硬件配置。


http://www.ppmy.cn/server/170727.html

相关文章

【漫话机器学习系列】105.学习速率(Learning Rate)

学习速率&#xff08;Learning Rate&#xff09;及其影响 学习速率&#xff08;Learning Rate, LR&#xff09;是机器学习和深度学习中的关键超参数&#xff0c;它决定了模型在训练过程中参数更新的步长。学习速率的选择直接影响训练的效率和最终模型的性能。本文将结合图示深…

WPS中Word表格做好了,忘记写标题了怎么办?

大家好&#xff0c;我是小鱼。 在使用wps制作Word表格时经常会遇到这种情况&#xff0c;就是辛辛苦苦把word表格制作好了&#xff0c;却突然发现忘了为表格添加标题了。怎么都没法为表格重写添加标题&#xff0c;真是一阵操作猛如虎&#xff0c;结果觉得表格真是白做了。其实&…

Linux编译工具链

文章目录 编译工具链1. 编译1.1 GCC其他选项1.2 条件编译1.2.1 条件编译的作用 2. 调试2.1 进入GDB调试界面2.2 调试程序查看源代码设置断点查看断点删除断点启动调试继续忽略断点n次单步调试跳出函数逐过程监视查看内存退出GDB 2.3 调试coredump文件查看系统是否允许生成Cored…

从卡顿到丝滑:火山引擎DeepSeek-R1引领AI工具新体验

方舟大模型体验中心全新上线&#xff0c;免登录体验满血联网版Deep Seek R1 模型及豆包最新版模型:https://www.volcengine.com/experience/ark?utm_term202502dsinvite&acDSASUQY5&rcGO9H7M38 告别DeepSeek卡顿&#xff0c;探索火山引擎DeepSeek-R1的丝滑之旅 在A…

QSplashScreen --软件启动前的交互

目录 QSplashScreen 类介绍 使用方式 项目中使用 THPrinterSplashScreen头文件 THPrinterSplashScreen实现代码 使用代码 使用效果 QSplashScreen 类介绍 QSplashScreen 是 Qt 中的一个类&#xff0c;用于显示启动画面。它通常在应用程序启动时显示&#xff0c;以向用户显…

Golang学习笔记_38——享元模式

Golang学习笔记_35——代理模式 Golang学习笔记_36——装饰器模式 Golang学习笔记_37——外观模式 文章目录 享元模式&#xff08;Flyweight Pattern&#xff09;详解一、核心概念1. 定义2. 解决的问题3. 核心角色4. 类图 二、特点分析三、适用场景1. 文字编辑器2. 游戏开发3. …

嵌入式项目:STM32刷卡指纹智能门禁系统

本文详细介绍基于STM32的刷卡指纹智能门禁系统。 获取资料/指导答疑/技术交流/选题/帮助&#xff0c;请点链接&#xff1a; https://gitee.com/zengzhaorong/share_contact/blob/master/stm32.txt 1 系统功能 1.1 功能概述 本系统由STM32硬件端&#xff08;下位机&#xff09;…

Spring Boot中@EnableAutoConfiguration的魔法与实例解析

在Spring Boot的世界里&#xff0c;EnableAutoConfiguration注解扮演着一个极为重要的角色。它不仅简化了Spring应用的配置过程&#xff0c;还通过智能的自动配置机制&#xff0c;让开发者能够更加专注于业务逻辑的实现&#xff0c;而无需过多地操心底层的配置细节。今天&#…