自学内容网 自学内容网

【STM32-学习笔记-2-】外部中断

外部中断

Ⅰ、EXIT函数

// 重置所有EXTI(外部中断/事件控制器)为默认值
void EXTI_DeInit(void);

// 初始化EXTI,根据初始化结构体配置参数
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

// 初始化EXTI初始化结构体的默认值
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);

// 生成指定EXTI线的软件中断
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);

// 获取指定EXTI线的标志状态
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
// 清除指定EXTI线的标志
void EXTI_ClearFlag(uint32_t EXTI_Line);

// 获取指定EXTI线的中断状态
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
// 清除指定EXTI线的中断待处理位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

Ⅱ、EXTI_InitTypeDef结构体参数

①、EXTI_Line

指定要启用或禁用的EXTI线(中断线)

  • 该参数可以是@ref EXTI_Lines

    • 宏定义解释

      这些宏定义用于选择特定的外部中断线。每个宏定义一个特定的中断线,值为该中断线对应的位掩码

      • EXTI_Line0EXTI_Line19
        • :从 ((uint32_t)0x00001)((uint32_t)0x80000)
        • 描述:分别表示选择外部中断线0到19。每个宏定义的值是该中断线对应的位掩码,例如 EXTI_Line0 的值为 0x00001,表示第0位被设置为1,其他位为0

      特殊中断线:

      • EXTI_Line16:连接到PVD(可编程电压检测器)输出
      • EXTI_Line17:连接到RTC(实时时钟)报警事件
      • EXTI_Line18:连接到USB设备/USB OTG FS从挂起状态唤醒事件
      • EXTI_Line19:连接到以太网唤醒事件

      宏函数

      1. IS_EXTI_LINE(LINE)
        • 描述:检查给定的中断线选择是否有效
        • 参数LINE,代表外部中断线选择
        • 功能:检查LINE是否为有效的中断线组合。具体来说,检查LINE的高16位是否为0,且不为0
        • 返回值:如果LINE有效,返回1(真),否则返回0(假)
      2. IS_GET_EXTI_LINE(LINE)
        • 描述:检查给定的中断线选择是否为单个中断线
        • 参数LINE,代表外部中断线选择
        • 功能:检查LINE是否等于预定义的单个中断线选择宏中的任一个
        • 返回值:如果LINE为单个中断线,返回1(真),否则返回0(假)

      表格:

      宏定义描述
      EXTI_Line0~EXTI_Line150x00001~0x08000选择外部中断线0~15
      EXTI_Line160x10000连接到PVD输出的中断线
      EXTI_Line170x20000连接到RTC报警事件的中断线
      EXTI_Line180x40000连接到USB唤醒事件的中断线
      EXTI_Line190x80000连接到以太网唤醒事件的中断线
      宏函数描述
      IS_EXTI_LINE(LINE)检查LINE是否为有效的外部中断线选择
      IS_GET_EXTI_LINE(LINE)检查LINE是否为单个外部中断线选择

②、EXTI_LineCmd

指定所选EXTI线(中断线)的新状态

  • ENABLE:使能
  • DISABLE:失能

③、EXTI_Mode

指定EXIT的模式

  • 该参数可以是@ref EXTIMode_TypeDef

    • 枚举类型定义

      typedef enum
      {
       EXTI_Mode_Interrupt = 0x00, /*!< 配置为中断模式 */
       EXTI_Mode_Event = 0x04      /*!< 配置为事件模式 */
      } EXTIMode_TypeDef;
      
      • EXTI_Mode_Interrupt:值为 0x00,表示配置为中断模式
        • 在这种模式下,当外部信号触发中断时,会生成一个中断请求,可以中断当前的CPU操作,执行中断服务程序(ISR)
      • EXTI_Mode_Event:值为 0x04,表示配置为事件模式
        • 在这种模式下,当外部信号触发事件时,不会生成中断请求,但可以用于触发其他硬件操作,如启动DMA传输

      宏函数

      #define IS_EXTI_MODE(MODE) (((MODE) == EXTI_Mode_Interrupt) || ((MODE) == EXTI_Mode_Event))
      
      • 描述:检查给定的模式是否为有效的EXTI模式
      • 参数MODE,代表EXTI模式
      • 功能:检查MODE是否等于预定义的模式中的任一个
      • 返回值:如果MODE有效,返回1(真),否则返回0(假)

④、EXTI_Trigger

指定EXTI的触发条件

  • 该参数可以是@ref EXTITrigger_TypeDef

    • 枚举类型定义

      typedef enum
      {
       EXTI_Trigger_Rising = 0x08,          /*!< 上升沿触发 */
       EXTI_Trigger_Falling = 0x0C,         /*!< 下降沿触发 */
       EXTI_Trigger_Rising_Falling = 0x10   /*!< 上升沿和下降沿都触发 */
      } EXTITrigger_TypeDef;
      
      • EXTI_Trigger_Rising:值为 0x08,表示配置为上升沿触发
        • 当外部信号从低电平变为高电平时,触发中断或事件
      • EXTI_Trigger_Falling:值为 0x0C,表示配置为下降沿触发
        • 当外部信号从高电平变为低电平时,触发中断或事件
      • EXTI_Trigger_Rising_Falling:值为 0x10,表示配置为上升沿和下降沿都触发
        • 当外部信号从低电平变为高电平或从高电平变为低电平时,触发中断或事件

      宏函数

      #define IS_EXTI_TRIGGER(TRIGGER) (((TRIGGER) == EXTI_Trigger_Rising) || \
                                        ((TRIGGER) == EXTI_Trigger_Falling) || \
                                        ((TRIGGER) == EXTI_Trigger_Rising_Falling))
      
      • 描述:检查给定的触发条件是否有效
      • 参数TRIGGER,代表EXTI的触发条件
      • 功能:检查TRIGGER是否等于预定义的触发条件中的任一个
      • 返回值:如果TRIGGER有效,返回1(真),否则返回0(假)

