STM32的NVIC详解

NVIC

  • 在NVIC的中断控制及状态寄存器中,有一个VECTACTIVE位段;特殊功能寄存器ISR,都记录了当前正服务异常的编号。
  • 如果一个中断不能立即响应,就称它被“悬起”(pending)。少数fault不允许被悬起,可能是系统当前正在执行一个更高优先级异常的服务例程,或者相关掩蔽位被设置导致异常被除能
  • 每个异常源,在被悬起的情况下,都会有一个对应的“悬起状态寄存器”保存其异常请求,直到该异常能执行
  1. NVIC寄存器

    1. NVIC访问地址是0xE000 E000,
    2. 所有NVIC的中断控制/状态寄存器都只能在特权级下访问
    3. 软件触发中断寄存器可以在用户级下访问以产生软件中断
    4. 所有中断控制/状态寄存器均可以按 半字/字节的方式访问
    5. 有些中断屏蔽寄存器(特殊功能寄存器)只能通过 MRS/MSR及CPS来访问
  2. 中断的使能与除能(SETENA/CLRENA)

                共240对使能/除能位,每个中断有一对,分布在8对32位寄存器中(0~8 + 0~8 = 16)

                欲使能一个中断,需要写1到对应SETENA的位中,0无效

                欲除能一个中断,需要写1到对应CLRENA的位中,0无效

                中断 0 的异常号是 16

  1. 中断的悬起与解悬(SETPEND/CLRPEND)

        当中断正发生时,正在处理同级或高优先级异常时,或被掩蔽,则中断不能立即得到响应,此时中断被悬起,中断的悬起状态可以通过"中断设置悬起寄存器(SETPEND)""中断悬起清除寄存器(CLRPEND)"来读取,还可以写来手工悬起中断.

悬起寄存器和解悬寄存器也有8对(8 + 8 = 16)

 

中断优先级

        每个外部中断都有一个对应的优先级寄存器,每个寄存器占8位,最少只使用最高3位

        4个相邻的寄存器拼成一个32位寄存器

 

活动状态(中断激活标志位)

        每个外部中断都有一个活动状态位,处理完ISR的第一条指令后,活动状态被1,直到ISR返回时才硬件0, 该寄存器只读

哪怕一个中断被抢占,其活动状态依然为1

 

STM32的NVIC软件配置程序

ST官方 NVIC控制结构体如下:

ISER[8]:ISER ( Interrupt Set-Enable Registers): 中断使能寄存器组

8个32位寄存器来控制,每个位控制一个中断,使能设置相应ISER位为1

由于STM32F1系列最多68个中断,所以只用到了 ISER[0~2]

 

ICER[8]ICER( Interrupt Clear-Enable Registers): 中断除能寄存器组

8个32位寄存器来控制,每个位控制一个中断,除能设置相应ICER位为1

 

ISPR[8]ISPR(Interrupt Set-Pending Registers): 中断挂起控制寄存器组

8个32位寄存器来控制,每个位控制一个中断,中断挂起设置相应ISPR位为1

 

ICPR[8]ICPR(Interrupt Clear-Pending Registers):中断解挂控制寄存器组

8个32位寄存器来控制,每个位控制一个中断,中断解挂设置相应ICPR位为1

 

IABR[8]IABR(Interrupt Active Bit Registers):  中断激活标志位

832位寄存器来控制,每个位控制一个中断,只读,当前正在执行的中断被设置成1,执行完后自动清0

 

IP[240]IP(Interrupt Priority Registers): 中断优先级控制寄存器组

240个8位的寄存器来控制,STM32F1可屏蔽中断只用到了前68个(IP[67]~IP[0])

每个8位寄存器只用到了高4位( bit[7:4] ), 抢占优先级在前,子优先级在后

优先级各占几个位根据 SCB->AIRCR [10:8] 来决定

 

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

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

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

 

NVIC分组函数 MY_NVIC_PriorityGroupConfig

//STM32只分了5个组(0~4)

void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)

{

u32 temp, temp1;

temp1 = (~NVIC_Group)&0x07; //取后三位

temp1 <= 8;

temp = SCB->AIRCR;    //读取先前的设置

temp &= 0X0000F8FF;   //清空先前分组

temp |= 0X05FA0000;    //写入钥匙

temp |= temp1;

SCB->AIRCR = temp;    //设置分组

}

