STM32中断系统

  • 抢占优先级用于确定中断的重要性,较高的抢占优先级意味着中断可以中断当前正在执行的较低优先级中断。
  • -响应优先级用于确定多个中断同时触发时的执行顺序。响应优先级高的中断会先执行,而响应优先级相同的中断会按照中断号顺序排队执行。
2、中断触发方式
  • 上升沿触发:中断在引脚电平由低到高变化时触发。
  • 下降沿触发:中断在引脚电平由高到低变化时触发。
  • 双边沿触发:中断在引脚电平由低到高或由高到低变化时触发。
  • 软件触发:通过执行一句特定的代码来触发中断,通常使用类似于 NVIC_SetPendingIRQ() 的函数。
3、触发响应方式
  • 中断响应:中断触发后,中断服务程序执行,通常用于需要立即响应的事件。
  • 事件响应:事件触发后,不会引发中断,而是触发其他外设操作,如启动ADC转换或启动DMA传输。
4、注意事项
  • 进入中断函数时,务必检查中断标志位以确定中断的原因。
  • 中断服务函数应该执行简短和高效的代码,以尽快释放中断,并允许更高优先级的中断执行。
  • 在中断服务函数退出时,通常需要清除中断标志位,以允许下一次中断触发

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

img

NVIC用于统一管理中断和分配中断优先级,属于内核外设,是CPU的小助手,可以让CPU专注于运算。相当于医院里的叫号系统(给病人进行排号,CPU相当于医生,只负责看病)。

2、 NVIC优先级分组

优先级:抢占优先级、响应优先级。

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

抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队

img

img

如果中断不多,很难导致中断冲突时,可以随意选择优先级分组,那个都行。

3、 EXIT(Extern Interrupt)外部中断

1、基本功能

EXTI 的主要功能是检测连接到微控制器引脚的电平变化,并在特定条件下触发中断。它允许您实时响应外部事件,如按钮按下或传感器状态变化。

2、支持的GPIO口

EXTI 支持所有的 GPIO 口,但需要注意的是相同的引脚不能同时触发中断。例如,如果您将 PA0 配置为触发中断,那么其他引脚上的中断可能会被禁用。但是,PA0 和 PA1 这样的不同引脚可以同时触发中断。

3、通道数

EXTI 支持最多16个 GPIO 引脚作为中断触发源。除了 GPIO 引脚,它还可以监测其他事件,如电源电压监测(PVD)、RTC 闹钟、USB 唤醒和以太网唤醒。

4、EXTI 基本结构

您提供的示意图展示了 EXTI 的基本结构。它包括了多个通道,每个通道对应一个 GPIO 引脚。当引脚状态变化时,相应的 EXTI 通道会触发中断。

5、 AFIO 中断引脚选择

AFIO(Alternate Function Input Output)是用于配置微控制器引脚的外设。在配置 EXTI 时,您可以选择将特定的 GPIO 引脚连接到 EXTI 通道。这允许您灵活地选择要触发中断的引脚。

EXIT基本结构:

img

AFIO中断引脚选择:在GPIO(A~G)外设的16个GPIO_Pin中选择一个连接到后面的EXIT的通道里。

4、 常用的触发外部中断的硬件模块

对于STM32来说,想要获取的信号是外部驱动的很快的突发信号,但是又不需要一直进行检测。

不需要经常使用、不需要一直检测的模块:

  1. 按键(注意抖动问题),不推荐,可以使用定时器中断
  2. 旋转编码器
  3. 红外遥控接收器

5、 外部中断程序设计步骤

img

涉及到的外设:RCC、GPIO、AFIO、EXTI、NVIC

