STM32F10xNVIC探究与学习_2021-04-24

NVIC探究与学习

嵌套向量中断控制器( NVIC
NVIC 驱动有多种用途:例如使能或者失能 IRQ 中断,使能或者失能单独的 IRQ 通道,改变 IRQ 通道的优
先级等等
NVIC
Enable 中断设置使能寄存器
Disable 中断清除使能寄存器
Set 中断设置待处理寄存器
Clear 中断清除待处理寄存器
Active 中断活动位寄存器
Priority 中断优先级寄存器
//NVIC 寄存器结构,NVIC_TypeDeff,在文件“stm32f10x_map.h”中定义如下:
typedef struct 
{ 
vu32 Enable[2]; 
u32 RESERVED0[30]; 
vu32 Disable[2]; 
u32 RSERVED1[30]; 
vu32 Set[2]; 
u32 RESERVED2[30]; 
vu32 Clear[2]; 
u32 RESERVED3[30]; 
vu32 Active[2]; 
u32 RESERVED4[62]; 
vu32 Priority[11]; 
} NVIC_TypeDef;/* NVIC Structure */ 
typedef struct
 
SCB
CPUID CPU ID 基寄存器
IRQControlStatus 中断控制状态寄存器
ExceptionTableOffset 向量表移位寄存器
AIRC 应用控制/ 重置寄存器
SysCtrl 系统控制寄存器
ConfigCtrl 设置控制寄存器
SystemPriority 系统处理优先级寄存器
SysHandlerCtrl 系统处理控制和状态寄存器
ConfigFaultStatus 设置错误状态寄存器
HardFaultStatus 硬件错误状态寄存器
DebugFaultStatus 除错错误寄存器
MemorymanageFaultAddr 存储器管理错误地址寄存器
BusFaultAddr 总线错误地址寄存器

 

typedef struct 
{ 
vu32 CPUID; 
vu32 IRQControlState; 
vu32 ExceptionTableOffset; 
vu32 AIRC; 
vu32 SysCtrl; 
vu32 ConfigCtrl; 
vu32 SystemPriority[3]; 
vu32 SysHandlerCtrl; 
vu32 ConfigFaultStatus; 
vu32 HardFaultStatus; 
vu32 DebugFaultStatus; 
vu32 MemoryManageFaultAddr; 
vu32 BusFaultAddr; 
} SCB_TypeDef; /* System Control Block Structure */

函数

NVIC函数较多,配置一个中断似乎看上去并不容易。我们需要先理解NVIC工作原理

1.什么是优先级分组

寄存器高四位用于配置优先级

  • 抢占优先级越小,优先级越高;相同抢占优先级的中断不能嵌套;
  • 相同抢占优先级N个中断发生时,响应优先级越小的中断首先执行(不能嵌套),如果响应优先级也均相同,则根据各中断对应向量表的位置来确定,向量表中越靠前的中断先响应。
  • 参考STM32中的NVIC详解_Adamsky-CSDN博客

2.如何配置NVIC

Step.1 分组函数NVIC_PriorityGroupConfig

参数列表
 

Step.2 定义初始化结构体NVIC_InitTypeDef structure

//NVIC_InitTypeDef structure 
//NVIC_InitTypeDef 定义于文件“stm32f10x_nvic.h”:
typedef struct 
{ 
u8 NVIC_IRQChannel; //该参数用以使能或者失能指定的 IRQ 通道
u8 NVIC_IRQChannelPreemptionPriority; //该参数设置了成员 NVIC_IRQChannel 中的先占优先级
u8 NVIC_IRQChannelSubPriority; //该参数设置了成员 NVIC_IRQChannel 中的从优先级
FunctionalState NVIC_IRQChannelCmd; //设置IRQ通道使能/失能
} NVIC_InitTypeDef;

Step.3 配置初始化结构体

NVIC_InitTypeDef NVIC_InitStructure; 
/* Configure the Priority Grouping with 1 bit */ 
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 
/* Enable TIM3 global interrupt with Preemption Priority 0 and Sub 
Priority as 2 */ 
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;    //IRQ通道参考Table.272
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;    //抢占优先级0(值越低优先级越高)
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;    //从优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    //IRQ通道使能

参数列表

设置优先级的时候要考虑周全,不要在高优先级中调用低优先级的中断
例如在USART1中断中调用Delay函数时要将USART优先级调低不能高于Delay
 
 

Step.4 调用NVIC_InitStructure(&NVIC_InitStructure)函数将值写入寄存器

NVIC_InitStructure(&NVIC_InitStructure);    //初始化函数将参数写入寄存器

至此就完成了NVIC的分组配置和优先级配置,在对应的模块使能中断后就可以使用中断了

例如

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
NVIC_InitTypeDef NVIC_InitStructure;	 
//Usart1 NVIC 配置
    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);	//根据指定的参数初始化NVIC寄存器 

USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);    //使用串口中断方式接收数据

Step.5 编写中断函数

void USART1_IRQHandler(void){ //串口1中断服务程序(固定的函数名不能修改)	
	u8 Res;
	//以下是字符串接收到USART_RX_BUF[]的程序,(USART_RX_STA&0x3FFF)是数据的长度(不包括回车)
	//当(USART_RX_STA&0xC000)为真时表示数据接收完成,即超级终端里按下回车键。
	//在主函数里写判断if(USART_RX_STA&0xC000),然后读USART_RX_BUF[]数组,读到0x0d 0x0a即是结束。
	//注意在主函数处理完串口数据后,要将USART_RX_STA清0
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){  //接收中断(接收到的数据必须是0x0d 0x0a结尾)		
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
		printf("%c\n",Res); //把收到的数据以 a符号变量 发送回电脑	
		a=Res;
		if((USART_RX_STA&0x8000)==0){//接收未完成			
			if(USART_RX_STA&0x4000){//接收到了0x0d				
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}else{ //还没收到0X0D					
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; //将收到的数据放入数组
					USART_RX_STA++;	//数据长度计数加1
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}   		 
	} 
} 

外设初始化时不要忘记启用中断,如USART_ITConfig(USART1, USART_IT_RXNE, Enable);//开启ENABLE

中断函数在参考手册向量表或者启动文件中可找到,函数名是固定的(如果没修改启动文件)

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值