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);
	}
}

学习笔记,仅供参考。

相关推荐
7yewh1 小时前
嵌入式硬件实战提升篇(一)-泰山派RK3566制作多功能小手机
linux·arm开发·驱动开发·嵌入式硬件·物联网·智能手机·硬件架构
@晓凡2 小时前
STM32编程遇到的问题随笔【一】
stm32·单片机·嵌入式硬件
DevinLGT4 小时前
6Pin Type-C Pin脚定义:【图文讲解】
人工智能·单片机·嵌入式硬件
小A1595 小时前
STM32完全学习——系统时钟设置
stm32·嵌入式硬件·学习
CoderBob5 小时前
【EmbeddedGUI】脏矩阵设计说明
c语言·单片机
陌夏微秋6 小时前
51单片机基础02 动态数码管显示-并串转换
arm开发·单片机·嵌入式硬件·51单片机·硬件工程·信息与通信·信号处理
面包板扎6 小时前
51单片机应用开发---LCD1602显示应用
单片机·嵌入式硬件·51单片机
面包板扎6 小时前
51单片机应用开发(进阶)---定时器应用(电子时钟)
单片机
好想有猫猫7 小时前
【51单片机】LCD1602液晶显示屏
c语言·单片机·嵌入式硬件·51单片机·1024程序员节
陌夏微秋7 小时前
51单片机基础01 单片机最小系统
单片机·嵌入式硬件·51单片机·硬件工程·信息与通信