【STM32】学习笔记:EXTI外部中断

一、外部中断简介

1、中断系统

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

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

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

2、EXTI简介

  • EXTI (Extern Interrupt)外部中断

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

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

  • 支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断 通道数︰16个GPIO_Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒

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

在这里难以理解的是:EXTI0包含的是PA0、PB0、PC0到PG0,EXTI1包含的是PA1、PB1、PC1到PG1,通过ETXI的数据选择器来确定EXTIx与哪一个端口相连,形成中断线路。

二、外部中断函数

        使用中断需要开启GPIO、AFIO时钟,EXTI的时钟与MCU核心同时开启,无需配置使能。将GPIO引脚与AFIO连接,将AFIO与EXTI连接形成中断线路。

1、开启时钟

void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)

(1)开启GPIO外设时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOx,ENABLE);

选择GPIOx的端口,开启GPIOx的时钟,可以查看库函数的解释来确定所用外设时钟在哪一个时钟线

(2)开启AFIO复用时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

开启AFIO的时钟

2、AFIO函数

(1)清除AFIO配置

void GPIO_AFIODeInit(void);

(2)锁定AFIO配置

void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

指定某个GPIOx端口的GPIO_Pin引脚的配置被锁定,防止意外修改

(3)

void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);

(4)

void GPIO_EventOutputCmd(FunctionalState NewState);

(5)引脚重映射

void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);

(6)配置AFIO的数据选择器

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);

其中GPIO_PortSource为外部中断源,GPIO_PinSource为外设中断线

@param  GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.
This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).

为EXTI中断线选择GPIO端口作为中断源,这个参数可以是x为A~G的GPIO_PortSourceGPIOx

@param  GPIO_PinSource: specifies the EXTI line to be configured.
This parameter can be GPIO_PinSourcex where x can be (0..15).

指定要配置的EXTI中断线,这个参数可以是x为0~15的GPIO_PinSourcex

例如,将EXTI1与PB1相连形成中断线路

GPIO_EXTILineConfig(GPIO_PortSourceB,GPIO_PinSource1)

(7)以太网外设

void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);

3、EXTI函数

(1)清除EXTI配置

void EXTI_DeInit(void);

(2)初始化EXTI配置

void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);

(3)参数结构体变量赋默认值

void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);

(4)软件触发外部中断

void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);

使用该函数可以触发一次指定的外部中断线EXTI_Line,软件模拟外部引脚触发中断。

(5)获取指定标志位是否置1

FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);

该函数读取EXTI中断寄存器的标志位,对中断是否有效不做判断。

(6)清除指定标志位

void EXTI_ClearFlag(uint32_t EXTI_Line);

(7)获取中断状态

ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);

与(5)类似,但该函数不仅读取EXTI的中断寄存器的标志位,还对中断是否有效(没有被EXT_IMR寄存器中断屏蔽)做出判断。

(8)清除指定中断线的挂起位

void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

与(6)类似,区别与(5)和(7)一样。

4、NVIC函数

(1)中断分组

void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);

配置先占优先级(抢占优先级)和从占优先级(响应优先级),整个MCU只有一种优先级分组,只需要调用一次。

(2)初始化NVIC

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);

根据指定结构体变量初始化NVIC

(3)设置中断向量表

void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);

(4)系统低功耗配置

void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);

三、外部中断

1、GPIO初始化

当GPIO用作EXTI输入线时,GPIO应使用浮空输入、上拉输入或下拉输入

GPIO_Mode_IN_FLOATING = 0x04,
GPIO_Mode_IPD = 0x28,
GPIO_Mode_IPU = 0x48,

GPIO完全配置示例如下

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);

2、EXTI外部中断初始化

创建EXTI结构体变量

EXTI_InitTypeDef EXTI_InitStructure;

结构体变量包含以下四个变量

