STM32学习笔记---NVIC/EXIT中断

本文借鉴该博客:
点此跳转

NVIC,全程嵌套向量控制器

在这里插入图片描述
(来自正点原子官方ppt,其中的中断82个,但是只会用到一部分,比如外部中断,串口中断,pwm输出事件中断等)
单片机的单字(我只是记得,出处未找到),某种程度上可以理解为某个时刻单片机只会执行一行代码,C语言的代码是按照流程执行的,如果想在执行这个代码过程中因为特定的条件发生,比如接受到信号,比如计数达到重装载值等,执行的任务从当前任务跳出,去执行指定函数的功能,完成后再回来继续执行原来执行到一半的代码。(如有错误,欢迎指正,毕竟也算是个小白)
如果有多个可能要执行的中断任务,就要给他们根据需求排序,即规定好他们的优先级。在中断优先级设置中,有抢占优先级和响应优先级之分:

在这里插入图片描述
可以举个例子:我们在设置中断优先级分组时,使用库函数:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
 
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
  
 
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

------------------------------------------------------------------------

IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \
                                       ((GROUP) == NVIC_PriorityGroup_1) || \
                                       ((GROUP) == NVIC_PriorityGroup_2) || \
                                       ((GROUP) == NVIC_PriorityGroup_3) || \
                                       ((GROUP) == NVIC_PriorityGroup_4))

我们使用参数NVIC_PriorityGroup_2,代表2位抢占优先级,2位响应优先级,抢占优先级可以取值0-3,响应优先级0-3。如果中断A抢占优先级0,响应优先级;中断B抢占优先级0,响应优先级1;中断C抢占优先级1,响应优先级0.
则优先级:A高于B,高于C
即优先级:先比较抢占优先级大小,再比较响应优先级大小;规定,越接近0,其优先级越大。
在设置优先级时候,需要做以下初始化:

 	NVIC_InitStructure.NVIC_IRQChannel = //多个中断通道,具体见stmf4xx.h
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			
	NVIC_Init(&NVIC_InitStructure);	

在解决完初始化之后,就可以从startup_stm32f40_41xxx.s中找相关的中断函数,函数的功能有自己来写,这里只是一个例子:

在这里插入图片描述
每一个可以使用中断的通道都有固定的中断函数可以自定义。
—————————————————————————————

EXIT 外部中断

可以以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发)
stm32的每个IO口都可以作为外部中断输入,stm32中断控制器支持22个外部中断/事件请求:
在这里插入图片描述
对应的IO口情况如下:
在这里插入图片描述
IO有16组,中断线有16个,但是中断服务函数并不是16个
在这里插入图片描述
在这里插入图片描述
现在来看下例程:

void EXTIX_Init(void)
{
	NVIC_InitTypeDef   NVIC_InitStructure;
	EXTI_InitTypeDef   EXTI_InitStructure;
	
	KEY_Init();
 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//EXIT的中断部分使用的时钟
	
 
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
	

  EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //例程中对应WAKE_UP键
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	

  


EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3 | EXTI_Line4;//对应KEY0,KEY1,KEY2
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;


  EXTI_Init(&EXTI_InitStructure);
 
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	   
}

相应的中断函数

void EXTI0_IRQHandler(void)
{
	delay_ms(10);	//用于消抖
	if(WK_UP==1)	 
	{
		BEEP=!BEEP; 
	}		 
	 EXTI_ClearITPendingBit(EXTI_Line0); //清除中断标志位
}	

void EXTI2_IRQHandler(void)
{
	delay_ms(10);	
	if(KEY2==0)	  
	{				 
   LED0=!LED0; 
	}		 
	 EXTI_ClearITPendingBit(EXTI_Line2);
}

void EXTI3_IRQHandler(void)
{
	delay_ms(10);	
	if(KEY1==0)	 
	{
		LED1=!LED1;
	}		 
	 EXTI_ClearITPendingBit(EXTI_Line3);  
}

void EXTI4_IRQHandler(void)
{
	delay_ms(10);	
	if(KEY0==0)	
	{				 
		LED0=!LED0;	
		LED1=!LED1;	
	}		 
	 EXTI_ClearITPendingBit(EXTI_Line4);
}

外部中断和外部事件

中断在这些代码中,有一个地方需要注意,即

EXTI_InitStructure.EXTI_Line = EXTI_Line2 | EXTI_Line3 | EXTI_Line4;//对应KEY0,KEY1,KEY2
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; 
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

第二行代码,代表使用的是外部中断。实际上,除了外部中断,我们还可以使用外部事件,具体原理图如下:
在这里插入图片描述
图和解析来源在文章开头。
大概意思为外部事件需要借助DMA,A/D通道,这样可以在不借助CPU来输出一定信号;中断则需要CPU支持来完成

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值