STM32
直播中

carey123

10年用户 1569经验值
擅长:可编程逻辑 嵌入式技术
私信 关注
[问答]

STM32的NVIC嵌套向量中断控制器与EXIT外部中断控制器介绍

NVIC是什么?NVIC嵌套向量中断控制器有何功能?
EXIT外部中断控制器是什么?有何功能?

回帖(1)

杨火亭

2021-11-16 10:59:21
  前言
  上一节中没有使用中断,这小节将使用中断,按键按下,触发中断,中断事情在中断服务函数中处理
  一、NVIC 嵌套向量中断控制器
  NVIC是嵌套向量中断控制器,控制着整个芯片中中断相关功能,是内核里面的一个外设。
  手册中的中断向量:分为系统中断和外设中断。红框框出来的是系统中断,有10个。外设中断比较多有60个,图片仅显示一小部分。
  
  
  优先级定义:
  原则上每个外部中断可配置的优先级为0~255,数值越小,优先级越高。优先级被分组成抢占优先级和子优先级。如果多个中断同时相应,抢占优先级会先执行。如果抢占优先级相同,再比较子优先级,如果子优先级相同在比较硬件的中断号,就是上图中Pritorty编号,编号越小优先级越高。
  优先级分组如下:
  
  固件库中NVIC相关的函数
  //设置分组优先级 void NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
  //获取分组优先级 uint32_t NVIC_GetPriorityGrouping(void)
  //中断使能 void NVIC_EnableIRQ(IRQn_Type IRQn)
  //中断失效 void NVIC_DisableIRQ(IRQn_Type IRQn)
  //获取中断 uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn)
  //设置中断 void NVIC_SetPendingIRQ(IRQn_Type IRQn)
  //清除中断 void NVIC_ClearPendingIRQ(IRQn_Type IRQn)
  //设置中断优先级 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
  //获取中断优先级 uint32_t NVIC_GetPriority(IRQn_Type IRQn)
  中断编程步骤:
  1)设置外设中断,比如串口收发中断;
  2)初始化NVIC_InitTypeDef结构体;
  typedef struct
  {
  uint8_t NVIC_IRQChannel;//中断源,参考IRQn_Type
  uint8_t NVIC_IRQChannelPreemptionPriority; //中断优先级 参考NVIC_Priority_Table
  uint8_t NVIC_IRQChannelSubPriority;//中断子优先级
  NVIC_Priority_Table FunctionalState NVIC_IRQChannelCmd;
  //This parameter can be set either to ENABLE or DISABLE
  }
  NVIC_InitTypeDef;
  3)中断服务函数
  二、EXIT 外部中断控制器
  EXIT(External interrupt/event controller)外部中断/事件控制器。每个中断/事件线都对应一个边沿检测器,可以实现输入信号的上升沿检测和下降沿检测。输入线一般是存在电平变化的信号。EXIT可分为两类,一类是产生中断,另一类是产生事件。中断直接给NVIC,进一步实现中断。中断事件输送给外设电路使用,比如ADC,定时器TIM。
  
  EXTI 有 20 个中断/事件线,每个 GPIO 都可以被设置为输入线,占用 EXTI0 至EXTI15,还有另外七根用于特定的外设事件。输入源与中断/事件的关系如下
  
  
  通过AFIO_EXTICRx配置GPIO线上的外部中断/事件
  
  EXIT结构体:
  typedef struct
  {
  uint32_t EXTI_Line;
  /* 中断/事件线,EXTI0-EXTI19 combination of @ref EXTI_Lines
  */ EXTIMode_TypeDef EXTI_Mode;
  /* 模式选择@ref EXTIMode_TypeDef
  */ EXTITrigger_TypeDef EXTI_Trigger;
  /* 触发选择,上升沿,下降沿,上升沿和下降沿 @ref EXTIMode_TypeDef
  */ FunctionalState EXTI_LineCmd;
  /* 是否使能ENABLE or DISABLE
  */ }EXTI_InitTypeDef;
  三 、外部中断实验
  使用外接的按键来作为触发源,使得控制器产生中断,并在中断服务函数中实现控制点灯的任务。按键KEY1对应的GPIO为使用PA0,EXTI对应于EXTI0中断线;NVIC对应于EXTI0_IRQn中断源。
  
  1) 初始化用来产生中断的GPIO
  2)初始化EXTI
  3)配置NVIC
  4)编写中断服务函数
  头文件
  #include “stm32f10x.h” #define KEY1_INT_GPIO_PORT GPIOA//组 PA #define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO)//时钟需要开启AFIO 配置中断 APB2 #define KEY1_INT_GPIO_PIN GPIO_Pin_0//引脚 #define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA//端口 #define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0//引脚 #define KEY1_INT_EXTI_LINE EXTI_Line0//中断线 #define KEY1_INT_EXTI_IRQ EXTI0_IRQn//中断源中断/事件 #define KEY1_IRQHandler EXTI0_IRQHandler//中断服务函数
  配置EXTI, 产生中断的GPIO
  void EXTI_Key_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; /*时钟设置*/ RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE); /* NVIC中断*/ NVIC_Configuration(); /*按键使用的GPIO*/ GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN; /* 浮空 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure); /* 选择EXTI信号源 Selects the GPIO pin used as EXTI Line */ GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); /*中断事件*/ EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE; /* 中断模式*/ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; /* 触发模式,上升沿*/ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; /* 使能 */ EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); }
  外部中断寄存器的配置 GPIO_EXTILineConfig 函数用来指定中断/事件线的输入源,它实际是设定外部中断配置寄存器的 AFIO_EXTICRx 值,该函数接收两个参数,第一个参数指定 GPIO 端口源,第二个参数为选择对应 GPIO 引脚源编号。
  配置NVIC
  static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /*优先级选择,组1 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* 中断源 */ NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ; /* 主优先级*/ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /*子优先级*/ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /*使能中断*/ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //初始化 NVIC_Init(&NVIC_InitStructure); }
  中断服务函数
  void KEY1_IRQHandler(void) { //获取中断线EXTI line状态 if(EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) { //翻转LED灯 LED1_TOGGLE; EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE); } }
举报

更多回帖

发帖
×
20
完善资料,
赚取积分