NVIC与EXTI外设详解

这篇具有很好参考价值的文章主要介绍了NVIC与EXTI外设详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、NVIC(嵌套向量中断控制器)简介

NVIC控制着整个芯片中断相关的功能,它跟内核紧密耦合。但是各个芯片厂商在设计芯片的时候会对 Cortex-M3 内核里面的 NVIC 进行裁剪,把不需要的部分去掉,所以STM32 的 NVIC 是 Cortex-M3 的 NVIC 的一个子集。

NVIC属于内核外设,MCU组成分为:内核(ARM设计)、片上外设(芯片制造商设计)。如下图
nvic,STM32学习笔记,单片机,stm32,c语言
NVIC部分标准库函数(由ARM提供,符合CMSIS 标准):
nvic,STM32学习笔记,单片机,stm32,c语言

2、EXTI(外部中断/事件控制器)简介

EXTI是STM32单片机上的一个外设,控制着单片机上的中断/事件的响应。STM32f1 有19个能产生事件/中断请求的边沿检测器(互联型有20个,比如f105/f107等)。 每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。

F103EXTI中断映射线路框图:
nvic,STM32学习笔记,单片机,stm32,c语言

3、EXTI 工作流程框图

nvic,STM32学习笔记,单片机,stm32,c语言EXTI 与NVIC有什么关系?
从上图中可以看出来,当MCU片上外设产生一个中断后,就会输入到NVIC控制器中,去控制中断的响应顺序。
nvic,STM32学习笔记,单片机,stm32,c语言
请求挂起寄存器发生触发请求后,一定要手动清0,不然会一直进入中断。

4、抢占优先级与响应优先级

nvic,STM32学习笔记,单片机,stm32,c语言
概括:通过优先级分组,管理中断的响应顺序。高优先级的抢占可以的打断低优先级的中断,如果是同优先级的中断,则会挂起,等现有中断执行完,再根据响应优先级来决定是谁先执行,如果同响应优先级,那么就根据IRQ编号决定先执行。

5、代码流程图
5.1、STM32中断优先级配置流程

nvic,STM32学习笔记,单片机,stm32,c语言中断优先级配置流程
1、调用HAL设置优先级分组函数HAL_NVIC_SetPriorityGrouping()
2、 配置中断线优先级,HAL_NVIC_SetPriority();
3、 在HAL_NVIC_SetPriority()中;调用NVIC库函数配置中断优先级。NVIC_SetPriority(IRQn,NVIC_EncodePriority());
4、 在NVIC_EncodePriority()里面糅合了中断优先级分组的概念
5、使能中断线 HAL_NVIC_EnableIRQ();

5.2、中断触发到中断服务函数的流程

nvic,STM32学习笔记,单片机,stm32,c语言
MCU触发了一个中断
1、执行指针就会跳转到中断向量表中
2、 找到对应的中断偏移地址
3、偏移地址:就是中断服务函数的入口 EXTI4_IRQHandler
4、 最终会在HAL_GPIO_EXTI_IRQHandler()里面调用callback函数,并清除PR寄存器

5.3、外设初始化流程图

nvic,STM32学习笔记,单片机,stm32,c语言
EXTI配置步骤
1、设置中断优先级分组
HAL_NVIC_SetPriorityGrouping();
2、初始化GPIO
1)、使能GPIO时钟
2)、配置GPIO 参数。引脚号,模式,上下拉
3)、初始化 HAL_GPIO_Init(端口号,结构体地址);
3、设置中断线优先级,是能中断线
1)、HAL_NVIC_SetPriority();中断线优先级
2)、HAL_NVIC_EnableIRQ();使能中断线
4、编写中断服务函数
EXTI3_IRQHandler();中断服务函数

6、Cube MX 配置

nvic,STM32学习笔记,单片机,stm32,c语言

7、示例实验代码

实验目的:利用外部中断方式检测按键输入,并在中断服务函数里面翻转LED电平,每检测到一次按键输入,LED电平翻转一次。

硬件原理图:
nvic,STM32学习笔记,单片机,stm32,c语言
示例代码:

led.h文件

#ifndef __LED_H
#define __LED_H
#include "stm32f1xx.h"

#define  LED1_PORT  GPIOE
#define  LED1_PIN   GPIO_PIN_5

#define  LED0_PORT  GPIOB
#define  LED0_PIN   GPIO_PIN_5

void LED_Init(void);

#endif

led.c文件

#include "led.h"


/**
  * @brief  初始化GPIO
  * @param  无
  * @retval 无
  */
