STM32单片机中断管理

1.中断介绍

  1. cortex-m3支持256个中断,其中包含了16个内核中断,240个外部中断
  2. stm32只有84个中断,包括16个内核中断和68个可屏蔽中断
  3. stm32f103上只有60个可屏蔽中断,f107上才有68个中断

也可以在相应的startup_stm32f10x_hd.s 中查看中断向量表查看当前芯片的中断源数。

我当前看的这个一共是60个外部中断,也可以在参考手册查找Interrupt and exception vectors 有详细的对应寄存器地址。

__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
                DCD     MemManage_Handler          ; MPU Fault Handler
                DCD     BusFault_Handler           ; Bus Fault Handler
                DCD     UsageFault_Handler         ; Usage Fault Handler
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     SVC_Handler                ; SVCall Handler
                DCD     DebugMon_Handler           ; Debug Monitor Handler
                DCD     0                          ; Reserved
                DCD     PendSV_Handler             ; PendSV Handler
                DCD     SysTick_Handler            ; SysTick Handler

                ; External Interrupts
                DCD     WWDG_IRQHandler            ; Window Watchdog
                DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
                DCD     TAMPER_IRQHandler          ; Tamper
                DCD     RTC_IRQHandler             ; RTC
                DCD     FLASH_IRQHandler           ; Flash
                DCD     RCC_IRQHandler             ; RCC
                DCD     EXTI0_IRQHandler           ; EXTI Line 0
                DCD     EXTI1_IRQHandler           ; EXTI Line 1
                DCD     EXTI2_IRQHandler           ; EXTI Line 2
                DCD     EXTI3_IRQHandler           ; EXTI Line 3
                DCD     EXTI4_IRQHandler           ; EXTI Line 4
                DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
                DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
                DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
                DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
                DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
                DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
                DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
                DCD     ADC1_2_IRQHandler          ; ADC1 & ADC2
                DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
                DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
                DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
                DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
                DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
                DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
                DCD     TIM1_UP_IRQHandler         ; TIM1 Update
                DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
                DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare
                DCD     TIM2_IRQHandler            ; TIM2
                DCD     TIM3_IRQHandler            ; TIM3
                DCD     TIM4_IRQHandler            ; TIM4
                DCD     I2C1_EV_IRQHandler         ; I2C1 Event
                DCD     I2C1_ER_IRQHandler         ; I2C1 Error
                DCD     I2C2_EV_IRQHandler         ; I2C2 Event
                DCD     I2C2_ER_IRQHandler         ; I2C2 Error
                DCD     SPI1_IRQHandler            ; SPI1
                DCD     SPI2_IRQHandler            ; SPI2
                DCD     USART1_IRQHandler          ; USART1
                DCD     USART2_IRQHandler          ; USART2
                DCD     USART3_IRQHandler          ; USART3
                DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
                DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line
                DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
                DCD     TIM8_BRK_IRQHandler        ; TIM8 Break
                DCD     TIM8_UP_IRQHandler         ; TIM8 Update
                DCD     TIM8_TRG_COM_IRQHandler    ; TIM8 Trigger and Commutation
                DCD     TIM8_CC_IRQHandler         ; TIM8 Capture Compare
                DCD     ADC3_IRQHandler            ; ADC3
                DCD     FSMC_IRQHandler            ; FSMC
                DCD     SDIO_IRQHandler            ; SDIO
                DCD     TIM5_IRQHandler            ; TIM5
                DCD     SPI3_IRQHandler            ; SPI3
                DCD     UART4_IRQHandler           ; UART4
                DCD     UART5_IRQHandler           ; UART5
                DCD     TIM6_IRQHandler            ; TIM6
                DCD     TIM7_IRQHandler            ; TIM7
                DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1
                DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel2
                DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel3
                DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
__Vectors_End

2.中断管理 - 中断优先级

STM32将中断分成5个组,分别为0-4组;同时对每个中断设置一个抢占优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。

在实际应用中一定要注意有时候由于中断优先级设置不合理会导致程序“截胡“。

1.抢占优先级。抢占优先级高的中断,可以打断抢占优先级低的中断。

