首页 > 技术文章 > STM32-EXTI中断/事件管理器

SergeyuiL 2022-01-11 16:04 原文

0、前言

异常类型

来自stm32f10x.hIRQn_Type结构体

/******  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                      */
  #ifdef STM32F10X_HD
  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        */
#endif /* STM32F10X_HD */  

NVIC

NVIC即嵌套向量中断控制器,STM32的NVIC是Cortex-M3的NVIC的一个子集

相关库函数

static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn);		//使能中断
static __INLINE void NVIC_DisableIRQ(IRQn_Type IRQn);		//失能中断
static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn);	//设置中断悬起位
static __INLINE uint32_t NVIC_ClearPendingIRQ(IRQn_Type IRQn);	//清除中断悬起位
static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn);	//获得悬起中断编号
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority);	//设置中断优先级
static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn);		//获得中断优先级
static __INLINE void NVIC_SystemReset(void);		//系统复位

中断优先级

中断分组,0~4

(第3组)抢占优先级0~7,响应优先级1或0

抢占优先级级别高于响应优先级,数值越小代表优先级越高

高优先级的抢占优先级可打断正在运行的低抢占优先级中断

高优先级的响应优先级不可打断低响应优先级

NVIC_PriorityGroup NVIC_IRQChannelPreemptionPriority NVIC_IRQChannelSubPriority
NVIC_PriorityGroup_0 0 0-15
NVIC_PriorityGroup_1 0-1 0-7
NVIC_PriorityGroup_2 0-3 0-3
NVIC_PriorityGroup_3 0-7 0-1
NVIC_PriorityGroup_4 0-15 0

NVIC配置优先级分组

  • 中断优先级分组
//整个系统执行过程中,只设置一次中断分组。
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
/*
NVIC_PriorityGroup_0~NVIC_PriorityGroup_4
*/
  • 初始化结构体
typedef struct
{
     uint8_t NVIC_IRQChannel; 		//定义中断源,选自IRQn_Type结构体中元素
     uint8_t NVIC_IRQChannelPreemptionPriority;		//抢占优先级
     uint8_t NVIC_IRQChannelSubPriority; 		//子优先级
     FunctionalState NVIC_IRQChannelCmd; 		//中断是否使能
 } NVIC_InitTypeDef;
//中断初始化
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
  • 编写对应的中断服务函数,统一写在stm32f10x_it.c

1、EXTI-外部中断/事件控制器

简介

外部中断/事件控制器由20个产生事件/中断请求的边沿检测器组成。

每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。

每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求

挂载于APB2总线

主要特性:

  • 每个中断/事件都有独立的触发和屏蔽
  • 每个中断线都有专用的状态位
  • 支持多达20个软件的中断/事件请求
  • 检测脉冲宽度低于APB2时钟宽度的外部信号。参见数据手册中电气特性部分的相关参数。

由输入线输入检测信号经一系列处理后,可至NVIC中断控制器产生软件层面的中断,或者经脉冲发生器产生硬件层面的事件,供给TIM,ADC等。

中断线

共有20条中断/事件线,EXTI0-15可用于GPIO,其他用于特定的外设事件

外部中断编程

常用库函数

//中断服务函数列表
EXTI0_IRQHandler           
EXTI1_IRQHandler
EXTI2_IRQHandler           
EXTI3_IRQHandler           
EXTI4_IRQHandler           
EXTI9_5_IRQHandler         
EXTI15_10_IRQHandler
//	设置IO口与中断线的映射关系
//	exp:  GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
//初始化中断线:触发方式等
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
//判断中断线中断状态,是否发生
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
//清除中断线上的中断标志位,必须手动清零
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

EXTI初始化结构体

typedef struct
{
    uint32_t EXTI_Line;   //指定要配置的中断线           
    EXTIMode_TypeDef EXTI_Mode;   //模式:事件 OR中断
    EXTITrigger_TypeDef EXTI_Trigger;//触发方式:上升沿/下降沿/双沿触发
    FunctionalState EXTI_LineCmd;  //使能 OR失能
}EXTI_InitTypeDef;

配置步骤

  • 外设时钟使能,复用时钟使能

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO, ENABLE);
    
  • 配置NVIC中断

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);	//设置优先级分组
    
    // NVIC结构体初始化
    /* 配置中断源 */
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
    /* 配置抢占优先级 */
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    /* 配置子优先级 */
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    /* 使能中断通道 */
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
  • 配置IO口

    GPIO_Init();
    
    //设置IO口与中断线的映射关系。
    void GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource13);
    
  • 初始化EXTI结构体

    EXTI_InitTypeDef* EXTI_InitStructure;
    
    EXTI_InitStructure.EXTI_Line=EXTI_Line13;  //可选EXTI0-19	
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	//中断或事件(EXTI_Mode_Event)
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
    //EXTI_Trigger_Rising / EXTI_Trigger_Rising_Falling
    EXTI_InitStructure.EXTI_LineCmd = ENABLE; //ENABLE或DISABLE
    
    EXTI_Init(&EXTI_InitStructure);
    
  • 编写中断服务函数(stm32f10x_it.c)

    void EXTI15_10_IRQHandler(void)
    {
      //确保是否产生了EXTI Line中断
    	if(EXTI_GetITStatus(EXTI_Line13) != RESET) 
    	{
    		
        	//清除中断标志位
    		EXTI_ClearITPendingBit(EXTI_Line13);     
    	}  
    }
    

推荐阅读