2. 按键输入与中断
任务目标
本案例使用M55开发板上的用户按键(连接至GPIO中断引脚)触发外部中断,每次按下按键时切换板载LED的亮灭状态。通过该实验掌握GPIO中断的配置流程:引脚初始化、中断触发条件设置、中断回调函数注册以及中断安全的状态变量操作。
硬件连接与前置条件
- 开发板:M55内核开发板(含板载按键与LED)
- 按键引脚:PB2(默认下拉,按下为高电平)
- LED引脚:PC13(低电平点亮)
- 依赖:HAL库(STM32CubeMX生成或手动包含),无需额外第三方库
完整代码实现
#include "main.h"
/* 中断安全的状态标志 */
static volatile uint8_t led_state = 0;
/* LED与按键引脚定义 */
#define LED_PIN GPIO_PIN_13
#define LED_PORT GPIOC
#define BTN_PIN GPIO_PIN_2
#define BTN_PORT GPIOB
void SystemClock_Config(void);
static void GPIO_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
GPIO_Init();
while (1)
{
/* 主循环空闲,等待中断触发 */
__WFI();
}
}
static void GPIO_Init(void)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef gpio_btn = {0};
gpio_btn.Pin = BTN_PIN;
gpio_btn.Mode = GPIO_MODE_IT_RISING; /* 上升沿触发中断 */
gpio_btn.Pull = GPIO_PULLDOWN; /* 默认下拉,按下为高 */
HAL_GPIO_Init(BTN_PORT, &gpio_btn);
GPIO_InitTypeDef gpio_led = {0};
gpio_led.Pin = LED_PIN;
gpio_led.Mode = GPIO_MODE_OUTPUT_PP;
gpio_led.Pull = GPIO_NOPULL;
gpio_led.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_PORT, &gpio_led);
/* 初始状态:LED熄灭(PC13高电平) */
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
/* 使能并注册EXTI中断回调 */
HAL_NVIC_SetPriority(EXTI2_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
}
/* EXTI2中断服务函数(在启动文件中已声明) */
void EXTI2_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(BTN_PIN);
}
/* 中断回调:按键按下时翻转LED */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == BTN_PIN)
{
/* 消除抖动:简单延时(实际工程建议使用定时器消抖) */
for (volatile uint32_t i = 0; i < 10000; i++);
/* 确认引脚仍为高电平(有效按下) */
if (HAL_GPIO_ReadPin(BTN_PORT, BTN_PIN) == GPIO_PIN_SET)
{
led_state ^= 1;
if (led_state)
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); /* 点亮 */
else
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET); /* 熄灭 */
}
}
}
编译与运行
- 使用STM32CubeIDE打开工程,将上述代码替换
main.c中对应内容(保留SystemClock_Config函数体)。 - 确认启动文件(startup_stm32u5xx.s)中包含
EXTI2_IRQHandler中断向量(默认已包含)。 - 编译并下载至开发板。
验证方法
程序运行后,观察板载LED状态:
- 上电复位后LED保持熄灭;
- 每次按下按键(PB2)并释放,LED状态翻转一次(亮→灭→亮→灭);
- 长按按键不会重复触发(仅在按下瞬间翻转一次)。
若LED状态与按键动作一致,且无抖动导致的多次翻转,则本案例验证通过。
关键说明
- 中断回调中使用了简单延时消抖,适用于教学演示;实际产品建议使用定时器或状态机消抖。
led_state声明为volatile,确保主循环与中断上下文访问一致性。- 若按键按下无反应,检查按键引脚是否与PB2一致(部分开发板使用PA0或PC13),需根据实际硬件修改
BTN_PIN/BTN_PORT定义。