ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于STM32F407的NVIC、EXTI相关入门知识

2022-03-20 19:04:05  阅读:300  来源: 互联网

标签:优先级 中断 NVIC InitStructure GPIO STM32F407 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(抢占优先级)

  1. 抢占优先级高的可抢占低的,插队先执行;
  2. 若相同抢占优先级,先发生 先执行;
  3. 抢占优先级低的不可抢占低的,排队等待执行;

Sub Priority(子优先级又称响应优先级)

  1. 在抢占优先级相同时,响应优先级高的不可以打断的响应优先级低的;
  2. 在抢占优先级相同,且同时请求中断时,响应优先级高的先执行。
  3. 在抢占优先级相同,且同时请求中断时,响应优先级也相同时,根据异常中断向量表排位顺序决定谁先执行

关系:在抢占优先级相同的前提下,再判断子优先级才有意义

中断优先级分组

SCB_AIRCR(中断和复位控制寄存器 Application Interrupt And Reset Control Register)(SCB(SystemControl Block)只是一个结构体的名称)

SCB_AIRCR[10:8]IP bit[7:4]分配情况分配结果优先级
00b1110:4

0位抢占优先级

4位响应优先级

1个抢占优先级

16个响应优先级

10b1101:3

1位抢占优先级

3位响应优先级

2个抢占优先级

8个响应优先级

20b1012:2

2位抢占优先级

2位响应优先级

4个抢占优先级

4个响应优先级

30b1003:1

3位抢占优先级

1位响应优先级

8个抢占优先级

2个响应优先级

40b0114:0

4位抢占优先级

0位响应优先级

16个抢占优先级

1个响应优先级

以组别3 (PriorityGroupCongfig_3)为例(SCB_AIRCR[10:8]与IP bit[7:4]是否有相连关系还没探究,有知道的小伙伴请留言一下,谢谢!

 SCB_AIRCR[10:8]IP bit[7:4]
位数109876543210
功能100保留
上面的二进制为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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有