STM32 外部中断 标准库函数

中断概念

中断对于单片机来说是必不可少的存在。例如使用一个按键打开一个灯的方法,就可以使用中断的方式实现,并且效果更好。
中断的概念比较容易理解,就相当于做饭的时候,你的主任务是炒菜,炒菜炒到一半,来了个电话你就需要优先去接电话,然后电话处理完后才会继续回归主任务进行炒菜。这就是一个中断的实际概念。
中断对于 STM32 来说是必不可少的一部分,STM32 支持的中断类型也很多,在这里主要介绍其概念,并且以一个简易的外部按键输入中断作为演示示例。

本文以一个外部按键输入中断更改 LED 灯亮灭为例进行说明,其余中断类型在遇到对应模式时再具体介绍。


中断操作

中断操作的步骤基本为一下步骤:

  • 开启时钟线
  • 初始化中断向量表
  • 初始化 GPIO 口
  • 初始化中断模式
  • 进行中断响应处理
  • 清除中断标志位
    我们将按照上面步骤一步步进行处理。

开启时钟线

开始时钟线主要使用 RCC_APB2PeriphClockCmdRCC_APB1PeriphClockCmd 这两个函数。
具体使用哪一个函数查阅下图:
image.png
根据所挂载的时钟线选择响应函数。
这里以 RCC_APB2PeriphClockCmd 为例:
image.png
其中第一个参数的选择范围如下:
image.png
这里以开启 GPIOE 以及 复用 IO 始终为例:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE| RCC_APB2Periph_AFIO,ENABLE);

初始化中断向量表

主要使用 NVIC_PriorityGroupConfig 以及 NVIC_Init 函数
NVIC_PriorityGroupConfig 函数主要用于设置优先级组合。具体使用方法如下:
image.png
然后是使用 NVIC_Init 函数进行初始化:
image.png
此函数与 GPIO 中的 GPIO_Init 函数相似,使用结构体 NVIC_InitTypeDef 作为参数进行初始化。其相对应的参数如下:

  • NVIC_IRQChannel
    image.png
    image.png
  • NVIC_IRQChannelPreemptionPriorityNVIC_IRQChannelSubPriority
    image.png
    其中在相同的 PreemptionPriority 下,优先响应 SubPriority 优先级高的中断。在不同的 PreemptionPriority 下,优先响应 PreemptionPriority 优先级高的, SubPriority 没影响。
  • NVIC_IRQChannelCmd
    image.png
    这里以开启 PE4 外部中断为例:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  
NVIC_InitTypeDef NVIC_Param;  
NVIC_Param.NVIC_IRQChannel = EXTI4_IRQn;  
NVIC_Param.NVIC_IRQChannelPreemptionPriority = 0;  
NVIC_Param.NVIC_IRQChannelSubPriority = 1;  
NVIC_Param.NVIC_IRQChannelCmd = ENABLE;  
NVIC_Init(&NVIC_Param);

初始化 GPIO 口

主要使用 GPIO_InitGPIO_EXTILineConfig 函数。其中 GPIO_Init 函数的使用方式详见:GPIO
GPIO_EXTILineConfig 函数如下:
image.png
这里以开启 PE4 的外部中断为例:

GPIO_InitTypeDef GPIO_Param;  
GPIO_Param.GPIO_Pin=GPIO_Pin_4;  
GPIO_Param.GPIO_Speed = GPIO_Speed_50MHz;  
GPIO_Param.GPIO_Mode = GPIO_Mode_IPU;  
GPIO_Init(GPIOE,&GPIO_Param);  
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);

初始化中断

主要使用 EXTI_Init 函数进行初始化,看名字就能看出来其与之前的 NVIC_Init 函数使用方法类似。
image.png
使用 EXTI_InitTypeDef 函数进行初始化。

  • EXTI_Line
    image.png
    其中选择具体哪一个看如下图片:
    image.png
  • EXTI_Mode
    image.png
    二者的区别主要是事件请求会等待当前事件完成后再响应,而中断请求会直接打断当前事件直接请求。
  • EXTI_Trigger
    image.png
  • EXTI_LineCmd
    image.png
    这里以开启 PE4下降沿 中断为例:
