STM32F1 - 中断优先级


1> STM32F103ZET6异常向量表

1

中断数量:70个

STM32F103ZET6有70个中断 = 60外设中断 + 10个系统中断;

问题来了:
70个中断中除了复位、NMI、硬件错误3个的中断优先级是固定的,
其他67个中断都可以改变,如何管理配置这些中断的优先级呢?


2> 中断优先级寄存器NVIC_IPRx

// core.cm3.h文件
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;   

NVIC的中断优先级寄存器,有240个,位宽为8位,
每个中断都由一个8位来控制,也就是能控制240个中断,
STM32F103ZET6只有70个中断,够够的。

 uint8_t  IP[240]; 

31

STM32F103只使用优先级控制寄存器IPn的高4位[7:4]


3> 中断优先级分组

通过配置SCB中AIRCR中[10~8]3位来确定IP中高4位的分组模式;
3

高抢占优先级,可以【打断】低抢占优先级程序;
子优先级没有抢占功能,同一抢占级中,高子优先级的先执行;

// 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 */

4> 例程:设置EXTI4中断优先级

第1步:
先设置优先级分组模式,一般主程序中设置1次;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		// 中断优先级分组

第2步:
设置具体中断的抢占优先级,子优先级;

NVIC_InitTypeDef NVIC_tmp;

NVIC_tmp.NVIC_IRQChannel = EXTI4_IRQn;			// 外部中断
NVIC_tmp.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级
NVIC_tmp.NVIC_IRQChannelSubPriority = 0;		// 子优先级
NVIC_tmp.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_tmp);

5> 例程:设置SysTick中断优先级

第1步:
先设置优先级分组模式,一般主程序中设置1次;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		// 中断优先级分组

第2步:
设置具体中断的抢占优先级,子优先级;

NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_PriorityGroup_2, 0, 0));

6> 为什么不能用NVIC_Init()设置Systick优先级?

uint8_t NVIC_IRQChannel; 是无符号的成员变量,而SysTick_IRQn是【-1】,
并且也有注释,NVIC_IRQChannel这个结构体成员用于STM32的外设,
SysTick属于CPU部分,所以要调用NVIC_SetPriority();

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) */
   
// 省略其他成员定义

} NVIC_InitTypeDef;

7> 函数NVIC_EncodePriority()

函数功能:

根据优先级分组,抢占优先级,子优先级,生成优先级数字,
给NVIC_SetPriority() 函数用

// core_cm3.h
/**
 * @brief  Encode the priority for an interrupt
 *  
 * @param  PriorityGroup    The used priority group
 * @param  PreemptPriority  The preemptive priority value (starting from 0)
 * @param  SubPriority      The sub priority value (starting from 0)
 * @return                  The encoded priority for the interrupt
 *
 * Encode the priority for an interrupt with the given priority group,
 * preemptive priority value and sub priority value.
 * In case of a conflict between priority grouping and available
 * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set.
 *
 * The returned priority value can be used for NVIC_SetPriority(...) function
 * 返回值用于NVIC_SetPriority();
 */
static __INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority)
{
  uint32_t PriorityGroupTmp = (PriorityGroup & 0x07);          /* only values 0..7 are used          */
  uint32_t PreemptPriorityBits;
  uint32_t SubPriorityBits;

  PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp;
  SubPriorityBits     = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS;
 
  return (
           ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) |
           ((SubPriority     & ((1 << (SubPriorityBits    )) - 1)))
         );
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值