typedef struct
{
  uint32_t EXTI_Line;               /*!< Specifies the EXTI lines to be enabled or disabled.
                                         This parameter can be any combination of @ref EXTI_Lines */
   
  EXTIMode_TypeDef EXTI_Mode;       /*!< Specifies the mode for the EXTI lines.
                                         This parameter can be a value of @ref EXTIMode_TypeDef */
​
  EXTITrigger_TypeDef EXTI_Trigger; /*!< Specifies the trigger signal active edge for the EXTI lines.
                                         This parameter can be a value of @ref EXTIMode_TypeDef */
​
  FunctionalState EXTI_LineCmd;     /*!< Specifies the new state of the selected EXTI lines.
                                         This parameter can be set either to ENABLE or DISABLE */ 
}EXTI_InitTypeDef;
  • EXTI_Line:指定外部中断线,包含EXTI_Line0~EXTI_Line15

  • EXTI_Mode:指定外部中断线的模式

    参数作用
    EXTI_Mode_Interrupt中断模式
    EXTI_Mode_Event时间模式
  • EXTI_Trigger:指定触发信号的有效边沿

    参数作用
    EXTI_Trigger_Rising上升沿触发
    EXTI_Trigger_Falling下降沿触发
    EXTI_Trigger_Rising_Falling上升沿和下降沿都触发

  • EXTI_LineCmd:指定选择的中断线的新状态,ENABLE或DISABLE

初始化外部中断结构体变量示例

EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line0;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);

3、NVIC配置

确定中断分组

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/**
  * @brief  Configures the priority grouping: pre-emption priority and subpriority.
  * @param  NVIC_PriorityGroup: specifies the priority grouping bits length. 
  *   This parameter can be one of the following values:
  *     @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
  *                                4 bits for subpriority
  *     @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
  *                                3 bits for subpriority
  *     @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
  *                                2 bits for subpriority
  *     @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
  *                                1 bits for subpriority
  *     @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
  *                                0 bits for subpriority
  * @retval None
  */

创建NVIC结构体变量

NVIC_InitTypeDef NVIC_InitStructure;

结构体变量包含以下四个变量

typedef struct
{
  uint8_t NVIC_IRQChannel;                    /*!< Specifies the IRQ channel to be enabled or disabled.
                                                   This parameter can be a value of @ref IRQn_Type 
                                                   (For the complete STM32 Devices IRQ Channels list, please
                                                    refer to stm32f10x.h file) */
​
  uint8_t NVIC_IRQChannelPreemptionPriority;  /*!< Specifies the pre-emption priority for the IRQ channel
                                                   specified in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */
​
  uint8_t NVIC_IRQChannelSubPriority;         /*!< Specifies the subpriority level for the IRQ channel specified
                                                   in NVIC_IRQChannel. This parameter can be a value
                                                   between 0 and 15 as described in the table @ref NVIC_Priority_Table */
​
  FunctionalState NVIC_IRQChannelCmd;         /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel
                                                   will be enabled or disabled. 
                                                   This parameter can be set either to ENABLE or DISABLE */   
} NVIC_InitTypeDef;
  • NVIC_IRQChannel:指定通道开启或关闭,可以通过对当前工程查找IRQn_Type来查询所需通道

由于使用的是STM32F103C8T6,选择在STM32F10X_MD查找

  • NVIC_IRQChannelCmd:指定中断通道是使能或失能,参        数为ENABLE或DISABLE

  • NVIC_IRQChannelPreemptionPriority:指定抢占优先级,0~15

  • NVIC_IRQChannelSubPriority:指定响应优先级,0~15

抢占优先级和响应优先级需按照中断分组来确定

4、编写中断函数

        中断函数名为固定唯一的,可以在启动文件startup_stm32f10x_md.s中查找

        例如,中断线EXTI0的中断函数,在进入中断函数后要清除EXTI中断线的挂起位,以防进入死循环。

void EXTI0_IRQHandler(void){
    //函数体
    EXTI_ClearITPendingBit(EXTI_Line0);
}

        值得注意的是,EXTI_Line10到EXTI_Line15使用的是同一条中断线,需要使用判断语句来进行区分是哪一个中断。

void EXTI15_10_IRQHandler(void){
    if(EXTI_GetITStatus(EXTI_Line10) == SET){
        //函数体
        EXTI_ClearITPendingBit(EXTI_Line10);
    }
}

四、示例代码

        主函数或头文件

//开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//配置GPIO    
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//配置EXTI
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line0;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_Init(&EXTI_InitStructure);
//配置NVIC    
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;    
NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);

中断函数

void EXTI0_IRQHandler(void){
    //函数体
}

  • 36
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值