1、如何设置外部中断 (EXTI)
  1. 打开RCC时钟: 在使用任何外设之前,需要确保相应的外设时钟已打开。在这种情况下,您打开了RCC (Reset and Clock Control) 时钟,它是控制各种外设时钟的关键。没有时钟,外设无法正常工作。
  2. 配置GPIO: 在使用外部中断之前,需要选择一个GPIO端口,并将其配置为输入模式。输入模式的配置可以是浮空(不连接到任何电平)、上拉(连接到高电平)或下拉(连接到低电平),具体取决于应用的要求。
  3. 配置AFIO: AFIO (Alternate Function I/O) 控制着GPIO引脚的复用功能。在这一步中,您选择了使用的GPIO并将其连接到后面的EXTI模块,以允许GPIO引脚触发外部中断。
  4. 配置EXTI: 外部中断线 (EXTI) 控制着外部中断的触发和响应方式。您需要选择外部中断触发的方式,例如上升沿、下降沿或双边沿触发。通常,中断触发方式应根据应用的需求来选择。此外,您还可以选择中断响应方式,一般选择中断响应以触发中断处理函数。
  5. 配置NVIC: NVIC (Nested Vectored Interrupt Controller) 用于配置中断优先级和中断的全局控制。在这一步中,您可以为外部中断选择一个合适的优先级,以确定它在中断处理器中的相对重要性。抢占优先级和响应优先级的选择可以确保在多个中断同时发生时,系统可以正确地处理它们。

配置完之后,写中断执行函数

在STM32中,中断函数的名字都是固定的,每个中断通道都对应一个中断函数。

中断函数的名字可以参考启动文件中的“stratup_stm32f10x_md文件

配置AFIO相关函数

img

void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

参数1:选择重映射方式

参数2:新的状态

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);

配置AFIO的数据选择器,来选择想要的中断引脚

注意:主函数和中断函数不要操控同一个硬件(比如OLED显示),避免不必要的冲突,中断函数只执行突发的事件,需要快速的执行,如操作变量、中断标志位。

2、一般步骤:

要使用 EXTI(External Interrupt,外部中断)来检测和响应外部事件,您需要遵循以下一般步骤:

  1. 配置引脚

    • 首先,您需要选择要配置为 EXTI 中断触发源的 GPIO 引脚。这可以通过将引脚模式配置为输入和选择触发方式来实现。通常,上升沿或下降沿触发是常见的配置。
    • 如果您使用的是 STM32 系列的微控制器,通常需要使用 GPIO 初始化函数来配置引脚,如 GPIO_Init()
  2. 配置 EXTI

    • 接下来,您需要配置 EXTI 外部中断。在 STM32 等微控制器中,这通常涉及到以下步骤:
      • 选择 EXTI 通道,通常与要配置的引脚对应。
      • 配置触发方式,选择上升沿、下降沿或其他方式。
      • 使能 EXTI 中断。
  3. 编写中断处理程序

    • 为了响应 EXTI 中断触发,您需要编写中断处理程序。这个程序会在外部事件触发时执行。
    • 在中断处理程序中,您可以执行与事件相关的操作,例如读取传感器数据、处理按钮按下事件等。
  4. 配置中断优先级(可选):

    • 如果系统中有多个中断源,您可能需要配置中断优先级以确定执行顺序。通常,您可以使用中断控制器(如 NVIC,在 STM32 中)来配置中断优先级。
  5. 清除中断标志位

    • 在中断处理程序中,通常需要清除 EXTI 的中断标志位,以允许下一个触发。这可以通过写入特定的寄存器来实现。
  6. 启用全局中断

    • 最后,在主程序的入口点,通常需要启用全局中断以允许所有中断触发。这可以通过使用 __enable_irq() 或类似的函数来实现。

以下是一个典型的 STM32 的 EXTI 配置示例,假设要配置 PA0 引脚上升沿触发的外部中断:

// 步骤1: 配置引脚
GPIO_InitTypeDef GPIO_InitStructure;
RCC\_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
// 使能 GPIOA 时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
// 输入浮空模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
// 配置 PA0 引脚
GPIO\_Init(GPIOA, &GPIO_InitStructure);

