关于STM32F407的NVIC、EXTI相关入门知识
作者:互联网
NVIC与EXTI关系
EXTI是ST公司在其STM32产品上扩展的外中断控制。它负责管理映射到GPIO引脚上的外中断和片内几个集成外设的中断(PVD,RTC alarm,USB wakeup,ethernet wakeup),以及软件中断。其输出最终被映射到NVIC的相应通道。因此,配置EXTI中断的过程必然包含对NVIC的配置,例如下面配置EXTI0的过程,就要首先配置EXTI控制器(使能相应的中断线,选择中断/事件模式,触发边沿极性),然后再配置NVIC控制器(EXTI0映射在NVIC上的通道号,中断优先级,中断屏蔽状态):------来源于STM32中EXTI(外部中断)和NVIC(嵌套向量中断)的关系 - 21ic电子网
NVIC
(内嵌 向量 中断 控制器(Nested Vectored Interrupt Controller))
NVIC优先级说明(一般编号越小,优先级越高)
Preemption Priority(抢占优先级)
- 抢占优先级高的可抢占低的,插队先执行;
- 若相同抢占优先级,先发生 先执行;
- 抢占优先级低的不可抢占低的,排队等待执行;
Sub Priority(子优先级又称响应优先级)
- 在抢占优先级相同时,响应优先级高的不可以打断的响应优先级低的;
- 在抢占优先级相同,且同时请求中断时,响应优先级高的先执行。
- 在抢占优先级相同,且同时请求中断时,响应优先级也相同时,根据异常中断向量表排位顺序决定谁先执行
关系:在抢占优先级相同的前提下,再判断子优先级才有意义
中断优先级分组
SCB_AIRCR(中断和复位控制寄存器 Application Interrupt And Reset Control Register)(SCB(SystemControl Block)只是一个结构体的名称)
组 | SCB_AIRCR[10:8] | IP bit[7:4]分配情况 | 分配结果 | 优先级 |
0 | 0b111 | 0:4 | 0位抢占优先级 4位响应优先级 | 1个抢占优先级 16个响应优先级 |
1 | 0b110 | 1:3 | 1位抢占优先级 3位响应优先级 | 2个抢占优先级 8个响应优先级 |
2 | 0b101 | 2:2 | 2位抢占优先级 2位响应优先级 | 4个抢占优先级 4个响应优先级 |
3 | 0b100 | 3:1 | 3位抢占优先级 1位响应优先级 | 8个抢占优先级 2个响应优先级 |
4 | 0b011 | 4:0 | 4位抢占优先级 0位响应优先级 | 16个抢占优先级 1个响应优先级 |
以组别3 (PriorityGroupCongfig_3)为例(SCB_AIRCR[10:8]与IP bit[7:4]是否有相连关系还没探究,有知道的小伙伴请留言一下,谢谢!)
SCB_AIRCR[10:8] IP bit[7:4] 位数 10 9 8 7 6 5 4 3 2 1 0 功能 1 0 0 保留 上面的二进制为4 抢占 响应 SCB_AIRCR[10:8]为0b100时二进制为4,则IP bit[7:4]以4为界,左边为抢占优先级,右边、包括4为响应优先级(不包括0~3),所以4左边有3位抢占优先级(也就是有8种),4右边包括自身有1位优先级(也就是有2种)。
以此类推。
库函数NVIC设置流程代码
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; //1.声明定义结构体类型NVIC_InitTypeDef的变量NVIC_InitStructure。(结构体定义在固件库misc.h)。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//2.中断优先级分组1(函数定义在固件库misc.h)。
//3.结构体4个成员初始化。
NVIC_InitStructure.NVIC_IRQChannel=EXTI1_IRQn;//(中断源)设置。
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//设置(抢占)优先级为0。(注意,这是组别1的抢占优先级0)
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;//设置(响应)优先级为2。(注意,这是组别1的响应优先级2)
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;// (使能)该中断。
NVIC_Init(&NVIC_InitStructure);//4.完成上述中断设置(函数定义在固件库misc.h)。
/*注意:上述成员初始化是为了将数据打包到结构体中,最后将结构体数据传入函数
NVIC_Init()内完成了1次设置。如若要设置多几个中断,只需要更改结构体成员数值,
再次传入函数NVIC_Init()即可。*/
}
NVIC设置流程总结
1.声明定义结构体类型NVIC_InitTypeDef的变量。
2.设置中断优先级分组
3.结构体4个成员初始化。
4.完成上述中断设置将结构体数据传入函数
EXTI(外部中断/事件控制器)
STM32F4系列EXTI支持23个外部中断/事件请求信号。其中:
EXTI线0~15:对应GPIO的外部中断,注意一条EXTI线的输入有A~I(字母系列)端口的某个同一位,如下:
注意:输入只能多选一,不能同时输入多个信号源。
库函数EXTI设置流程代码
以PA0配置为外部中断输入为例
下面用到的函数定义在
stm32f4xx_gpio.h
stm32f4xx_exti.h
misc.h
stm32f4xx_rcc.c
stm32f4xx_syscfg.h
void EXTIX_Init(void)
{
//1.声明定义各模块结构体类型的变量
GPIO_InitTypeDef GPIO_InitStructure;//初始化GPIO,声明结构体类型GIPO_InitTypeDef变量GPIO_InitStructure,函数定义在(stm32f4xx_gpio.h)
EXTI_InitTypeDef EXTI_InitStructure;//该结构类型定义在stm32f4xx_exti.h
NVIC_InitTypeDef NVIC_InitStructure;//该结构类型定义在misc.h (misc英文翻译:混杂的)
//2.开时钟(函数定义在stm32f4xx_rcc.c)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_GPIOA, ENABLE);//使能GPIO A端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟,使用GPIO外部中断时必须使能SYSCFG时钟
//3.初始化结构体GPIO_InitTypeDef成员(有5个成员,因为设置了输入模式,所以输出速度、类型不设置)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//选择(中断源)对应引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//引脚输入模式
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化
/*
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//输出类型,上面设置了输入模式,这里就不用设置了
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//输出速度
*/
GPIO_Init(GPIOA,&GPIO_InitStructure);//数据传入配置函数内完成配置
//4.设置 IO 口与中断线的映射关系,将GPIOA的0号引脚作为EXTI线0的信号输入引脚
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource0);//PA0 连接到中断线0,(该函数定义在stm32f4xx_syscfg.h)
//5.初始化结构体EXTI_InitStructure成员(4个成员)
EXTI_InitStructure.EXTI_Line = EXTI_Line0;//选择EXTI_LINE0线端口
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //触发模式为上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE0
EXTI_Init(&EXTI_InitStructure);//结构体EXTI_InitStructure各成员数据传入配置函数里完成配置
//6.设置中断优先级组别
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//中断优先级分组1(函数定义在固件库misc.h)。
//7.初始化结构体NVIC_InitStructure成员(4个成员)
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//设置外部中断0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;//子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能该外部中断通道
NVIC_Init(&NVIC_InitStructure);//数据传入配置函数内完成配置
}
EXTI设置流程总结:
1.声明定义各模块结构体类型的变量 (GPIO,EXTI,NVIC模块)
2.开时钟(GPIO时钟和SYSCFG时钟)
3.初始化结构体GPIO_InitTypeDef成员
4.设置 IO 口与中断线的映射关系
5.初始化结构体EXTI_InitStructure成员
6.设置中断优先级组别
7.初始化结构体NVIC_InitStructure成员(4个成员)
判断EXTI线中断状态/清除EXTI中断标志位
以产生外部中断一次,LED灯亮灭反转为例的中断服务函数
void EXTI0_IRQHandler(void)//(自己定义的函数名称)
{
if( EXTI_GetITStatus(EXTI_Line0) == SET )//判断EXTI线中断状态,因为上面程序设置了上升沿触发,IO口产生电平上升沿即会进入中断,进入中断后返回SET,否则返回RESET。
{
LED1 = !LED1;//(自定义的函数)LED灯状态反转
EXTI_ClearITPendingBit(EXTI_Line0);//该函数是清除EXTI中断时产生的标志位,挂起中断请求寄存器,相当于把这个中断的按键松开了,以便接受下一次按键检测(中断请求)。
}
}
重点理解:EXTI_ClearITPendingBit(EXTI_Line0);//该函数是清除EXTI中断时产生的标志位,挂起中断请求寄存器,相当于把这个中断的“按键”松开了,以便接受下一次按键检测(中断请求)。
学习心得:
通过学习STM32库函数发现,C语言的结构体和函数的基础知识很重要;
结构体成员名称记不住只能通过查找标准库,但是一点都记不起来的话也是很难找,所以还是要简单记一下函数的名称和源文件。
本文记录本人学习STM32的知识,便于以后复习所用,对新学的知识的理解可能比较浅显、甚至有误,如有不妥之处,欢迎留言指正,以共同进步!
标签:优先级,中断,NVIC,InitStructure,GPIO,STM32F407,EXTI 来源: https://blog.csdn.net/weixin_47937575/article/details/123595863