void LED_Init(void)
{
      //使能端口时钟,在hal_rcc里面找
      __HAL_RCC_GPIOB_CLK_ENABLE();
      __HAL_RCC_GPIOE_CLK_ENABLE();
    
      //创建一个 GPIO_InitTypeDef类型的结构体
        GPIO_InitTypeDef GPIO_InitStruct;  
      
    
       //配置结构体成员参数:
       //模式:输出推挽
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
       //Pin
      GPIO_InitStruct.Pin  = LED1_PIN;
       //上下拉
      GPIO_InitStruct.Pull = GPIO_NOPULL;
       //输出速度 2M ---------/10M/50M
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      //调用库函数,使用上面配置的结构体成员参数,初始化端口IO
        HAL_GPIO_Init(LED1_PORT,&GPIO_InitStruct);
    
    
        //LED0端口的其他配置相同,也是用的同一个结构体,\
        //不用改的参数在上一步还有保持在 GPIO_InitStruct的堆栈中。(不确定是不是堆栈?)
        GPIO_InitStruct.Pin  = LED0_PIN;
        //初始化化端口IO
        HAL_GPIO_Init(LED0_PORT,&GPIO_InitStruct);
        
        //不可以这样写,是同一个寄存器才可以这样写,现在GPIO_TypeDef *GPIOx 是一个指针,\
        //原本是去地址40011800跟40010c00的基地址配置参数,结果变成了去40011c00的基地址配置参数
        //  40011800 | 40010c00 = 40011c00
//    HAL_GPIO_WritePin(((uint32_t)LED1_PORT | (uint32_t)LED0_PORT),GPIO_PIN_5,GPIO_PIN_SET);


        //配置端口的初始电平状态
      HAL_GPIO_WritePin(LED1_PORT ,GPIO_PIN_5,GPIO_PIN_SET);
        HAL_GPIO_WritePin(LED1_PORT ,GPIO_PIN_5,GPIO_PIN_SET);
    
}

key.h文件

#ifndef __KEY_H
#define __KEY_H
#include "stm32f1xx.h"

#define  KEY1_PORT  GPIOE
#define  KEY1_PIN   GPIO_PIN_3

#define  KEY0_PORT  GPIOE
#define  KEY0_PIN   GPIO_PIN_4

void EXTI_KEY_Init(void);

#endif

key.c文件

#include "key.h"
/**
  * @brief  初始化外部中断输入
  * @param  无
  * @retval 无
  */
void EXTI_KEY_Init(void )
{
    GPIO_InitTypeDef  GPIO_InitStruct;
    
    //使能端口时钟,在hal_rcc里面找
    __HAL_RCC_GPIOE_CLK_ENABLE();
    
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct.Pin  = KEY1_PIN;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(KEY1_PORT,&GPIO_InitStruct);
    
    //设置中断线优先级,在hal_cortex里面找
    HAL_NVIC_SetPriority(EXTI3_IRQn,2,1);
    //使能对应的时钟线
    HAL_NVIC_EnableIRQ(EXTI3_IRQn);
     
    GPIO_InitStruct.Pin  = KEY0_PIN;
    HAL_GPIO_Init(KEY0_PORT,&GPIO_InitStruct);
    
    HAL_NVIC_SetPriority(EXTI4_IRQn,2,1);
    HAL_NVIC_EnableIRQ(EXTI4_IRQn);
    
}

exti.h文件

#ifndef __EXTI_H
#define __EXTI_H
#include "stm32f1xx_hal.h"


#endif

exti.c文件 :调库如果不知道用哪个函数,可以先去相关外设库找,比如按键去hal_gpio.h库,中断去hal_exti库,如果外设库中不到,就去与内核相关的库找,比如hal_cortex.h

#include "exti.h"
#include "led.h"

/**
*  @brief  EXTI3中断服务函数
  * @param  无
  * @retval 无
  */
    
//在startup_stm32f103xe.s文件里面找中断服务函数名称
void EXTI3_IRQHandler(void)
{
      //硬件按键可能有问题,抖动100ms还可能有
      HAL_Delay(100);  
      //处理中断请求的函数,在hal_gpio.h里面找
        HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
}
//中断线检测回调函数,在hal_gpio.h里面找
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
      HAL_GPIO_TogglePin(LED1_PORT,LED1_PIN);
}


/**
*  @brief  EXTI4中断服务函数
  * @param  无
  * @retval 无
  */
void EXTI4_IRQHandler(void)
{
        HAL_Delay(100);
      if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4) != 0x00u) //判断中断线有没有挂起,在hal_gpio_h中找
  {
          //这里是要先清PR寄存器,因为确定了有中断进来,接下来执行功能代码,
          //假如接下来的程序执行时间很长,中间又有一次同一个中断线触发,
          //可能会漏掉一次。
          __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);  //在hal_gpio_h中找这个函数。
          HAL_GPIO_TogglePin(LED0_PORT,LED0_PIN);
          
  }
}
作者公众号

