EXTI概念
EXTI(外部中断和事件控制器)是用来捕捉输入信号的变化并产生中断。
线的概念
如图可以分为三个部分,一个是信号输入即从GPIO输入进来,第二部分就是EXTI线用来捕获信号的上升和下降沿,第三部分就是产生中断。这样的EXTI线有20条。
线的内部结构
其中复用器是用来选择用哪个端口如GPIOA,选择了用EXTI线0去监听PA0,那就不能用EXTI线0去监听其他的PB0,PC0,PD0什么的。然后用边沿检测电路去检测是上升沿还是下降沿,然后选择模式是触发中断还是事件,当然还需要闭合开关。
选择线来监听引脚
配置EXTI初始化EXTI的线
配置NVIC
1.首先确定中断优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
2.配置中断
由于我们选择的是线5和线6,中断名为EXTI9_5,我们需要去库文件中找到这个中断名称,所以去库文件然后搜索IRQ,找到了对应的中断名称EXTI9_5_IRQn。然后配置抢占优先级还有子优先级还有闭合开关。
编写中断响应函数
1.去启动文件中找响应函数名称(下图最后一行)
2.判断那条线触发中断,并清除标志位
代码
#include "stm32f10x.h"
void App_OnBoardLED_Init(void);
void App_Button_Init(void);
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
App_OnBoardLED_Init();
App_Button_Init();
while(1)
{
}
}
void App_OnBoardLED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET);
}
void App_Button_Init(void)
{
// #1. 初始化PA5和PA6
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
// PA5
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// PA6
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// #2. 为EXTI5和EXIT6分配引脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6);
// #3. 初始化EXTI的线
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line5;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
EXTI_InitStruct.EXTI_Line = EXTI_Line6;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
// #4. 配置中断
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetFlagStatus(EXTI_Line5) == SET)
{
EXTI_ClearFlag(EXTI_Line5);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_RESET); // 亮灯
}
if(EXTI_GetFlagStatus(EXTI_Line6) == SET)
{
EXTI_ClearFlag(EXTI_Line6);
GPIO_WriteBit(GPIOC, GPIO_Pin_13, Bit_SET); // 灭灯
}
}
个人总结
1.我们是先对按钮和GPIO进行初始化
2.因为我们选择了PA5和PA6所以选择线的时候是line5和line6进行监听上升沿,所以我们要为EXTI5和6分配引脚。
3.初始化EXTI,线5线6,中断模式,上升沿,闭合开关
4.配置中断NVIC,因为是线5和线6监听其中断事件名称为EXTI9_5,抢占优先级和子优先级都是0,闭合开关
5.编写响应函数
总的流程图如下