当前位置:   article > 正文

【嵌入式STM32-05】STM32 外部中断 EXTI 基本原理|库函数程序代码|寄存器_stm32外部中断的原理

stm32外部中断的原理

STM32外部中断

1.中断基本原理

  • 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行

  • 中断优先级:当有多个中断源同时申请中断时,CPU会根据中断源的轻重缓急进行裁决,优先响应更加紧急的中断源

  • 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,CPU再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次进行返回

STM32中断

  • 68个可屏蔽中断通道,包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设

  • 使用NVIC统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级

中断/异常向量表

程序中的中断地址是由编译器分配的,是不固定的

所以需要中断向量表的地址,中断产生后,跳到这个地址

这个地址中存放中断程序的地址,再跳过去

image-20220922221819196

image-20220922221906957

NVIC

  • NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级

  • 抢占优先级高的可以中断嵌套【即先送入CPU处理】

    响应优先级高的可以优先排队【即可以插队在靠前的位置,等待CPU处理】

    抢占优先级和响应优先级均相同的按中断号排队

image-20220922222049914

image-20220922222249947

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //放在main.c初始化函数中只调用一次就行
  • 1

EXTI

  • EXTI(Extern Interrupt)外部中断

  • EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序

  • 支持的触发方式:上升沿/下降沿/双边沿/软件触发

  • 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断【例如PA0 PB0不能一起用外部中断】

  • 通道数:16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒

  • 触发响应方式:中断响应/事件响应

image-20220922222941747

AFIO

【Alternate Fuction复用功能】

  • AFIO主要用于引脚复用功能的选择和重定义

  • 在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择

image-20220922223057898

外部中断/事件控制器框图

image-20220922223304698

2.STM32 EXTI库函数

参考【STM32固件库使用手册】

所有相关函数

image-20220922225239471

image-20220922225605711

EXTI_Init

请结合

一、EXTI->外部中断/事件控制器框图

四、各寄存器

阅读以下代码

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
{
  uint32_t tmp = 0;

  /* Check the parameters */
  assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode));
  assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger));
  assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line));  
  assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd));

  tmp = (uint32_t)EXTI_BASE;
     
  if (EXTI_InitStruct->EXTI_LineCmd != DISABLE)
  {
    /* Clear EXTI line configuration */
    EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line;
    EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line;
    
    tmp += EXTI_InitStruct->EXTI_Mode;

    *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;

    /* Clear Rising Falling edge configuration */
    EXTI->RTSR &= ~EXTI_InitStruct->EXTI_Line;
    EXTI->FTSR &= ~EXTI_InitStruct->EXTI_Line;
    
    /* Select the trigger for the selected external interrupts */
    if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling)
    {
      /* Rising Falling edge */
      EXTI->RTSR |= EXTI_InitStruct->EXTI_Line;
      EXTI->FTSR |= EXTI_InitStruct->EXTI_Line;
    }
    else
    {
      tmp = (uint32_t)EXTI_BASE;
      tmp += EXTI_InitStruct->EXTI_Trigger;

      *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;
    }
  }
  else
  {
    tmp += EXTI_InitStruct->EXTI_Mode;

    /* Disable the selected external lines */
    *(__IO uint32_t *) tmp &= ~EXTI_InitStruct->EXTI_Line;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

完整应用程序

有个分组信息,分一次就行,写在主函数里

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //放在main.c初始化函数中只调用一次就行
  • 1
void EXTIX_Init(void)
{	                                       
    GPIO_InitTypeDef GPIO_InitStructure;
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);        //开启IO口复用时钟
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource3); //IO口与中断线映射关系

    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3 ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    EXTI_InitStructure.EXTI_Line = EXTI_Line3;                  //GPIOx.3【中断屏蔽寄存器】
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;         //中断模式【中断屏蔽寄存器/事件屏蔽寄存器】
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;     //触发方式下降沿【上升/下降沿/软中断触发寄存器】
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;                   //使能【中断屏蔽寄存器】
    EXTI_Init(&EXTI_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

void EXTI3_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生 
  {
    
    EXTI_ClearITPendingBit(EXTI_Line3);   //清除 LINE 上的中断标志位
  }     
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

3.STM32 EXTI CubeMX

image-20221014091333087

image-20221014091421527

image-20221014091547646

4.STM32 EXTI 寄存器

参考【STM32F10XXX参考手册】

image-20220922224009989

中断屏蔽寄存器(EXTI_IMR)

interrupt mask register

image-20220922224110486

事件屏蔽寄存器(EXTI_EMR)

event mask register

image-20220922224201542

上升沿触发选择寄存器(EXTI_RTSR)

Rising edge trigger select register

image-20220922224244126

下降沿触发选择寄存器(EXTI_FTSR)

Falling edge trigger select register

image-20220922224317769

软件中断事件寄存器(EXTI_SWIER)

Software Interrupt Event Register

image-20220922224359687

挂起寄存器(EXTI_PR)

pending register

image-20220922224434112

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/280951
推荐阅读
相关标签
  

闽ICP备14008679号