2. 按键输入与中断

任务目标

使用STM32的外部中断(EXTI)功能读取按键状态,实现按键按下时翻转LED的亮灭状态。本案例以STM32F103系列为例,按键接入PA0引脚(对应EXTI0中断线),LED接PC13引脚。

硬件连接

  • 按键一端接PA0,另一端接GND(按下为低电平)
  • LED正极经限流电阻接PC13,负极接GND(低电平点亮)
  • PA0需配置为上拉输入,确保按键未按下时引脚为高电平

实现代码

#include "stm32f10x.h"

// 按键中断服务函数
void EXTI0_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
        // 翻转PC13电平(LED状态取反)
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, 
            (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)));
        // 清除中断标志位
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

// 按键GPIO与EXTI初始化
void KEY_EXTI_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);

    // PA0上拉输入(按键按下接地)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // PC13推挽输出(控制LED)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    // 将PA0连接到EXTI0
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);

    // 配置EXTI0:下降沿触发(按键按下时产生中断)
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    // 配置NVIC:使能EXTI0中断通道
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

int main(void)
{
    // 初始化按键中断
    KEY_EXTI_Init();

    // 初始状态:LED熄灭(PC13输出高电平)
    GPIO_SetBits(GPIOC, GPIO_Pin_13);

    while (1) {
        // 主循环无任务,等待中断触发
    }
}

编译与烧录

  1. 使用Keil MDK或STM32CubeIDE创建工程,芯片选择STM32F103C8T6(或兼容型号)
  2. 将上述代码复制到main.c中,确保包含标准外设库头文件路径
  3. 编译工程,通过ST-Link或J-Link烧录到开发板

验证方法

烧录完成后,观察LED状态:

  • 上电后LED应处于熄灭状态
  • 每次按下按键(PA0接地),LED应立即翻转状态(亮→灭或灭→亮)
  • 松开按键后LED保持当前状态不变,等待下一次按下

若按键按下时LED无反应,检查PA0是否配置为上拉输入、EXTI触发边沿是否为下降沿,以及NVIC中断是否已使能。

关键说明

  • 本案例使用下降沿触发,对应按键按下瞬间;如需检测松开动作可改为上升沿触发
  • 实际应用中按键存在机械抖动,可在硬件上加RC滤波或软件延时消抖;本案例为演示中断机制,未做消抖处理
  • 中断服务函数中执行操作应尽量简短,避免在中断中处理耗时任务