NVIC设置函数 MY_NVIC_Init

//设置 NVIC

//NVIC_PreemptionPriority: 抢占优先级

//NVIC_SubPriority : 响应优先级

//NVIC_Channel : 中断编号

//NVIC_Group : 中断分组 0~4

//注意优先级不能超过设定的组的范围!否则会有意想不到的错误

//组划分:

//组 0: 0 位抢占优先级, 4 位响应优先级

//组 1: 1 位抢占优先级, 3 位响应优先级

//组 2: 2 位抢占优先级, 2 位响应优先级

//组 3: 3 位抢占优先级, 1 位响应优先级

//组 4: 4 位抢占优先级, 0 位响应优先级

//NVIC_SubPriority 和 NVIC_PreemptionPriority 的原则是, 数值越小, 越优先

 

void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)

{

u32 temp;

MY_NVIC_PriorityGroupConfig(NVIC_Group);   //设置分组

temp = NVIC_PreemptionPriority << (4-NVIC_Group); 

temp |= NVIC_SubPriority & (0x0f>>NVIC_Group);

temp &= 0xf; //取低四位

NVIC->ISER[NVIC_Channel/32] |= (1<<NVIC_Channel%32);   //使能中断位

NVIC->IP[NVIC_Channel] |= temp<<4; //设置响应优先级和抢断优先级

}

STM32的外部中断软件程序

IMR: 中断屏蔽寄存器,32位, 只有前19位有效( bit[18:0] )

设置为1开启这个线上的中断,否则关闭该线上的中断

 

EMR: 事件屏蔽寄存器, 32位,  只有前19位有效( bit[18:0] )

设置为1开启这个线上的事件,否则关闭该线上的事件

 

RTSR:上升沿触发选择寄存器, 32位, 前19位有效( bit[18:0] )

设置为1允许上升沿触发中断/事件, 否则不允许

FTSR:下降沿触发选择寄存器, 32位, 前19位有效( bit[18:0] )

设置为1允许下降沿触发中断/事件, 否则不允许, 上升沿和下降沿可以同时设置,任意电平触发

 

SWIER: 软件中断事件寄存器, 32位

未设置IMR和EMR时写1,将会挂起PR的相应位,设置了IMR和EMR时将产生一次中断

SWIER被设置的位将会在PR中对应位清除后清除

 

PR: 挂起寄存器, 32位

当外部中断线上发生了选择的边沿事件,该寄存器的对应位会被置1

通过对该寄存器写1可以清除该位,以清除中断请求

 

EXTICR:外部中断复用寄存器, 32位,只用低16位

EXTICR[0] ~ EXTICR[3] 对应 AFIO_EXTICR1~4

 

外部中断配置 Ex_NVIC_Config

/**

  * @brief  外部中断配置函数,只针对GPIOA~G;

  *     不包括PVD,RTC和USB唤醒这三个

  *     该函数一次只能配置1个IO口,多个IO口,需多次调用

  * @param  GPIOx:0~6,代表GPIOA~G

  *     BITx:需要使能的位

  *     TRIM:触发模式,1,下升沿;2,上降沿;3,任意电平触发

  * @retval None

  */

void Ex_NVIC_Config(u8 GPIOx, u8 BITx, u8 TRIM)

{

u8 EXTADDR;

u8 EXTOFFSET;

EXTADDR = BITx/4; //得到中断寄存器组的编号

EXTOFFSET = (BITx%4)*4; //得到中断线

RCC->APB2ENR |= 0x01; //使能 io 复用时钟

AFIO->EXTICR[EXTADDR] &= ~(0x000F<<EXTOFFSET);  //清除原来设置!!!

AFIO->EXTICR[EXTADDR] |= GPIOx<<EXTOFFSET;    //EXTI.BITx 映射到 GPIOx.BITx

//自动设置

EXTI->IMR |= 1<<BITx; //开启 line BITx 上的中断

if(TRIM&0x01)EXTI->FTSR |=1<< BITx; //line BITx 上事件下降沿触发

if(TRIM&0x02)EXTI->RTSR |=1<< BITx; //line BITx 上事件上升降沿触发}

}

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值