文章目录
- 一、EXTI
- 二、EXTI功能框图
-
- [ 1、EXTI框图](# 1、EXTI框图)
- [ 2、EXTI框图详解](# 2、EXTI框图详解)
- [ 3、中断/事件线](# 3、中断/事件线)
- [ 4、EXTI结构体详解](# 4、EXTI结构体详解)
- 三、GPIO中断
-
- [ 1、编程要点](# 1、编程要点)
- [ 2、硬件设计](# 2、硬件设计)
- [ 3、编程代码](# 3、编程代码)
一、EXTI
EXTI:External interrupt / event controller 外部 中断/事件 控制器
EXTI(External interrupt/event controller)---外部中断/事件控制器,管理了控制器的20个中断/事件线。
每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。
EXTI可以实现对每个中断/事件线进行单独配置, 可以单独配置为中断或者事件,以及触发事件的属性。
二、EXTI功能框图
1、EXTI框图

2、EXTI框图详解
编号1:输入线
EXTI控制器有19个中断/事件输入线,这些输入线可以通过寄存器设置为任意一个GPIO,也可以是一些外设的事件。
输入线一般是存在电平变化的信号。
编号2:边沿检测电路
根据上升沿触发选择寄存器(EXTI_RTSR)和下降沿触发选择寄存器(EXTI_FTSR)对应位的设置来控制信号触发。
边沿检测电路以输入线作为信号输入端,如果检测到有边沿跳变就输出有效信号1给编号3电路,否则输出无效信号0。
可以设置只有上升沿触发、只有下降沿触发或者上升沿和下降沿都触发。
编号3:或门电路
输入来自编号2电路,另外一个输入来自软件中断事件寄存器(EXTI_SWIER)。
EXTI_SWIER允许我们通过程序控制就可以启动中断/事件线。
或门电路作用就是有1就为1。
这两个输入随便一个有有效信号1就可以输出1给编号4和编号6电路。
编号4:与门电路
一个输入是编号3电路,另外一个输入来自中断屏蔽寄存器(EXTI_IMR)。
门电路要求输入都为1才输出1, 导致的结果是如果EXTI_IMR设置为0时,
那不管编号3电路的输出信号是1还是0,最终编号4电路输出的信号都为0;
如果EXTI_IMR设置为1时, 最终编号4电路输出的信号才由编号3电路的输出信号决定。
编号5:输出到NVIC
将EXTI_PR寄存器内容输出到NVIC内,从而实现系统中断事件控制。
编号6:与门电路
一个输入来自编号3电路, 另外一个输入来自事件屏蔽寄存器(EXTI_EMR)。
如果EXTI_EMR设置为0时,那不管编号3电路的输出信号是1还是0,最终编号6电路输出的信号都为0;
如果EXTI_EMR设置为1时,最终编号6电路输出的信号才由编号3电路的输出信号决定。
编号7:脉冲发生器电路
当它的输入端,即编号6电路的输出端,是一个有效信号1时就会产生一个脉冲;如果输入端是无效信号就不会输出脉冲。
编号8:脉冲信号
脉冲信号可以给其他外设电路使用,比如定时器TIM、模拟数字转换器ADC等。
总结:
EXTI可分为两大部分功能,一个是产生中断12345 ,另一个是产生事件 123678。
3、中断/事件线
EXTI有20个中断/事件线,每个GPIO都可以被设置为输入线,占用EXTI0至EXTI15, 还有另外七根用于特定的外设事件.

EXTI16-19,4根特定外设中断/事件线由外设触发。
EXTI0-15用于GPIO,通过编程控制可以实现任意一个GPIO作为EXTI的输入源。
EXTI0可以通过AFIO的外部中断配置寄存器1(AFIO_EXTICR1)的EXTI0[3:0]位选择配置为PA0、 PB0、PC0、PD0、PE0、PF0、PG0、PH0或者PI0。

4、EXTI结构体详解
c
typedef struct {
uint32_t EXTI_Line; // 中断/事件线
EXTIMode_TypeDef EXTI_Mode; // EXTI模式
EXTITrigger_TypeDef EXTI_Trigger; // 触发类型
FunctionalState EXTI_LineCmd; // EXTI使能
} EXTI_InitTypeDef;
XTI_Line:
EXTI中断/事件线选择,可选EXTI0至EXTI19,可参考表 EXTI中断_事件线 选择。
EXTI_Mode:
EXTI模式选择,可选为产生中断(EXTI_Mode_Interrupt)或者产生事件(EXTI_Mode_Event)。
EXTI_Trigger:
EXTI边沿触发事件,可选上升沿触发(EXTI_Trigger_Rising)、 下降沿触发( EXTI_Trigger_Falling)或者上升沿和下降沿都触发( EXTI_Trigger_Rising_Falling)。
EXTI_LineCmd:
控制是否使能EXTI线,可选使能EXTI线(ENABLE)或禁用(DISABLE)。
三、GPIO中断
1、编程要点
1,初始化要连接到EXTI的 GPIO。
2,初始化EXTI用于产生中断事件。
3,初始化NVIC,用于处理中断。
4,编写中断服务函数。
5,main函数。
2、硬件设计

3、编程代码
按键和EXTI宏定义
按键和EXTI宏定义 EXTI.h文件内
c
//引脚定义
#define KEY1_INT_GPIO_PORT GPIOA
#define KEY1_INT_GPIO_CLK (RCC_APB2Periph_GPIOA\
|RCC_APB2Periph_AFIO)
#define KEY1_INT_GPIO_PIN GPIO_Pin_0
#define KEY1_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOA
#define KEY1_INT_EXTI_PINSOURCE GPIO_PinSource0
#define KEY1_INT_EXTI_LINE EXTI_Line0
#define KEY1_INT_EXTI_IRQ EXTI0_IRQn
#define KEY1_IRQHandler EXTI0_IRQHandler
#define KEY2_INT_GPIO_PORT GPIOC
#define KEY2_INT_GPIO_CLK (RCC_APB2Periph_GPIOC\
|RCC_APB2Periph_AFIO)
#define KEY2_INT_GPIO_PIN GPIO_Pin_13
#define KEY2_INT_EXTI_PORTSOURCE GPIO_PortSourceGPIOC
#define KEY2_INT_EXTI_PINSOURCE GPIO_PinSource13
#define KEY2_INT_EXTI_LINE EXTI_Line13
#define KEY2_INT_EXTI_IRQ EXTI15_10_IRQn
嵌套向量中断控制器NVIC配置
嵌套向量中断控制器NVIC配置 EXTI.c文件内
c
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 配置NVIC为优先级组1 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
/* 配置中断源:按键1 */
NVIC_InitStructure.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;
/* 配置抢占优先级:1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 配置子优先级:1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中断通道 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 配置中断源:按键2,其他使用上面相关配置 */
NVIC_InitStructure.NVIC_IRQChannel = KEY2_INT_EXTI_IRQ;
NVIC_Init(&NVIC_InitStructure);
}
EXTI中断配置.
EXTI中断配置 EXTI.c文件内
c
void EXTI_Key_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
/*开启按键GPIO口的时钟*/
RCC_APB2PeriphClockCmd(KEY1_INT_GPIO_CLK,ENABLE);
/* 配置 NVIC 中断*/
NVIC_Configuration();
/*--------------------------KEY1配置---------------------*/
/* 选择按键用到的GPIO */
GPIO_InitStructure.GPIO_Pin = KEY1_INT_GPIO_PIN;
/* 配置为浮空输入 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_INT_GPIO_PORT, &GPIO_InitStructure);
/* 选择EXTI的信号源 */
GPIO_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, \
KEY1_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY1_INT_EXTI_LINE;
/* EXTI为中断模式 */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 上升沿中断 */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
/* 使能中断 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/*--------------------------KEY2配置------------------*/
/* 选择按键用到的GPIO */
GPIO_InitStructure.GPIO_Pin = KEY2_INT_GPIO_PIN;
/* 配置为浮空输入 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY2_INT_GPIO_PORT, &GPIO_InitStructure);
/* 选择EXTI的信号源 */
GPIO_EXTILineConfig(KEY2_INT_EXTI_PORTSOURCE, \
KEY2_INT_EXTI_PINSOURCE);
EXTI_InitStructure.EXTI_Line = KEY2_INT_EXTI_LINE;
/* EXTI为中断模式 */
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
/* 下降沿中断 */
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
/* 使能中断 */
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
EXTI中断服务函数
EXTI中断服务函数 stm32f10x_it.c内
c
void EXTI0_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if (EXTI_GetITStatus(KEY1_INT_EXTI_LINE) != RESET) {
// LED1 取反
LED1_TOGGLE;
//清除中断标志位
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
void EXTI15_10_IRQHandler(void)
{
//确保是否产生了EXTI Line中断
if (EXTI_GetITStatus(KEY2_INT_EXTI_LINE) != RESET) {
// LED2 取反
LED2_TOGGLE;
//清除中断标志位
EXTI_ClearITPendingBit(KEY2_INT_EXTI_LINE);
}
}
Main函数
c
int main(void)
{
/* LED 端口初始化 */
LED_GPIO_Config();
/* 初始化EXTI中断,按下按键会触发中断,
* 触发中断会进入stm32f10x_it.c文件中的函数
* KEY1_IRQHandler和KEY2_IRQHandler,处理中断,反转LED灯。
*/
EXTI_Key_Config();
/* 等待中断,由于使用中断方式,CPU不用轮询按键 */
while (1) {
}
}