// 步骤2: 配置 EXTI
EXTI_InitTypeDef EXTI_InitStructure;
RCC\_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 
// 使能 AFIO 时钟
GPIO\_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); 
// 配置 EXTI 到 PA0
EXTI_InitStructure.EXTI_Line = EXTI_Line0; 
// EXTI0 通道
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; 
// 中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; 
// 上升沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE; 
// 使能 EXTI0
EXTI\_Init(&EXTI_InitStructure);

// 步骤3: 编写中断处理程序
void EXTI0\_IRQHandler(void) {
    // 在此处编写中断处理程序,响应外部事件
    // 例如,您可以执行读取传感器数据的操作

    EXTI\_ClearITPendingBit(EXTI_Line0); 
    // 清除中断标志位
}

// 步骤4: 配置中断优先级 (可选)
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; 
// EXTI0 中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; 
// 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; 
// 响应优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
// 使能中断通道
NVIC\_Init(&NVIC_InitStructure);

// 步骤5: 启用全局中断
\_\_enable\_irq();

这个示例配置了 PA0 引脚上升沿触发的 EXTI 中断,当 PA0 引脚状态从低电平变为高电平时,将触发中断处理程序 EXTI0_IRQHandler。中断处理程序中的代码可根据外部事件的需要自定义。

3、GPIO中断输入输出函数
/\*\*
 \* @brief 锁定指定的GPIO引脚配置,防止进一步更改。
 \* @param GPIOx: 要锁定的GPIO端口。
 \* @param GPIO\_Pin: 要锁定的GPIO引脚。
 \* @retval 无
 \*/
void GPIO\_PinLockConfig(GPIO_TypeDef\* GPIOx, uint16\_t GPIO_Pin);

/\*\*
 \* @brief 配置外部中断的事件输出功能,通常用于触发外部事件。
 \* @param GPIO\_PortSource: 事件输出的源GPIO端口。
 \* @param GPIO\_PinSource: 事件输出的源GPIO引脚。
 \* @retval 无
 \*/
void GPIO\_EventOutputConfig(uint8\_t GPIO_PortSource, uint8\_t GPIO_PinSource);

/\*\*
 \* @brief 启用或禁用外部中断的事件输出功能。
 \* @param NewState: 事件输出功能的新状态(ENABLE或DISABLE)。
 \* @retval 无
 \*/
void GPIO\_EventOutputCmd(FunctionalState NewState);

/\*\*
 \* @brief 配置GPIO引脚重映射,允许将一个引脚映射到另一个引脚。
 \* @param GPIO\_Remap: GPIO引脚重映射配置。
 \* @param NewState: 重映射功能的新状态(ENABLE或DISABLE)。
 \* @retval 无
 \*/
void GPIO\_PinRemapConfig(uint32\_t GPIO_Remap, FunctionalState NewState);

/\*\*
 \* @brief 配置外部中断线映射,将指定的GPIO引脚映射到外部中断线上。
 \* @param GPIO\_PortSource: 外部中断线映射的源GPIO端口。
 \* @param GPIO\_PinSource: 外部中断线映射的源GPIO引脚。
 \* @retval 无
 \*/
void GPIO\_EXTILineConfig(uint8\_t GPIO_PortSource, uint8\_t GPIO_PinSource);

/\*\*
 \* @brief 配置以太网接口的媒体类型(例如,RMII或MII)。
 \* @param GPIO\_ETH\_MediaInterface: 以太网媒体接口类型配置。
 \* @retval 无
 \*/
void GPIO\_ETH\_MediaInterfaceConfig(uint32\_t GPIO_ETH_MediaInterface);

4、配置AFIO外部中断引脚选择

这段代码是用于配置外部中断线映射的函数。外部中断线映射允许将特定的GPIO引脚映射到外部中断线上,从而使这些引脚能够触发外部中断。以下是对该函数的注释和解释:

