STM32F103ZET6按键中断控制灯

发布于:2025-07-10 ⋅ 阅读:(23) ⋅ 点赞:(0)

        在嵌入式开发中,外部中断是实现硬件事件实时响应的关键机制。STM32 的外部中断 / 事件控制器(EXTI)具备强大的中断管理能力,本文将围绕按键中断应用,详细拆解 EXTI 工作原理与配置流程,帮助大家掌握硬件中断的开发技巧。

一、外部中断控制器核心架构

(一)控制器特性概览

STM32 的外部中断 / 事件控制器支持 19 路独立输入线,每路可配置:

  • 触发模式:上升沿、下降沿、双边沿触发
  • 中断 / 事件类型:中断请求(触发 CPU 响应)或事件请求(触发外设联动,无 CPU 干预 )
  • 独立屏蔽:可单独关闭某路中断,不影响其他通道
  • 脉冲检测:支持捕获窄脉冲(宽度低于 APB2 时钟周期),满足高精度场景需求

核心特点:每个中断线独立配置、状态可查、支持软件触发,为复杂中断场景提供灵活控制。

(二)关键组件解析

  1. 边沿检测器:监测 GPIO 引脚电平变化,触发中断 / 事件的 “传感器”
  2. 挂起寄存器(EXTI->PR):记录中断请求状态,置 1 表示对应中断线有未处理请求
  3. 屏蔽寄存器(EXTI->IMR):控制中断是否上报 NVIC(置 1 允许,置 0 屏蔽 )
  4. 触发选择寄存器(EXTI->FTSR/RTSR):配置下降沿 / 上升沿触发

同一中断线仅能映射一个 GPIO 引脚,需通过 AFIO 外设配置引脚与中断线的映射关系。

二、按键中断需求分析(以 PE4 为例)

(一)硬件连接

        按键一端接地,另一端接 PE4,默认状态下 PE4 经上拉电阻保持高电平;按键按下时,PE4 电平拉低(下降沿变化 )。需配置 PE4 下降沿触发中断,实现按键事件实时响应(如 LED 翻转 )。

(二)中断设计目标

  • 检测 PE4 引脚下降沿(按键按下动作 )
  • 触发中断后翻转 LED 状态
  • 确保中断标志正确清除,避免重复触发

三、外部中断配置全流程

(一)1. 使能 APB2 时钟(关键外设使能)

// 使能 AFIO 时钟(必须!中断引脚映射依赖 AFIO)
RCC->APB2ENR |= (0x01 << 0);  

        AFIO 负责管理 GPIO 与 EXTI 中断线的映射关系,必须先使能其时钟才能配置引脚映射。

(二)2. 配置引脚 - 中断线映射(AFIO 寄存器操作)

// 将 PE4 映射到 EXTI4 中断线
AFIO->EXTICR[1] |= (0x04 << 0);  
  • EXTICR[1] 对应 EXTICR2 寄存器(数组索引 0 对应 EXTICR1 ,索引 1 对应 EXTICR2 )
  • 0x04 表示选择 PORT E(PE),左移 0 位对应 EXTI4 中断线
  • 作用:建立 PE4 与 EXTI4 的硬件关联,使 EXTI4 能感知 PE4 的电平变化

(三)3. 使能 EXTI4 中断请求

// 允许 EXTI4 中断线向 NVIC 发送请求
EXTI->IMR |= (0x01 << 4);  

    IMR(Interrupt Mask Register)寄存器第 4 位置 1,解除 EXTI4 的中断屏蔽,中断事件可传递到 NVIC。

(四)4. 配置下降沿触发模式(定义中断触发条件)

// 配置 EXTI4 为下降沿触发
EXTI->FTSR |= (0x01 << 4);  

FTSR(Falling Trigger Selection Register)第 4 位置 1,当 PE4 检测到电平从高→低变化时,触发中断请求。

(五)5. 配置 NVIC 中断优先级与使能

// 配置中断优先级分组(假设 2 位抢占 + 2 位响应)
NVIC_SetPriorityGrouping(2);  

// 设置 EXTI4 中断优先级(抢占优先级 1,响应优先级 0 → 编码为 0100B = 4?需根据分组调整,此处示例为 6 简化)
NVIC_SetPriority(EXTI4_IRQn, 6);  

// 使能 EXTI4 中断
NVIC_EnableIRQ(EXTI4_IRQn);  
  • 优先级分组:通过 NVIC_SetPriorityGrouping 划分抢占优先级和响应优先级的位数,影响中断嵌套逻辑
  • 优先级设置NVIC_SetPriority 定义中断响应优先级,数值越小优先级越高
  • 中断使能NVIC_EnableIRQ 允许 NVIC 转发 EXTI4 中断到 CPU

(六)6. 实现中断处理函数(业务逻辑编写)

// 定义全局标志位(控制 LED 状态)
volatile uint8_t flag = 0;  

void EXTI4_IRQHandler(void)
{
    // 检查 EXTI4 中断标志(确认中断源)
    if ((EXTI->PR & (0x01 << 4)) != 0)  
    {
        // 清除中断标志(必须手动写 1 清除,否则会重复触发)
        EXTI->PR |= (0x01 << 4);  
        
        // 翻转标志位
        flag = !flag;  
        
        // 模拟 LED 控制(根据 flag 切换状态,需实现 LED1 函数)
        LED1(flag);  
    }
}
  • 中断标志检测:通过 EXTI->PR 寄存器判断中断是否由 EXTI4 触发
  • 标志清除:写 1 清除 PR 寄存器对应位,否则中断会持续触发
  • 业务逻辑:翻转标志位并控制 LED,实现 “按键按下→LED 翻转” 的交互

四、库函数版配置对比(简化开发流程)

若使用 STM32 标准外设库,配置流程更简洁:

void EXTI4_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    EXTI_InitTypeDef EXTI_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    // 1. 使能 AFIO 和 GPIOE 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOE, ENABLE);

    // 2. 配置 PE4 为输入模式(上拉/下拉,根据硬件决定)
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入(匹配按键硬件)
    GPIO_Init(GPIOE, &GPIO_InitStruct);

    // 3. 配置引脚-中断线映射(PE4 → EXTI4)
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4);

    // 4. 配置 EXTI4 中断模式
    EXTI_InitStruct.EXTI_Line = EXTI_Line4;
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStruct);

    // 5. 配置 NVIC 中断
    NVIC_InitStruct.NVIC_IRQChannel = EXTI4_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; // 抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;        // 响应优先级
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
}

// 中断处理函数(与寄存器版逻辑一致)
void EXTI4_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line4) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line4); // 清除中断标志
        flag = !flag;
        LED1(flag);
    }
}

        库函数通过 GPIO_EXTILineConfig 简化引脚映射,EXTI_InitTypeDef 封装触发模式、中断使能等配置,降低了寄存器操作的复杂度。

0voice · GitHub


网站公告

今日签到

点亮在社区的每一天
去签到