文章目录
- 外部中断
- Ⅰ、EXIT函数
- Ⅱ、EXTI_InitTypeDef结构体参数
- ①、EXTI_Line
- ②、EXTI_LineCmd
- ③、EXTI_Mode
- ④、EXTI_Trigger
- Ⅲ、NVIC函数
- Ⅳ、NVIC_InitTypeDef结构体参数
- ①、NVIC_IRQChannel
- ②、NVIC_IRQChannelCmd
- ③、NVIC_IRQChannelPreemptionPriority
- ④、NVIC_IRQChannelSubPriority
- Ⅲ、EXIT基本结构
- Ⅳ、配置外部中断
外部中断
Ⅰ、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_Line0
到EXTI_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
:连接到以太网唤醒事件宏函数
IS_EXTI_LINE(LINE)
- 描述:检查给定的中断线选择是否有效
- 参数:
LINE
,代表外部中断线选择- 功能:检查
LINE
是否为有效的中断线组合。具体来说,检查LINE
的高16位是否为0,且不为0- 返回值:如果
LINE
有效,返回1
(真),否则返回0
(假)IS_GET_EXTI_LINE(LINE)
- 描述:检查给定的中断线选择是否为单个中断线
- 参数:
LINE
,代表外部中断线选择- 功能:检查
LINE
是否等于预定义的单个中断线选择宏中的任一个- 返回值:如果
LINE
为单个中断线,返回1
(真),否则返回0
(假)表格:
宏定义 值 描述 EXTI_Line0
~EXTI_Line15
0x00001~0x08000 选择外部中断线0~15 EXTI_Line16
0x10000 连接到PVD输出的中断线 EXTI_Line17
0x20000 连接到RTC报警事件的中断线 EXTI_Line18
0x40000 连接到USB唤醒事件的中断线 EXTI_Line19
0x80000 连接到以太网唤醒事件的中断线
宏函数 描述 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的中断
②、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基本结构
Ⅳ、配置外部中断
- 开启GPIO和AFIO的时钟
- 启用AFIO,允许配置引脚的备用功能,比如将某些引脚用作外部中断输入
- 配置GPIO
- 将引脚配置为外部中断(EXTI)线的触发源
- 配置EXIT
- 配置嵌套向量中断控制器(NVIC)的优先级分组
- 配置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);
}
}