调用这个函数,就可以配置AFIO的数据选择器,来选择我们想要的中断引脚

/\*\*
 \* @brief 配置外部中断线映射,将指定的GPIO引脚映射到外部中断线上。
 \* @param GPIO\_PortSource: 外部中断线映射的源GPIO端口。
 \* @param GPIO\_PinSource: 外部中断线映射的源GPIO引脚。
 \* @retval 无
 \*/
void GPIO\_EXTILineConfig(uint8\_t GPIO_PortSource, uint8\_t GPIO_PinSource);

  • GPIO_PortSource 参数用于指定外部中断线映射的源GPIO端口。这是一个数字,表示GPIO端口,例如,如果要映射的引脚属于GPIOA,则该参数为 GPIO_PortSource = GPIO_PortSourceGPIOA
  • GPIO_PinSource 参数用于指定外部中断线映射的源GPIO引脚。这是一个数字,表示要映射的GPIO引脚的位置,例如,如果要映射的引脚是GPIOA的第2号引脚,则该参数为 GPIO_PinSource = GPIO_PinSource2

通过调用此函数,您可以配置外部中断线映射,以便将特定GPIO引脚与外部中断相关联。这使得在满足外部中断触发条件时,可以触发相应的中断处理程序。在配置外部中断时,通常需要使用此函数来设置引脚到外部中断线的映射关系。

6、配置EXTI

1、EXTI库函数
/\*\*
 \* @brief 将外部中断模块的配置恢复为默认值。
 \*/
void EXTI\_DeInit(void);

/\*\*
 \* @brief 初始化外部中断模块。
 \* @param EXTI\_InitStruct: 包含外部中断配置的结构体指针。
 \*/
void EXTI\_Init(EXTI_InitTypeDef\* EXTI_InitStruct);

/\*\*
 \* @brief 将外部中断配置结构体初始化为默认值。
 \* @param EXTI\_InitStruct: 要初始化的外部中断配置结构体指针。
 \*/
void EXTI\_StructInit(EXTI_InitTypeDef\* EXTI_InitStruct);

/\*\*
 \* @brief 生成软件触发的外部中断。
 \* @param EXTI\_Line: 要生成中断的外部中断线。
 \*/
void EXTI\_GenerateSWInterrupt(uint32\_t EXTI_Line);
//主程序:
/\*\*
 \* @brief 检查指定外部中断线的中断标志位是否已设置。
 \* @param EXTI\_Line: 要检查的外部中断线。
 \* @retval 设置标志位的状态 (SET或RESET)。
 \*/
FlagStatus EXTI\_GetFlagStatus(uint32\_t EXTI_Line);

/\*\*
 \* @brief 清除指定外部中断线的中断标志位。
 \* @param EXTI\_Line: 要清除标志位的外部中断线。
 \*/
void EXTI\_ClearFlag(uint32\_t EXTI_Line);
//中断程序:
/\*\*
 \* @brief 检查指定外部中断线的中断挂起位是否已设置。
 \* @param EXTI\_Line: 要检查的外部中断线。
 \* @retval 挂起位的状态 (SET或RESET)。
 \*/
ITStatus EXTI\_GetITStatus(uint32\_t EXTI_Line);

/\*\*
 \* @brief 清除指定外部中断线的中断挂起位。
 \* @param EXTI\_Line: 要清除挂起位的外部中断线。
 \*/
void EXTI\_ClearITPendingBit(uint32\_t EXTI_Line);

7、配置NVIC

以下是对这些函数的代码注释解释:

/\*\*
 \* @brief 配置中断优先级分组。
 \* @param NVIC\_PriorityGroup: 中断优先级分组,可以是 NVIC\_PriorityGroup\_x 中的一个值。
 \*/
void NVIC\_PriorityGroupConfig(uint32\_t NVIC_PriorityGroup);

