STM32 按键输入检测(GPIO 外部中断)
在 STM32 开发中,按键输入是最基础的实验之一。通常按键可通过GPIO 轮询或外部中断(EXTI)方式检测。本实验介绍使用 GPIO 外部中断检测按键输入,让 STM32 在检测到按键按下时自动执行回调函数,提高系统响应速度。
1. 按键输入检测方式
- GPIO 轮询(Polling):定期读取按键 GPIO 电平,适用于简单应用,但占用 CPU 资源。
- GPIO 外部中断(EXTI):当按键状态变化时触发中断,MCU 只在事件发生时响应,适用于低功耗或高实时性应用。
本实验使用 EXTI 外部中断 检测按键。
2. 硬件连接
- 按键连接 STM32
- 按键一端接 GPIO(PA0)
- 另一端接 GND
- 需开启 上拉电阻(Pull-Up),否则按键松开时可能出现悬空状态
3. STM32CubeMX 配置
3.1 新建工程
- 打开 STM32CubeMX
- 选择目标 STM32 芯片/开发板(如 STM32F103C8T6)
3.2 配置 GPIO 为外部中断
- 选择 PA0(连接按键的引脚)
- 设置 GPIO Mode 为 External Interrupt Mode with Falling edge trigger(下降沿触发中断)
- 设置 Pull-up(上拉)
- 进入 NVIC(中断配置) 选项卡,启用 EXTI0 中断
3.3 配置时钟
- 进入 Clock Configuration
- 选择 HSE 8MHz,主频 72MHz(F1)或 168MHz(F4)
3.4 生成代码
- Project Manager:设置工程名称(如
Key_EXTI
) - Toolchain/IDE:选择 Keil / STM32CubeIDE
- 点击 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 代码烧录
- F7 编译
- Ctrl+F8 下载程序
- F5 进入调试模式
6.2 STM32CubeIDE 代码烧录
- Ctrl+B 编译
- 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 开发效率! 🚀