目的:使用外部中断方式触发按键,会使用外部中断的操作
配置文件:#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_exti.h"
寄存器:EXTI_IMR:高13位保留,低19位对应19个中断线编号,置1时开放该线上外部 中断
EXTI_EMR:高13位保留,低19位对应19个中断线编号,置1时开放该线上事 件中断
EXTI_RTSR:高13位保留,低19位对应19个中断线编号,置1时允许上升沿触 发事件和外部中断
EXTI_FTSR:高13位保留,低19位对应19个中断线编号,置1时允许下降沿触 发事件和外部中断
EXTI_SWIER:高13位保留,低19位对应19个中断线编号,置1时允许软件中 断,引起EXTI_PR挂起位置1,在IMR或EMR允许时产生中断
EXTI_PR:发生触发请求时置1,向该位写1可清除标志位
结构体定义:
中断向量初始化结构体:
typedef struct
{
uint8_t NVIC_IRQChannel; //中断通道
uint8_t NVIC_IRQChannelPreemptionPriority; //抢占优先级
uint8_t NVIC_IRQChannelSubPriority; //次优先级
FunctionalState NVIC_IRQChannelCmd; / /使能中断
} NVIC_InitTypeDef;
其中宏定义有
typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;//使能宏定义
中断通道宏定义(注意中断线5以后的标号有变化)
EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */
EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */
EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */
EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */
EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */
EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */
EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */
中断优先级设置表
中断初始化结构体
typedef struct
{
uint32_t EXTI_Line; //无符号32位变量设置中断线
EXTIMode_TypeDef EXTI_Mode; //中断模式
EXTITrigger_TypeDef EXTI_Trigger; //中断触发方式
FunctionalState EXTI_LineCmd; //中断使能
}EXTI_InitTypeDef;
其中有几个宏定义枚举量:
typedef enum //中断模式选择,外部中断和事件中断
{
EXTI_Mode_Interrupt = 0x00,
EXTI_Mode_Event = 0x04
}EXTIMode_TypeDef;
typedef enum //下降沿,上升沿,两者兼有
{
EXTI_Trigger_Rising = 0x08,
EXTI_Trigger_Falling = 0x0C,
EXTI_Trigger_Rising_Falling = 0x10
}EXTITrigger_TypeDef;
中断线定义
#define EXTI_Line0 ((uint32_t)0x00001) /*!< External interrupt line 0 */
#define EXTI_Line1 ((uint32_t)0x00002) /*!< External interrupt line 1 */
#define EXTI_Line2 ((uint32_t)0x00004) /*!< External interrupt line 2 */
#define EXTI_Line3 ((uint32_t)0x00008) /*!< External interrupt line 3 */
#define EXTI_Line4 ((uint32_t)0x00010) /*!< External interrupt line 4 */
#define EXTI_Line5 ((uint32_t)0x00020) /*!< External interrupt line 5 */
#define EXTI_Line6 ((uint32_t)0x00040) /*!< External interrupt line 6 */
#define EXTI_Line7 ((uint32_t)0x00080) /*!< External interrupt line 7 */
#define EXTI_Line8 ((uint32_t)0x00100) /*!< External interrupt line 8 */
#define EXTI_Line9 ((uint32_t)0x00200) /*!< External interrupt line 9 */
#define EXTI_Line10 ((uint32_t)0x00400) /*!< External interrupt line 10 */
#define EXTI_Line11 ((uint32_t)0x00800) /*!< External interrupt line 11 */
#define EXTI_Line12 ((uint32_t)0x01000) /*!< External interrupt line 12 */
#define EXTI_Line13 ((uint32_t)0x02000) /*!< External interrupt line 13 */
#define EXTI_Line14 ((uint32_t)0x04000) /*!< External interrupt line 14 */
#define EXTI_Line15 ((uint32_t)0x08000) /*!< External interrupt line 15 */
#define EXTI_Line16 ((uint32_t)0x10000) /*!< External interrupt line 16 Connected to the PVD Output */
#define EXTI_Line17 ((uint32_t)0x20000) /*!< External interrupt line 17 Connected to the RTC Alarm event */
#define EXTI_Line18 ((uint32_t)0x40000) /*!< External interrupt line 18 Connected to the USB Device/USB OTG FS
Wakeup from suspend event */
#define EXTI_Line19 ((uint32_t)0x80000) /*!< External interrupt line 19 Connected to the Ethernet Wakeup event */
库函数:
NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) //中断向量初始化函数,参数:中断向量初始化结构体
EXTI_DeInit(void) 中断初始化为缺省值
EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) 中断初始化为中断初始化结构体中的指定值
参数:中断初始化结构体
EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct)中断初始化为复位值 参数:中断初始化结构体
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line) 查询中断标志位,参数,无符号32位中断线标号,返回该中断线的中断标志位是否置1
EXTI_ClearFlag(uint32_t EXTI_Line) 清除中断标志位,参数,无符号32位中断线标号
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)查询中断标志位并查看是否被屏蔽,参数,无符号32位中断线标号,返回中断线上标志位是否置1而且未被屏蔽
EXTI_ClearITPendingBit(uint32_t EXTI_Line)清空中断标志位,与之前那个完全相同,参数,无符号32位中断线标号
GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource),这个函数属于GPIO的配置,所以单独列写,用于指定IO口作为中断的输入口,这个函数的参数有如下宏定义:
#define GPIO_PinSource0 ((uint8_t)0x00)
#define GPIO_PinSource1 ((uint8_t)0x01)
#define GPIO_PinSource2 ((uint8_t)0x02)
#define GPIO_PinSource3 ((uint8_t)0x03)
#define GPIO_PinSource4 ((uint8_t)0x04)
#define GPIO_PinSource5 ((uint8_t)0x05)
#define GPIO_PinSource6 ((uint8_t)0x06)
#define GPIO_PinSource7 ((uint8_t)0x07)
#define GPIO_PinSource8 ((uint8_t)0x08)
#define GPIO_PinSource9 ((uint8_t)0x09)
#define GPIO_PinSource10 ((uint8_t)0x0A)
#define GPIO_PinSource11 ((uint8_t)0x0B)
#define GPIO_PinSource12 ((uint8_t)0x0C)
#define GPIO_PinSource13 ((uint8_t)0x0D)
#define GPIO_PinSource14 ((uint8_t)0x0E)
#define GPIO_PinSource15 ((uint8_t)0x0F)
#define GPIO_PortSourceGPIOA ((uint8_t)0x00)
#define GPIO_PortSourceGPIOB ((uint8_t)0x01)
#define GPIO_PortSourceGPIOC ((uint8_t)0x02)
#define GPIO_PortSourceGPIOD ((uint8_t)0x03)
#define GPIO_PortSourceGPIOE ((uint8_t)0x04)
#define GPIO_PortSourceGPIOF ((uint8_t)0x05)
#define GPIO_PortSourceGPIOG ((uint8_t)0x06)
注意:FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line)只是检测是否产生了中断标志位, 并不一定响应中断
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)出了检测是否中断标志位是否置1外 还确认是不是中断不被屏蔽,会响应中断
EXTI_ClearITPendingBit(uint32_t EXTI_Line)与EXTI_ClearFlag(uint32_t EXTI_Line) 功能是相同的,都是清除中断标志位的。
程序代码分析(代码出自FIRE)
static void NVIC_Configuration(void) // 配置中断向量
{
NVIC_InitTypeDef NVIC_InitStructure; //结构体定义中断向量结构体
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//设置中断向量通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//设置子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//中断向量通道使能
NVIC_Init(&NVIC_InitStructure);
}
void EXTI_PA0_Config(void)//中断配置函数
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure; //结构体定义中断结构体
/* config the extiline clock and AFIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); //开启GPIOA时钟和第二功能时钟
/* config the NVIC */
NVIC_Configuration();//中断向量配置
/* EXTI line gpio config*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* EXTI line mode config */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); //选择A0为中断口
EXTI_InitStructure.EXTI_Line = EXTI_Line0;//中断线0
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿中断
EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断使能
EXTI_Init(&EXTI_InitStructure); //调用中断初始化函数
}
开放总中断和关闭总中断的宏定义,中断前需调用
#define CLI() __set_PRIMASK(1) /
#define SEI() __set_PRIMASK(0) /
中断服务函数
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0) != RESET) //检查中断是否开启
{
LED1_TOGGLE;//进入中断则led取反
EXTI_ClearITPendingBit(EXTI_Line0); //清除中断标志位
}
}
小总结:1、配置中断首先配置中断向量,再配置中断,配置中断时要调用中断向量的配置, 并在GPIO中配置中断口的选择
2、中断函数开始时需确认中断是否响应,结束时需要清除中断标志位
3、Stm32有19个中断线,其中16个为IO口外部中断,每一个对应IO口编号(A...E), 一共有80个中断,其它的3个 EXTI线16连接到PVD输出 EXTI线17连接到 RTC闹钟事件 EXTI线18连接到USB唤醒事件
4、中断挂起寄存器实际上就是中断标志位寄存器
5、中断服务函数在stm32f10x_it.c 文件中定义,这里定义了一些基本的中断服务 函数