你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32的外部中断EXTI及NVIC中断优先级介绍(内附代码)

[复制链接]
STMCU小助手 发布时间:2022-5-18 21:00
一、什么是中断?

打断当前的操作,执行中断需要做的事情。

中断的作用:中断机制不仅赋予了系统处理意外情况的能力,就可以“同时”完成多个任务,提高了并发“处理”能力。

和线程的区别:线程是同时执行多个任务,中断是停下来去执行其他的(注意优先级),执行完了再回来执行,

     定时器才相当于线程,定一个时间,每到这个时间执行一次

6J71O1~9KX_H[0P~(7VD3V2.png


二、中断概述

STM32F4并没有使用CM4内核的全部东西,而是只用了它的一部分。

STM32F40xx/STM32F41xx总共有92个中断

STM32F42xx/STM32F43xx则总共有96个中断

STM32F40xx/STM32F41xx的92个中断里面,包括10个内核中断和82个可屏蔽中断,具有16级可编程的中断优先级,而我们常用的就是这82个可屏蔽中断。

三、外部中断/事件线映射多达140个GPIO。


{ACBQPU~~``QJVWEYH]SLIP.png

5Q{ZAFW3JUJYSLCR57VT%]O.png

根据图文,发现我们的中断线总共有23根,其中16根是连接PA~PI引脚。

STM32F4供IO使用的中断线只有16个:EXTI线0~15:对应外部IO口的输入中断。

剩下的七根是分别连接专用设备的:

另外七根 EXTI 线连接方式如下:

● EXTI 线 16 连接到 PVD 输出

● EXTI 线 17 连接到 RTC 闹钟事件

● EXTI 线 18 连接到 USB OTG FS 唤醒事件

● EXTI 线 19 连接到以太网唤醒事件

● EXTI 线 20 连接到 USB OTG HS(在 FS 中配置)唤醒事件

● EXTI 线 21 连接到 RTC 入侵和时间戳事件

● EXTI 线 22 连接到 RTC 唤醒事件

四、中断服务函数分配

IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数

DXLNHE7G7{94VB)81R1OUAS.png

从表中看出,外部中断线5~9分配一个中断向量,共用一个服务函数 外部中断线10~15分配一个中断向量,共用一个中断服务函数

中断服务函数列表如下:

2018061716341163.png

五、设置中断优先级的分组

    1、中断优先级有两种:

        抢占(占先式)优先级 --》 第一序列                  响应(副)优先级 --》 第二序列

  2、抢占优先级 &响应优先级区别:

        高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。

        抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。

        抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。

        如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;

@ADBNL{OC0MYQ9K[LJSO%NU.png

3、中断优先级设置步骤

//①系统运行后先设置中断优先级分组。调用函数:

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);整个系统执行中只设置一次中断分组。

//②针对每个中断,设置对应的抢占优先级和响应优先级:

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
③如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可

20180617165802365.png

五、外部中断的一般配置步骤

①使能SYSCFG时钟:

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

②初始化IO口为输入。

    GPIO_Init();

K1DUI9P0SC5AO]P4BM75XST.png

③设置IO口与中断线的映射关系。

    void SYSCFG_EXTILineConfig();//通过设置SYSCFG寄存器,建立IO口和中断线的连接

④初始化线上中断,设置触发条件等。

    EXTI_Init();

XOOS_X4[XZ8TCHM@4AM`OUO.png

⑤配置中断分组(NVIC),并使能中断。

    NVIC_Init();

20180617165751877.png

⑥编写中断服务函数。

    EXTIx_IRQHandler();

且清除中断标志位

EXTI_ClearITPendingBit();//清除中断标志位是为了表示中断已经开始执行,可以接收下一个中断。

代码如下:

  1. /**********************************************
  2. *
  3. *功能:四个按键中断
  4. *
  5. **********************************************/
  6. #include "exti.h"


  7. //外部中断初始化程序
  8. //初始化PE2~4,PA0为中断输入.
  9. void EXTI4_Init(void)
  10. {
  11.     NVIC_InitTypeDef   NVIC_InitStructure;
  12.     EXTI_InitTypeDef   EXTI_InitStructure;
  13.     GPIO_InitTypeDef  GPIO_InitStructure;


  14.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE时钟
  15.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟

  16.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //KEY0 KEY1 KEY2对应引脚
  17.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
  18.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
  19.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  20.     GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4

  21.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4);//PE4 连接到中断线4

  22.     /* 配置EXTI_Line2,3,4 */
  23.     EXTI_InitStructure.EXTI_Line = EXTI_Line4;
  24.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
  25.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
  26.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能
  27.     EXTI_Init(&EXTI_InitStructure);//配置

  28.     NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断4
  29.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1
  30.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  31.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  32.     NVIC_Init(&NVIC_InitStructure);//配置   
  33. }


  34. void EXTI3_Init(void)
  35. {
  36.     NVIC_InitTypeDef   NVIC_InitStructure;
  37.     EXTI_InitTypeDef   EXTI_InitStructure;
  38.     GPIO_InitTypeDef  GPIO_InitStructure;


  39.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE时钟
  40.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟

  41.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //KEY0 KEY1 KEY2对应引脚
  42.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
  43.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
  44.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  45.     GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4

  46.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);//PE4 连接到中断线4


  47.     /* 配置EXTI_Line2,3,4 */
  48.     EXTI_InitStructure.EXTI_Line = EXTI_Line3;
  49.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
  50.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
  51.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能
  52.     EXTI_Init(&EXTI_InitStructure);//配置

  53.     NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//外部中断4
  54.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1
  55.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  56.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  57.     NVIC_Init(&NVIC_InitStructure);//配置   
  58. }


  59. void EXTI2_Init(void)
  60. {
  61.     NVIC_InitTypeDef   NVIC_InitStructure;
  62.     EXTI_InitTypeDef   EXTI_InitStructure;
  63.     GPIO_InitTypeDef  GPIO_InitStructure;

  64.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOA,GPIOE时钟
  65.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟

  66.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //KEY0 KEY1 KEY2对应引脚
  67.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
  68.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
  69.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  70.     GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4

  71.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2);//PE4 连接到中断线4


  72.     /* 配置EXTI_Line2,3,4 */
  73.     EXTI_InitStructure.EXTI_Line = EXTI_Line2;
  74.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
  75.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
  76.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能
  77.     EXTI_Init(&EXTI_InitStructure);//配置

  78.     NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中断4
  79.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1
  80.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  81.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  82.     NVIC_Init(&NVIC_InitStructure);//配置   
  83. }


  84. void EXTI0_Init(void)
  85. {
  86.     NVIC_InitTypeDef   NVIC_InitStructure;
  87.     EXTI_InitTypeDef   EXTI_InitStructure;
  88.     GPIO_InitTypeDef  GPIO_InitStructure;


  89.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA,GPIOE时钟
  90.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟

  91.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //KEY0 KEY1 KEY2对应引脚
  92.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
  93.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
  94.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  95.     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOE2,3,4

  96.     SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);//PE4 连接到中断线4


  97.     /* 配置EXTI_Line2,3,4 */
  98.     EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  99.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件
  100.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发
  101.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能
  102.     EXTI_Init(&EXTI_InitStructure);//配置

  103.     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断4
  104.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;//抢占优先级1
  105.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2
  106.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道
  107.     NVIC_Init(&NVIC_InitStructure);//配置   
  108. }


  109. //外部中断4服务程序
  110. void EXTI4_IRQHandler(void)
  111. {
  112.      if(EXTI_GetITStatus(EXTI_Line4) != RESET)//判断是否置位
  113.     {}
  114.     EXTI_ClearITPendingBit(EXTI_Line4);//清除LINE4上的中断标志位  
  115. }


  116. //外部中断3服务程序
  117. void EXTI3_IRQHandler(void)
  118. {
  119.     delay_ms(15);

  120.     EXTI_ClearITPendingBit(EXTI_Line3);//清除LINE4上的中断标志位  
  121. }


  122. //外部中断2服务程序
  123. void EXTI2_IRQHandler(void)
  124. {
  125.     EXTI_ClearITPendingBit(EXTI_Line2);//清除LINE4上的中断标志位  
  126. }


  127. //外部中断0服务程序
  128. void EXTI0_IRQHandler(void)
  129. {
  130.     EXTI_ClearITPendingBit(EXTI_Line1);//清除LINE4上的中断标志位  
  131. }

复制代码



收藏 评论0 发布时间:2022-5-18 21:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版