Ⅲ、NVIC函数

// 配置NVIC(嵌套向量中断控制器)优先级分组
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

// 初始化NVIC,根据初始化结构体配置参数
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

// 设置NVIC中断向量表的位置和偏移量
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);

// 配置NVIC的系统低功耗模式
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);

Ⅳ、NVIC_InitTypeDef结构体参数

①、NVIC_IRQChannel

指定要启用或禁用的IRQ通道

  • 该参数可以是@ref IRQn_Type

      • 描述:指定要启用或禁用的中断请求(IRQ)通道

      • 取值范围:可以是IRQn_Type枚举类型中的任意值。IRQn_Type定义了STM32设备的所有中断通道。具体值可以参考stm32f10x.h文件中的定义

      • 示例

        NVIC_IRQChannel = USART1_IRQn;  // 例如,启用USART1的中断
        

        image-20250112134951924

②、NVIC_IRQChannelCmd

配置NVIC_IRQChannel中定义的IRQ通道启用或禁用

  • ENABLE:使能(启用)
  • DISABLE:失能(禁用)

③、NVIC_IRQChannelPreemptionPriority

指定IRQ通道的抢占优先级

  • 在NVIC_IRQChannel中指定。该参数可以是一个值在0~15之间

      • 描述:指定在NVIC_IRQChannel中指定的IRQ通道的抢占优先级

      • 取值范围:0到15。0表示最高优先级,15表示最低优先级

      • 示例

        NVIC_IRQChannelPreemptionPriority = 0;  // 最高优先级
        

④、NVIC_IRQChannelSubPriority

指定IRQ通道的子优先级

  • 在NVIC_IRQChannel。该参数可以是一个值在0~15之间

      • 描述:指定在NVIC_IRQChannel中指定的IRQ通道的子优先级

      • 取值范围:0到15。0表示最高优先级,15表示最低优先级

      • 示例

        NVIC_IRQChannelSubPriority = 1;  // 子优先级为1
        
  • 抢占优先级:当多个中断同时发生时,抢占优先级高的中断会先被处理。如果抢占优先级相同,则子优先级高的中断先被处理
  • 子优先级:在抢占优先级相同的情况下,子优先级用于进一步区分中断的优先级

Ⅲ、EXIT基本结构

image-20250112134102539

Ⅳ、配置外部中断

  1. 开启GPIO和AFIO的时钟
    • 启用AFIO,允许配置引脚的备用功能,比如将某些引脚用作外部中断输入
  2. 配置GPIO
  3. 将引脚配置为外部中断(EXTI)线的触发源
  4. 配置EXIT
  5. 配置嵌套向量中断控制器(NVIC)的优先级分组
  6. 配置NVIC
#include "stm32f10x.h"                  // Device header

void CountSensor_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//启用AFIO,允许配置引脚的备用功能,比如将某些引脚用作外部中断输入
    //配置GPIO
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
  
    //配置EXIT外部中断
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//将PB14引脚配置为外部中断(EXTI)线的触发源
    
    EXTI_InitTypeDef EXTI_InitStruct;
    EXTI_InitStruct.EXTI_Line = EXTI_Line14;//选择外部中断线14
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;//启用外部中断线14
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//设置外部中断模式为中断模式
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//选择下降沿触发
    EXTI_Init(&EXTI_InitStruct);//初始化外部中断
  
    //设置NVIC
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置嵌套向量中断控制器(NVIC)的优先级分组
    
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;//选择外部中断15到10的IRQ通道
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//启用这个IRQ通道
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//设置抢占优先级为1
    NVIC_InitStruct.NVIC_IRQChannelSubPriority  = 1;//设置响应优先级为1
    NVIC_Init(&NVIC_InitStruct);
}
/*
//中断程序示例
void EXTI15_10_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line14) == SET)//判断是否进入中断
    {
        //执行中断程序 
        
        EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位
    }
}
*/

//*****************************************************************
void EXTI0_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line0) == SET)//顺时针旋转触发外部中断
    {
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)
        {
            Encoder_Count--;//逆时针旋转
        }
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

void EXTI1_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line1) == SET)//顺时针旋转触发外部中断
    {
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0)
        {
            Encoder_Count++;//顺时针旋转
        }
        EXTI_ClearITPendingBit(EXTI_Line1);
    }
}

void EXTI15_10_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line14) == SET)
    {
        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14) == 1)
        {
            Encoder_Count = 0;//按下旋转编码器计数清零
        }
        EXTI_ClearITPendingBit(EXTI_Line14);
    }
}


原文地址:https://blog.csdn.net/qq_63040946/article/details/145094369

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!