stm32专题六:中断 NVIC

stm32的中断分为 1.抢占优先级。 2.子优先级。

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

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

其实,子优先级主要给出了一种响应的优先队列。假设中断的抢占优先级都相同。如果有多个相同抢占优先级的中断来了 ,那么他们不会互相打断,但是他们后续的排队会按照子优先级排队。也就是说,在第一个中断没有执行完的期间内,后续的最高级的子优先级是被安排到最高等待位处理的。

NVIC设置流程:

  1. 定义NVIC初始化结构体;
  2. 配置优先级分组;
  3. 往NVIC初始化结构体中填充,如中断源,抢占优先级,子优先级,使能等;
  4. 调用NVIC初始化函数;
  5. 编写中断服务函数;
static void EXTI_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStruct;

    // 先设置中断优先级分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	
    NVIC_Init(&NVIC_InitStruct);
}

void EXTI0_IRQHandler(void)
{
	// 判断是否发生中断
	// 与函数FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);功能相同
	if (EXTI_GetITStatus(EXTI_Line0) != RESET)
	{
		LED_R_TOGGLE;
	}
	// 清除标志位,往EXTI_PR寄存器写1,与函数void EXTI_ClearFlag(uint32_t EXTI_Line)功能相同
	// 之所有一个功能有两个一样的函数,是为了兼容旧的固件库
	EXTI_ClearITPendingBit(EXTI_Line0);
}

stm32的中断可以分为系统异常10个(内核)和外部中断60个(外设)。NVIC是内核的外设,管理包括内核和片上外设所有的中断功能,在core_cm3.h和misc.h中。

NVIC的寄存器描述:

ISER:中断使能寄存器,对应60个外设的不可屏蔽中断,其中NVIC_ISER0的0~31位对应着中断向量表中的编号0~31,NVIC_ISER1对应着32~63,ISER2对应剩余位,其中还存在一些保留位,要想开启特定的中断,设置特定的位就可以。

ICER:中断清除寄存器,对应60个外设的不可屏蔽中断。与ISER类似,要想清除特定的中断,设置特定的位就可以。

ISPR:中断挂起寄存器,可挂起正在执行的中断,设置特定位。当置位此寄存器时,这个中断不会立即执行,而是等待可执行的时候再执行;比如高低级别的中断同时产生,CPU会自然的将低级别的中断挂起,当高优先级中断执行完毕后,再去处理低优先级中断,这个时候需要清除挂起位(使用ICPR),然后执行低级别中断。

ICPR:中断解除挂起寄存器,可以解除被挂起的中断。

IABR:中断激活标志寄存器(只读),可读取该寄存器判断当前执行的中断是哪个,中断执行完硬件清零。

IPR:中断优先级寄存器,用于中断分组。

STIR:软件触发中断寄存器,用于系统任务调度,编写SDK(不让别人看到代码)。

core_cm3.h中的NVIC结构体:

typedef struct
{
    __IO uint32_t ISER[8];                      /*!< Offset: 0x000  Interrupt Set Enable Register           */
    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          */
    uint32_t RESERVED2[24];
    __IO uint32_t ICPR[8];                      /*!< Offset: 0x180  Interrupt Clear Pending Register        */
    uint32_t RESERVED3[24];
    __IO uint32_t IABR[8];                      /*!< Offset: 0x200  Interrupt Active bit Register           */
    uint32_t RESERVED4[56];
    __IO uint8_t  IP[240];                      /*!< Offset: 0x300  Interrupt Priority Register (8Bit wide) */
    uint32_t RESERVED5[644];
    __O  uint32_t STIR;                         /*!< Offset: 0xE00  Software Trigger Interrupt Register     */
}  NVIC_Type;

stm32设计了8个ISER寄存器,实际上只用到其中的3个,之所以设计这么多组,是为了后续内核和外设资源的升级来考虑的,中间有24个保留地址,总共是32个32位地址,所以ICER的偏移地址为0X80(每4个地址增加0X10),以此类推。

值得注意的是,设置中断优先级的寄存器是8位有效(ARM规定),实际上stm32只使用了高4位,忽略低4位。但是中断优先级寄存器IPR是32位的,因此,每8位寄存器为一个优先级数组IP,每个IPR寄存器表示4个IP优先级分组,如下图:

misc.h中实现了NVIC所有的功能函数:

// 优先级分组
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
// NVIC初始化
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
// 设置中断向量表
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
// 设置系统进入低功耗模式
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
// 设置内核时钟来源,72M或72M/8=9M(8分频)
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);

NVIC初始化结构体

/** 
  * @brief  NVIC Init Structure definition  
  */

typedef struct
{
  uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.
                                                   This parameter can be a value of @ref IRQn_Type 
                                                   (For the complete STM32 Devices IRQ Channels list, please
                                                    refer to stm32f10x.h file) */

  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
                                                   specified in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */

  uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
                                                   in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */

  FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
                                                   will be enabled or disabled. 
                                                   This parameter can be set either to ENABLE or DISABLE */   
} NVIC_InitTypeDef;
 
/**
  * @}
  */

/** @defgroup NVIC_Priority_Table 
  * @{
  */

/**
@code  
 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                       
  ============================================================================================================================

当接收到两个中断,先比较主优先级(抢占优先级),再比较子优先级,如果均相等,则比较硬件中断编号。

中断编程的顺序:

  1. 使能中断请求(包括外设和NVIC);
  2. 配置中断优先级分组;
  3. 配置NVIC寄存器,初始化NVIC_InitTypeDef;
  4. 编写中断服务函数;

1 注意:中断的使能有两扇大门,第一个是外设的中断使能,比如串口发送完成中断,则TCIE位要置1,这是一扇小门;然后要设置NVIC总开关,来接受外设的中断请求,这个大门就是NVIC的中断使能寄存器NVIC_ISER。

2 因为会存在多个中断,所以要设置优先级分组。

3 配置好优先级分组后,就要初始化NVIC结构体,包括中断源,主优先级,子优先级和中断使能。

typedef struct
{
  uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.
                                                   This parameter can be a value of @ref IRQn_Type 
                                                   (For the complete STM32 Devices IRQ Channels list, please
                                                    refer to stm32f10x.h file) */

  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
                                                   specified in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */

  uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
                                                   in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */

  FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
                                                   will be enabled or disabled. 
                                                   This parameter can be set either to ENABLE or DISABLE */   
} NVIC_InitTypeDef;

如果是ENABLE,则会根据上述信息配置相应的寄存器,如果是DISABLE,直接设置ICER清除中断使能。

4 编写中断服务函数

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值