为了让各位读者更方便地阅读文章,作者开始把博客的文章同步到个人的微信公众号,欢迎您的关注。
文章来源地址https://www.toymoban.com/news/detail-536330.html

到了这里,关于NVIC与EXTI外设详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32】中断与NVIC以外部中断为例

    在stm32中姑且可以认为,异常就是中断 单片机上电之后,首先执行启动文件,开辟堆栈之后,开始初始化中断向量表。 NVIC NVIC是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦合,是 内核 里面的一个外设。 ####三个寄存器 ISER 、 ICER 和 IP NVIC 结构体

    2024年02月10日
    浏览(15)
  • STM32 hal库 NVIC初始化函数梳理

    使用的是stm32f407vg,代码来源stm32cubemx。 已经配置了中断的是GPIOD_pin6和TIM2。  这个是STM32CubeMX里面NVIC的控制面板;其中最上面priority grope是优先级组,我设置的是4位抢占优先级,0位响应优先级,就和以前刚学中断时中断嵌套那样。 下面是有哪些中断源,勾上之后,在最下面

    2024年01月18日
    浏览(29)
  • STM32——关于NVIC讲解及标准库应用(基础篇)

            NVIC是指STM32中的中断控制器(Nested Vectored Interrupt Controller)。中断是STM32中的重要机制,通过中断可以实现异步事件处理。NVIC提供了灵活、高效、可扩展的中断处理机制,支持多级优先级、多向中断、嵌套向量中断等特性,是STM32中的重要组件。         当S

    2024年02月16日
    浏览(14)
  • STM32中断分组配置NVIC_PriorityGroup,移植操作系统需需注意NVIC_PriorityGroup_4

    一、先说明中断分组的由来 中断优先级分组表: 优先级分组 抢占优先级 响应优先级 bit[7:4] 分配情况 备注 NVIC_PriorityGroup_0 取值:0 取值:0~15 0:4 0bit抢占优先级、4bit响应优先级 NVIC_PriorityGroup_1 取值:0~1 取值:0~7 1:3 1bit抢占优先级、3bit响应优先级 NVIC_PriorityGroup_2 取值:0~3

    2024年02月04日
    浏览(24)
  • stm32-NVIC中断优先级管理(以古代官职角度分析)

    讲在前面的话: 博主在学习正点原子这一章节的时候很是懵,感觉摸不到门路,于是在网上找了一些相关的视频讲解,将他们的内容整合了一下,并尽量用易懂的话讲解。(本文基于stm32f103ZET6) CM3 内核支持256个中断,其中包含了 16 个内核中断和 240 个外部中断,并且具有

    2024年02月22日
    浏览(23)
  • 【STM32】HAL库的RCC复位状态判断及NVIC系统软件复位

    【STM32】HAL库的RCC复位状态判断及NVIC系统软件复位 在实际开发中 有时候会遇到复位状态不同 导致结果不同的情况 比如在上电复位时 电压不稳定 可能导致一些外部芯片无法正常工作 从而导致进行了错误的操作流程 所以 可以在程序运行后 加一个复位状态判断 用来检测是否

    2024年02月02日
    浏览(27)
  • 【明解STM32】中断系统理论基础知识篇之中断基本原理及NVIC

    目录 一、前言 二、基本原理概述 1、中断的作用 2、中断和异常 3、NVIC中断控制器 4、中断的分类 三、中断管理机制 1、中断向量 2、中断优先级 3、中断嵌套 四、中断处理流程 五、总结         中断是什么?举个例子来说,当我们正在工作时,突然电话响了,这时你会把

    2024年02月05日
    浏览(27)
  • 【STM32】进阶(一):抢占式优先级和响应式优先级(NVIC_PriorityGroupConfig)

    【STM32】STM32单片机总目录 STM32(Cortex-M3)中每个中断源都有两级优先级:抢占式优先级(pre-emption priority)和子优先级(subpriority),子优先级也叫响应式优先级。 望文知义,就是优先级高的可以抢占优先级的中断。 具有高抢占式优先级的中断可以在具有低抢占式优先级的中断

    2024年02月12日
    浏览(36)
  • 【STM32】STM32学习笔记-EXTI外部中断(11)

    中断 :在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行 中断优先级 :当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加

    2024年02月04日
    浏览(21)
  • STM32外设GPIO(学习笔记)

    在编写stm32程序时,对寄存器进行操着需要知道每个外设的基地址,标准库的stm32f10x.h文件里也有各种外设的基地址。 比如GPIO:在定义输出数据寄存器地址GPIOA_ODR_Addr时,在GPIOA_BASE(GPIO端口A的基址地址)地址基础上偏移 在stm32f10x.h文件里面有定义GPIOA_BASE,是APB2PERIPH_BASE(

    2024年04月12日
    浏览(23)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包