STM32F1中断NVIC

目录

[1. 中断系统](#1. 中断系统)

[2. 中断向量表](#2. 中断向量表)

[3. NVIC基本结构](#3. NVIC基本结构)

[4. NVIC优先级分组](#4. NVIC优先级分组)

[5. NVIC程序编写](#5. NVIC程序编写)

[5.1 中断分组](#5.1 中断分组)

[5.2 中断结构体变量](#5.2 中断结构体变量)

[5.3 中断通道选择](#5.3 中断通道选择)

[5.4 抢占优先级和响应优先级配置](#5.4 抢占优先级和响应优先级配置)

[6. 中断程序执行](#6. 中断程序执行)


1. 中断系统

中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行

在此时的断点部分,若是此时主程序还在进行例如加减乘除运算,但是突然有个更加紧急的的事情需要处理,可以在此时进行中断,优先处理更加紧急的事情,等事情处理完后,在返回主程序继续处理。

在中断这里,我们在断点处离开,编译器会自动帮我们保护现场(当前程序),等我们回来(中断完成后),继续工作。

中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源

例如:两个人同时就医,急诊和门诊。

中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

STM32F1系列包含最多:68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设。

使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级

2. 中断向量表

灰色部分为内核中断,了解即可,一般用不上,初学者可以不用那么深入。

这里仅做了解,编译器已经帮我们做好了。

中断函数的地址由编译器来进行分配的,是不固定的,但是终端的跳转因为硬件的限制,只能调到固定的地址进行程序的执行,为了让硬件跳转到不固定的一个中断函数里,这里需要在中断函数里定义一个地址的列表,列表地址是固定的,中断发生后跳到这个位置,在这个固定位置由编译器,再加上一条跳转到中断函数的代码,这样就可以调到任意位置。

3. NVIC基本结构

NVIC:嵌套中断向量控制器

统一分配中断优先级,和管理中断

NVIC内核外设,CPU的小助手

米色圈住部分,意思是:一个外设可能会占用多个中断通道,所以这里有"n"条线,NVIC只有一个输出口,NVIC根据每个中断的优先级进行分配中断的先后顺序。

例如:医院叫号,CPU为医生,NVIC进行排号,中断是病人,NVIC根据病人的紧急程度进行排号,找医生。

4. NVIC优先级分组

NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级

抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

对于响应优先级,相当于"插队",此时"1"在看病(程序在进行中),"4"要是比较严重,"4"可以进行插队到"2"前面,但是要等"1"看完(进程走完)

对于抢占优先级(中断嵌套),相当于"1"在看病(程序在进行中),"4"不等"1"看完直接冲到屋内,把"1"推到一边,"4"先看病(进行),"4"先看完,在进行"1",再依次进行后续的操作。

5. 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);

5.1 中断分组

/**
  * @brief  Configures the priority grouping: pre-emption priority and subpriority.
  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 
  *   This parameter can be one of the following values:
  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
  *                                4 bits for subpriority
  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
  *                                3 bits for subpriority
  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
  *                                2 bits for subpriority
  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
  *                                1 bits for subpriority
  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
  *                                0 bits for subpriority
  * @retval None
  */
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
  /* Check the parameters */
  assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
  
  /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
  SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}

根据需求,配置所需要的分组,几个抢占,几个响应。

这里我们选择分组2,两个抢占,两个响应

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组

注意:分组方式整个芯片只能用一种

5.2 中断结构体变量

	NVIC_InitTypeDef NVIC_InitStructure;

5.3 中断通道选择

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

要是我们配置PC13引脚,则:

	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;

5.4 抢占优先级和响应优先级配置

根据如图分组进行配置,我们配置为分组"2",则抢占优先级和响应优先级的取值都为"0~3",由于我们只配置一个引脚所以这里全给"1"。

	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

完整初始化:

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组,
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);	

6. 中断程序执行

void EXTI15_10_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line14) == SET)
	 {
			EXTI_ClearITPendingBit(EXTI_Line14);
	}
}

学习笔记,仅供参考。

相关推荐
2401_843785232 小时前
STM32 AD多通道
stm32·单片机·嵌入式硬件
厂太_STAB_丝针3 小时前
【自学嵌入式(8)天气时钟:天气模块开发、主函数编写】
c语言·单片机·嵌入式硬件
charlie1145141914 小时前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(协议层封装)
c语言·驱动开发·单片机·学习·教程·oled
简知圈8 小时前
【04-自己画P封装,并添加已有3D封装】
笔记·stm32·单片机·学习·pcb工艺
徐某人..8 小时前
ARM嵌入式学习--第十天(UART)
arm开发·单片机·学习·arm
Ronin-Lotus10 小时前
嵌入式硬件篇---CPU&GPU&TPU
嵌入式硬件·学习·cpu·gpu·tpu
LS_learner12 小时前
42步进电机
嵌入式硬件
LS_learner12 小时前
PCA9685 一款由 NXP Semiconductors 生产的 16 通道、12 位 PWM(脉宽调制)控制器芯片
嵌入式硬件
stm32发烧友16 小时前
基于 STM32 的智能电梯控制系统
stm32·单片机·嵌入式硬件
快秃头的码农17 小时前
ESP32-c3实现获取土壤湿度(ADC模拟量)
单片机·嵌入式硬件