EXTI_InitTypeDef EXTI_Param;  
EXTI_Param.EXTI_Line = EXTI_Line4;  
EXTI_Param.EXTI_Mode=EXTI_Mode_Interrupt;  
EXTI_Param.EXTI_Trigger = EXTI_Trigger_Falling;  
EXTI_Param.EXTI_LineCmd = ENABLE;  
EXTI_Init(&EXTI_Param);

中断响应处理

中断响应处理是我们进入中断后进行响应处理的地方,也是最重要的地方。不同的中断会调用不同的中断处理函数。所以我们需要根据我们初始化的中断选用不同的中断处理函数。
中断处理函数主要查看程序配置中的 stm32f10x.h 文件,然后根据自己的启动文件类别进行操作, 我这里使用的是 hd 类型的启动文件,这里值贴出对应的中断处理函数

typedef enum IRQn  
{  
/******  Cortex-M3 Processor Exceptions Numbers ***************************************************/  
  NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                             */  
  MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M3 Memory Management Interrupt              */  
  BusFault_IRQn               = -11,    /*!< 5 Cortex-M3 Bus Fault Interrupt                      */  
  UsageFault_IRQn             = -10,    /*!< 6 Cortex-M3 Usage Fault Interrupt                    */  
  SVCall_IRQn                 = -5,     /*!< 11 Cortex-M3 SV Call Interrupt                       */  
  DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M3 Debug Monitor Interrupt                 */  
  PendSV_IRQn                 = -2,     /*!< 14 Cortex-M3 Pend SV Interrupt                       */  
  SysTick_IRQn                = -1,     /*!< 15 Cortex-M3 System Tick Interrupt                   */  
  
/******  STM32 specific Interrupt Numbers *********************************************************/  
  WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                            */  
  PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detection Interrupt            */  
  TAMPER_IRQn                 = 2,      /*!< Tamper Interrupt                                     */  
  RTC_IRQn                    = 3,      /*!< RTC global Interrupt                                 */  
  FLASH_IRQn                  = 4,      /*!< FLASH global Interrupt                               */  
  RCC_IRQn                    = 5,      /*!< RCC global Interrupt                                 */  
  EXTI0_IRQn                  = 6,      /*!< EXTI Line0 Interrupt                                 */  
  EXTI1_IRQn                  = 7,      /*!< EXTI Line1 Interrupt                                 */  
  EXTI2_IRQn                  = 8,      /*!< EXTI Line2 Interrupt                                 */  
  EXTI3_IRQn                  = 9,      /*!< EXTI Line3 Interrupt                                 */  
  EXTI4_IRQn                  = 10,     /*!< EXTI Line4 Interrupt                                 */  
  DMA1_Channel1_IRQn          = 11,     /*!< DMA1 Channel 1 global Interrupt                      */  
  DMA1_Channel2_IRQn          = 12,     /*!< DMA1 Channel 2 global Interrupt                      */  
  DMA1_Channel3_IRQn          = 13,     /*!< DMA1 Channel 3 global Interrupt                      */  
  DMA1_Channel4_IRQn          = 14,     /*!< DMA1 Channel 4 global Interrupt                      */  
  DMA1_Channel5_IRQn          = 15,     /*!< DMA1 Channel 5 global Interrupt                      */  
  DMA1_Channel6_IRQn          = 16,     /*!< DMA1 Channel 6 global Interrupt                      */  
  DMA1_Channel7_IRQn          = 17,     /*!< DMA1 Channel 7 global Interrupt                      */
  ADC1_2_IRQn                 = 18,     /*!< ADC1 and ADC2 global Interrupt                       */  
  USB_HP_CAN1_TX_IRQn         = 19,     /*!< USB Device High Priority or CAN1 TX Interrupts       */  
  USB_LP_CAN1_RX0_IRQn        = 20,     /*!< USB Device Low Priority or CAN1 RX0 Interrupts       */  
  CAN1_RX1_IRQn               = 21,     /*!< CAN1 RX1 Interrupt                                   */  
  CAN1_SCE_IRQn               = 22,     /*!< CAN1 SCE Interrupt                                   */  
  EXTI9_5_IRQn                = 23,     /*!< External Line[9:5] Interrupts                        */  
  TIM1_BRK_IRQn               = 24,     /*!< TIM1 Break Interrupt                                 */  
  TIM1_UP_IRQn                = 25,     /*!< TIM1 Update Interrupt                                */  
  TIM1_TRG_COM_IRQn           = 26,     /*!< TIM1 Trigger and Commutation Interrupt               */  
  TIM1_CC_IRQn                = 27,     /*!< TIM1 Capture Compare Interrupt                       */  
  TIM2_IRQn                   = 28,     /*!< TIM2 global Interrupt                                */  
  TIM3_IRQn                   = 29,     /*!< TIM3 global Interrupt                                */  
  TIM4_IRQn                   = 30,     /*!< TIM4 global Interrupt                                */  
  I2C1_EV_IRQn                = 31,     /*!< I2C1 Event Interrupt                                 */  
  I2C1_ER_IRQn                = 32,     /*!< I2C1 Error Interrupt                                 */  
  I2C2_EV_IRQn                = 33,     /*!< I2C2 Event Interrupt                                 */  
  I2C2_ER_IRQn                = 34,     /*!< I2C2 Error Interrupt                                 */  
  SPI1_IRQn                   = 35,     /*!< SPI1 global Interrupt                                */  
  SPI2_IRQn                   = 36,     /*!< SPI2 global Interrupt                                */  
  USART1_IRQn                 = 37,     /*!< USART1 global Interrupt                              */  
  USART2_IRQn                 = 38,     /*!< USART2 global Interrupt                              */  
  USART3_IRQn                 = 39,     /*!< USART3 global Interrupt                              */  
  EXTI15_10_IRQn              = 40,     /*!< External Line[15:10] Interrupts                      */  
  RTCAlarm_IRQn               = 41,     /*!< RTC Alarm through EXTI Line Interrupt                */  
  USBWakeUp_IRQn              = 42,     /*!< USB Device WakeUp from suspend through EXTI Line Interrupt */  
  TIM8_BRK_IRQn               = 43,     /*!< TIM8 Break Interrupt                                 */  
  TIM8_UP_IRQn                = 44,     /*!< TIM8 Update Interrupt                                */  
  TIM8_TRG_COM_IRQn           = 45,     /*!< TIM8 Trigger and Commutation Interrupt               */  
  TIM8_CC_IRQn                = 46,     /*!< TIM8 Capture Compare Interrupt                       */  
  ADC3_IRQn                   = 47,     /*!< ADC3 global Interrupt                                */  
  FSMC_IRQn                   = 48,     /*!< FSMC global Interrupt                                */  
  SDIO_IRQn                   = 49,     /*!< SDIO global Interrupt                                */  
  TIM5_IRQn                   = 50,     /*!< TIM5 global Interrupt                                */  
  SPI3_IRQn                   = 51,     /*!< SPI3 global Interrupt                                */  
  UART4_IRQn                  = 52,     /*!< UART4 global Interrupt                               */  
  UART5_IRQn                  = 53,     /*!< UART5 global Interrupt                               */  
  TIM6_IRQn                   = 54,     /*!< TIM6 global Interrupt                                */  
  TIM7_IRQn                   = 55,     /*!< TIM7 global Interrupt                                */  
  DMA2_Channel1_IRQn          = 56,     /*!< DMA2 Channel 1 global Interrupt                      */  
  DMA2_Channel2_IRQn          = 57,     /*!< DMA2 Channel 2 global Interrupt                      */  
  DMA2_Channel3_IRQn          = 58,     /*!< DMA2 Channel 3 global Interrupt                      */  
  DMA2_Channel4_5_IRQn        = 59      /*!< DMA2 Channel 4 and Channel 5 global Interrupt        */

自行根据此内容进行查询选择即可。查询到对应的中断处理函数后,在自己的文件中实现对应的函数即可。
这里以 PE4 的中断为例:

// 中断响应函数  
void EXTI4_IRQHandler()  
{  
    if (EXTI_GetFlagStatus(EXTI_Line4) == SET)  
    {  
        GPIO_Toggle(GPIOB,GPIO_Pin_5);  
        //清除中断标志位  
        EXTI_ClearITPendingBit(EXTI_Line4);  
    }  
}

其中的 EXTI_GetFlagStatus 函数用于防抖,用法如下:
image.png
此函数与 EXTI_GetITStatus 函数作用相同,看个人爱好。
image.png


清除中断标志位

清除中断标志位十分重要!不进行清除程序将一直处于中断中。
主要使用的函数是 EXTI_ClearITPendingBit
其用法如下:
image.png
示例代码如下:

EXTI_ClearITPendingBit(EXTI_Line4);  
  • 10
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值