STM32学习笔记——中断(2)

外部中断

认识外部中断

STM32的外部中断是一种用于检测和响应外部事件的机制。它允许微控制器在发生特定的外部信号变化时,立即暂停当前执行的任务,转而执行一个中断服务例程(ISR)。这对于处理时间敏感的任务,如按钮按下、传感器信号变化等,非常重要。
STM32芯片有19个EXTI外部中断源,其中GPIO外部中断源16个,分别对应7个中断向量,即对应着7个中断服务函数。
在这里插入图片描述

外部中断的触发条件

  1. 下降沿触发(Falling Edge Trigger)
    条件:当外部信号从高电平变为低电平时触发中断。
    应用:适用于需要对信号的负跳变进行响应的场合,例如检测按钮的按下。
  2. 上升沿触发(Rising Edge Trigger)
    条件:当外部信号从低电平变为高电平时触发中断。
    应用:适用于需要对信号的正跳变进行响应的场合,例如检测按钮的释放。
  3. 双沿触发(Both Edge Trigger)
    条件:当外部信号在上升沿或下降沿时都会触发中断。
    应用:适用于需要对信号的任何边沿变化都进行响应的场合,例如高频信号的边沿检测。
  4. 电平触发(Level Trigger)
    条件:当外部信号保持在特定电平(高或低)时触发中断。STM32F103中不直接支持电平触发,但可以通过外部电路来实现电平触发的效果。
    应用:适用于需要对信号电平状态变化的监控,但通常需要额外的电路来转换为边沿触发的信号。

注意:所有的GPIO口都可以触发中断,但相同的Pin号不能同时触发中断。
在这里插入图片描述

代码示例

配置过程中我们需要使用到一些库函数,如GPIO库函数、RCC库函数、EXTI库函数、NVIC库函数。
在这里插入图片描述
除了GPIO的基本配置函数,这里还需使用GPIO库函数的最后一个,即选择GPIO管脚用作外部中断线路。
在这里插入图片描述在这里插入图片描述
我们需要使能GPIO的时钟、AFIO的时钟、外部中断的时钟。
在这里插入图片描述
根据功能要求使用相应的EXTI库函数。
在这里插入图片描述
NVIC库函数提供了对中断控制和管理的全面支持,包括中断使能、禁用、优先级设置和优先级分组等功能。

static void ConfigEXTIGPIO(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;  //GPIO_InitStructure用于存放GPIO的参数
                                                                     
  //使能RCC相关时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA的时钟
                                                                                       
  //配置PA0
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;           //设置引脚
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;        //设置输入类型
  GPIO_Init(GPIOA, &GPIO_InitStructure);                //根据参数初始化GPIO
}

初始化PA0引脚,对应STM32板子上的KEY3。

static void ConfigEXTI(void)
{
  EXTI_InitTypeDef EXTI_InitStructure;  //EXTI_InitStructure用于存放EXTI的参数
  NVIC_InitTypeDef NVIC_InitStructure;  //NVIC_InitStructure用于存放NVIC的参数
  
  //使能RCC相关时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //使能AFIO的时钟

 //配置PA0的EXTI和NVIC
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);   //选择引脚作为中断线
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;                    //选择中断线
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;           //开放中断请求
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;        //设置为上升沿触发
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                     //使能中断线 
  EXTI_Init(&EXTI_InitStructure);                               //根据参数初始化EXTI
  
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;              //中断通道号
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;     //设置抢占优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;            //设置响优先级
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;               //使能中断
  NVIC_Init(&NVIC_InitStructure);                               //根据参数初始化NVIC
}
  1. EXTI_InitTypeDef EXTI_InitStructure; 和 NVIC_InitTypeDef NVIC_InitStructure;定义了两个结构体,用于存储 EXTI 和 NVIC 的初始化配置参数。
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);使能 AFIO外设的时钟,这是配置外部中断所必须的。AFIO 允许将 GPIO引脚配置为外部中断源。
  3. GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);配置GPIOA 的第 0 引脚(PA0)为外部中断源 EXTI0。这是将具体的 GPIO 引脚映射到 EXTI 线的步骤。
  4. EXTI_InitStructure.EXTI_Line = EXTI_Line0;选择 EXTI0 作为外部中断线。STM32 的EXTI 线用于处理外部信号中断。
  5. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;配置为中断模式。中断模式会在触发条件满足时产生中断请求。
  6. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;设置中断触发条件为上升沿触发。即当 PA0 引脚检测到上升沿时,会产生中断。
  7. EXTI_InitStructure.EXTI_LineCmd = ENABLE;使能 EXTI0 中断线,表示启用配置好的中断线。
  8. EXTI_Init(&EXTI_InitStructure);根据配置参数初始化 EXTI 外部中断线。
  9. NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;设置 NVIC 中断通道为EXTI0 中断通道,NVIC 用于中断管理。
  10. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;:设置 EXTI0中断的抢占优先级为 2。抢占优先级用于确定中断是否可以打断当前正在执行的中断。
  11. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;设置 EXTI0中断的响应优先级为 2。响应优先级用于在同一抢占优先级下决定中断的优先处理顺序。
  12. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;使能 EXTI0 中断通道。
  13. NVIC_Init(&NVIC_InitStructure);根据配置参数初始化 NVIC 中断控制器。

这段代码的目的是配置外部中断线 EXTI0,并设置中断触发条件、优先级等,使得当 PA0 引脚检测到上升沿时,会产生中断请求并由处理器处理。

void EXTI0_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line0) != RESET) //判断中断是否发生
  {   
    //LED1状态取反
    GPIO_WriteBit(GPIOC, GPIO_Pin_4, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_4)));
    //LED2状态取反
    GPIO_WriteBit(GPIOC, GPIO_Pin_5, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_5)));    
    EXTI_ClearITPendingBit(EXTI_Line0);     //清除Line0上的中断标志位
  }
}

上述代码实现的是,按键KEY3每按下一次,LED1和LED2状态进行一次翻转。

  • 14
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值