按键输入检测(GPIO外部中断)

STM32 按键输入检测(GPIO 外部中断)

在 STM32 开发中,按键输入是最基础的实验之一。通常按键可通过GPIO 轮询外部中断(EXTI)方式检测。本实验介绍使用 GPIO 外部中断检测按键输入,让 STM32 在检测到按键按下时自动执行回调函数,提高系统响应速度。


1. 按键输入检测方式

  1. GPIO 轮询(Polling):定期读取按键 GPIO 电平,适用于简单应用,但占用 CPU 资源。
  2. GPIO 外部中断(EXTI):当按键状态变化时触发中断,MCU 只在事件发生时响应,适用于低功耗或高实时性应用。

本实验使用 EXTI 外部中断 检测按键。


2. 硬件连接

  • 按键连接 STM32
    • 按键一端接 GPIO(PA0)
    • 另一端接 GND
    • 需开启 上拉电阻(Pull-Up),否则按键松开时可能出现悬空状态

3. STM32CubeMX 配置

3.1 新建工程

  1. 打开 STM32CubeMX
  2. 选择目标 STM32 芯片/开发板(如 STM32F103C8T6)

3.2 配置 GPIO 为外部中断

  1. 选择 PA0(连接按键的引脚)
  2. 设置 GPIO ModeExternal Interrupt Mode with Falling edge trigger(下降沿触发中断)
  3. 设置 Pull-up(上拉)
  4. 进入 NVIC(中断配置) 选项卡,启用 EXTI0 中断

3.3 配置时钟

  • 进入 Clock Configuration
  • 选择 HSE 8MHz,主频 72MHz(F1)或 168MHz(F4)

3.4 生成代码

  1. Project Manager:设置工程名称(如 Key_EXTI
  2. Toolchain/IDE:选择 Keil / STM32CubeIDE
  3. 点击 Generate Code,STM32CubeMX 自动生成外部中断初始化代码

4. 代码编写

STM32CubeMX 生成的 MX_GPIO_Init() 会自动配置 EXTI0 作为外部中断,接下来编写中断回调函数

4.1 EXTI 按键中断回调函数

stm32f1xx_it.c(或 stm32f4xx_it.c)文件中,找到 EXTI0_IRQHandler(),修改如下:

void EXTI0_IRQHandler(void) {
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);  // 调用 HAL 处理中断
}

stm32f1xx_hal_gpio.c 中找到 HAL_GPIO_EXTI_Callback(),添加按键处理逻辑:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == GPIO_PIN_0) {  // 确保是 PA0 触发的中断
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); // 翻转 LED
    }
}

📌 解释:

  • HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); 处理 EXTI0 中断标志
  • HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); 按键按下时 翻转 LED 状态

4.2 完整 main.c 代码

#include "main.h"

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init(); // 初始化 GPIO 和 EXTI

    while (1) {
        // 按键按下后 LED 翻转,主循环无需轮询
    }
}

/* 按键外部中断回调函数 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == GPIO_PIN_0) {  // PA0 按键中断
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); // LED 翻转
    }
}

5. 消除按键抖动

机械按键在按下时可能会产生抖动(短时间内多次触发),可通过 软件延时定时器消抖 解决。

方法 1:软件延时消抖

HAL_GPIO_EXTI_Callback() 中增加 HAL_Delay(20);

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == GPIO_PIN_0) {  // PA0 按键中断
        HAL_Delay(20); // 延时 20ms 消抖
        if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) { // 确认按键仍处于低电平
            HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); // LED 翻转
        }
    }
}

方法 2:定时器消抖

使用定时器在 按键按下后启动消抖计时,到达设定时间后再检测一次按键状态,适用于高精度应用。


6. 代码下载 & 运行

6.1 Keil 代码烧录

  1. F7 编译
  2. Ctrl+F8 下载程序
  3. F5 进入调试模式

6.2 STM32CubeIDE 代码烧录

  1. Ctrl+B 编译
  2. Debug > Run 烧录代码

按下按键,LED 亮/灭交替变化。


7. FreeRTOS 低功耗优化

在低功耗应用中,可以让 STM32 进入低功耗模式,按键中断时唤醒 MCU,减少功耗。

HAL_GPIO_EXTI_Callback() 中添加低功耗模式:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == GPIO_PIN_0) {  
        __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // 清除唤醒标志
        HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); // 进入低功耗模式
    }
}

📌 解释

  • PWR_FLAG_WU:清除唤醒标志,防止 STM32 误进入低功耗
  • HAL_PWR_EnterSLEEPMode():让 MCU 进入睡眠模式,等待按键中断唤醒

8. 结论

使用 GPIO 外部中断(EXTI)可提高 STM32 按键响应速度
通过 HAL_GPIO_EXTI_Callback() 处理按键逻辑
需要消除按键抖动,可用软件延时或定时器
在低功耗应用中,可结合 FreeRTOS 让 STM32 进入睡眠模式

 

📌 建议新手先学习 GPIO 输入,再学习 EXTI 外部中断,提高 STM32 开发效率! 🚀

评论
列表