/\*\*
 \* @brief 初始化中断控制器 (NVIC) 寄存器。
 \* @param NVIC\_InitStruct: 包含中断控制器配置信息的结构体指针。
 \*/
void NVIC\_Init(NVIC_InitTypeDef\* NVIC_InitStruct);

/\*\*
 \* @brief 配置向量表的基地址和偏移量。
 \* @param NVIC\_VectTab: 向量表的基地址,可以是 NVIC\_VectTab\_RAM 或 NVIC\_VectTab\_FLASH。
 \* @param Offset: 向量表偏移量。
 \*/
void NVIC\_SetVectorTable(uint32\_t NVIC_VectTab, uint32\_t Offset);

/\*\*
 \* @brief 配置系统低功耗模式。
 \* @param LowPowerMode: 低功耗模式,可以是 SysTick\_CLKSource\_HCLK\_Div8 或 SysTick\_CLKSource\_HCLK。
 \* @param NewState: 新状态,可以是 ENABLE(启用)或 DISABLE(禁用)。
 \*/
void NVIC\_SystemLPConfig(uint8\_t LowPowerMode, FunctionalState NewState);

/\*\*
 \* @brief 配置SysTick定时器的时钟源。
 \* @param SysTick\_CLKSource: SysTick定时器的时钟源,可以是 SysTick\_CLKSource\_HCLK 或 SysTick\_CLKSource\_HCLK\_Div8。
 \*/
void SysTick\_CLKSourceConfig(uint32\_t SysTick_CLKSource);

这些函数用于配置和管理中断控制器 (NVIC) 和系统滴答定时器 (SysTick)。以下是它们的简要解释:

  • NVIC_PriorityGroupConfig 用于配置中断优先级分组,这是为了确定中断的优先级管理方式。
  • NVIC_Init 用于初始化中断控制器的寄存器,配置中断的优先级和其他设置。
  • NVIC_SetVectorTable 用于配置向量表的基地址和偏移量,这是中断处理程序的入口。
  • NVIC_SystemLPConfig 用于配置系统低功耗模式,以降低系统功耗。
  • SysTick_CLKSourceConfig 用于配置 SysTick 定时器的时钟源,以控制其工作时钟。

这些函数通常在初始化阶段用于配置系统的中断和定时器设置,以满足应用程序的需求。确保查阅您使用的STM32系列的参考手册和文档,以获取详细的配置信息和示例代码。

8、红外传感器中断计次

uint16\_t CountSensor_Count; // 存储传感器计数值的变量

void CountSensor\_Init(void)
{
    // 使能GPIOB和AFIO时钟
    RCC\_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC\_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    
    // 配置GPIOB引脚14为上拉输入模式
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数嵌入式工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/ecb219ed22817596703449f74d01fbb6.png)

![img](https://img-blog.csdnimg.cn/img_convert/941d47a7c0f78a999e0bdc1cc7b6e55c.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/03ad09e9eed0fd5b9991f2518777ec2d.png)

 **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

![img](https://img-blog.csdnimg.cn/img_convert/250aabe37ead1bbcd6bcf252ec8458cb.png)

![img](https://img-blog.csdnimg.cn/img_convert/fc5417da0551911dd8342e98c1a62bd1.png)

 

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)**

<img src="https://img-community.csdnimg.cn/images/73bb5de17851459088c6af944156ee24.jpg" alt="img" style="zoom: 67%;" />



# 最后

**资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~**

**你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!**

63)]

 **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[外链图片转存中...(img-sCkQhTHZ-1712311822764)]

[外链图片转存中...(img-VbUJ4yo0-1712311822766)]

 

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)**

<img src="https://img-community.csdnimg.cn/images/73bb5de17851459088c6af944156ee24.jpg" alt="img" style="zoom: 67%;" />



# 最后

**资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~**

**你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!**

**[更多资料点击此处获qu!!](https://bbs.csdn.net/topics/618376385)**
  • 25
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值