2.响应优先级。抢占优先级相同的中断,响应优先级高的可以优先执行。

 

高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。

抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。

抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。

如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;

 

假定设置中断优先级组为2,然后设置

中断3(RTC中断)的抢占优先级为2,响应优先级为1。  中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断7(外部中断1)的抢占优先级为2,响应优先级为0。

那么这3个中断的优先级顺序为:中断7>中断3>中断6

3.中断管理 - 中断分组

分组配置是由SCB->AIRCR寄存器的bit10-8来定义的。SCB->AIRCR是CM3内核定义的。其中AIRCR寄存器来确定是用哪种分组,IP寄存器是相对应于那种分组抢占优先级和响应优先级的分配比例。例如组设置成2,那么此时所有的60个中断优先寄存器高4位中的最高2位是抢占优先级,低2位为响应优先级。Cortex-M3中定义了8个Bit用于设置中断源的优先级,而STM32只选用其中的最高4个Bit。

在STM32中把这些中断分为5组,如下

分组

SCB->AIRCR寄存器

IP bit[7:4]

抢占优先级和响应优先级

0

111

0:4

0位抢占优先级,4位响应优先级

1

110

1:3

1位抢占优先级,3位响应优先级

2

101

2:2

2位抢占优先级,2位响应优先级

3

100

3:1

3位抢占优先级,1位响应优先级

4

011

4:0

4位抢占优先级,0位响应优先级

/*misc.h*/

#define NVIC_PriorityGroup_0         ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
                                                            4 bits for subpriority */
#define NVIC_PriorityGroup_1         ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
                                                            3 bits for subpriority */
#define NVIC_PriorityGroup_2         ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
                                                            2 bits for subpriority */
#define NVIC_PriorityGroup_3         ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
                                                            1 bits for subpriority */
#define NVIC_PriorityGroup_4         ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
                                                            0 bits for subpriority */


 The table below gives the allowed values of the pre-emption priority and subpriority according
 to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function
  ============================================================================================================================
    NVIC_PriorityGroup   | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority  | Description
  ============================================================================================================================
   NVIC_PriorityGroup_0  |                0                  |            0-15             |   0 bits for pre-emption priority
                         |                                   |                             |   4 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------
   NVIC_PriorityGroup_1  |                0-1                |            0-7              |   1 bits for pre-emption priority
                         |                                   |                             |   3 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_2  |                0-3                |            0-3              |   2 bits for pre-emption priority
                         |                                   |                             |   2 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_3  |                0-7                |            0-1              |   3 bits for pre-emption priority
                         |                                   |                             |   1 bits for subpriority
  ----------------------------------------------------------------------------------------------------------------------------    
   NVIC_PriorityGroup_4  |                0-15               |            0                |   4 bits for pre-emption priority
                         |                                   |                             |   0 bits for subpriority                       
  ============================================================================================================================


4.库函数中断寄存器

在Keil中 core_cm3.h 这个NVIC_Type中控制着中断向量表中60个中断

typedef struct
{
  __IO uint32_t ISER[8];   /*!< Offset: 0x000  Interrupt Set Enable Register  只用了ISER[0]和ISER[1]   */
       uint32_t RESERVED0[24];                                   
  __IO uint32_t ICER[8];    /*!< Offset: 0x080  Interrupt Clear Enable Register         */
       uint32_t RSERVED1[24];                                    
  __IO uint32_t ISPR[8];  /*!< Offset: 0x100  Interrupt Set Pending Register中断挂起控制寄存器。通过置1可以将正在进行的中断挂起,执行同级或者更高级别的中断。写0无效。*/
       uint32_t RESERVED2[24];                                   
  __IO uint32_t ICPR[8];   /*!< Offset: 0x180  Interrupt Clear Pending Register中断解挂控制寄存器。通过置1可以将正在挂起的中断解挂。写0无效*/
       uint32_t RESERVED3[24];                                   
  __IO uint32_t IABR[8];  /*!< Offset: 0x200  Interrupt Active bit Register  这是一个只读寄存器,可以知道当前在执行的中断是哪一个(为1),在中断执行完后硬件自动清零。*/
       uint32_t RESERVED4[56];                                   
  __IO uint8_t  IP[240];   /*!< Offset: 0x300  Interrupt Priority Register (8Bit wide) 中断优先级控制的寄存器。这是用来控制每个中断的优先级。由于CM3由240个外部中断,每个中断由一个8位寄存器控制,但是STM32F10x系列一共60个可屏蔽中断,
所以只使用了IP[59]~IP[0]。其中每个IP寄存器的高4位[7:4]用来设置抢占和响应优先级(根据分组),低4位没有用到。而两个优先级各占几个位又要由上面讲到的中断优先级分组决定。
*/
       uint32_t RESERVED5[644];                                  
  __O  uint32_t STIR;   /*!< Offset: 0xE00  Software Trigger Interrupt Register     */
}  NVIC_Type;
typedef struct
{
  __I  uint32_t CPUID;     /*!< Offset: 0x00  CPU ID Base Register                                  */
  __IO uint32_t ICSR;    /*!< Offset: 0x04  Interrupt Control State Register                      */
  __IO uint32_t VTOR;  /*!< Offset: 0x08  Vector Table Offset Register                          */
  __IO uint32_t AIRCR;  /*!< Offset: 0x0C  Application Interrupt / Reset Control Register        */
  __IO uint32_t SCR;  /*!< Offset: 0x10  System Control Register                               */
  __IO uint32_t CCR;  /*!< Offset: 0x14  Configuration Control Register                        */
  __IO uint8_t  SHP[12];    /*!< Offset: 0x18  System Handlers Priority Registers (4-7, 8-11, 12-15) */
  __IO uint32_t SHCSR;  /*!< Offset: 0x24  System Handler Control and State Register             */
  __IO uint32_t CFSR;  /*!< Offset: 0x28  Configurable Fault Status Register                    */
  __IO uint32_t HFSR;  /*!< Offset: 0x2C  Hard Fault Status Register                            */
  __IO uint32_t DFSR;  /*!< Offset: 0x30  Debug Fault Status Register                           */
  __IO uint32_t MMFAR;  /*!< Offset: 0x34  Mem Manage Address Register                           */
  __IO uint32_t BFAR;  /*!< Offset: 0x38  Bus Fault Address Register                            */
  __IO uint32_t AFSR;  /*!< Offset: 0x3C  Auxiliary Fault Status Register                       */
  __I  uint32_t PFR[2];  /*!< Offset: 0x40  Processor Feature Register                            */
  __I  uint32_t DFR;  /*!< Offset: 0x48  Debug Feature Register                                */
  __I  uint32_t ADR;  /*!< Offset: 0x4C  Auxiliary Feature Register                            */
  __I  uint32_t MMFR[4];   /*!< Offset: 0x50  Memory Model Feature Register                         */
  __I  uint32_t ISAR[5];  /*!< Offset: 0x60  ISA Feature Register                                  */
} SCB_Type;

5.具体应用中断初始化

中断优先级设置

一般情况下,系统代码执行过程中,只设置一次中断优先级分组.

设置中断优先级分组为组2:2位抢占优先级,2位响应优先级

5.1中断分组设置

/*函数调用*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

/*库函数源码*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
  
  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

5.2中断优先级设置

/*函数调用*/
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能

NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器


/*库函数源码*/

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
  uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
  
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
  assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));  
  assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
    
  if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
  {
    /* Compute the Corresponding IRQ Priority --------------------------------*/    
    tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
    tmppre = (0x4 - tmppriority);
    tmpsub = tmpsub >> tmppriority;

    tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
    tmppriority |=  NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
    tmppriority = tmppriority << 0x04;
        
    NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
    
    /* Enable the Selected IRQ Channels --------------------------------------*/
    NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
  else
  {
    /* Disable the Selected IRQ Channels -------------------------------------*/
    NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
      (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
  }
} 

6.中断嵌套

具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,这样就形成了低优先级中断中嵌套着高优先级中断,当高优先级中断来的时候可以打断正在运行的低优先级中断。

当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个

猜你喜欢

转载自blog.csdn.net/yuupengsun/article/details/107445635