记录一次EXTI使用中遇到的问题

今天上午加入一个功能时出现了问题,PB12~15配置外部中断失败,原因是操作AFIO前没有使能它的时钟。

我的目标是:
设置PA4 PA5 PA6 PA7 PB12 PB13 PB14 PB15为外部中断输入,每个引脚接收到一个上升沿就将引脚对应的计数加一。
配置代码如下(有问题):

//A4
#define Fre1_EXTI_PortSource     GPIO_PortSourceGPIOA
#define Fre1_EXTI_PinSource      GPIO_PinSource4
//A5
#define Fre2_EXTI_PortSource    GPIO_PortSourceGPIOA
#define Fre2_EXTI_PinSource     GPIO_PinSource5
//A6
#define Fre3_EXTI_PortSource     GPIO_PortSourceGPIOA
#define Fre3_EXTI_PinSource      GPIO_PinSource6
//A7
#define Fre4_EXTI_PortSource     GPIO_PortSourceGPIOA
#define Fre4_EXTI_PinSource      GPIO_PinSource7
//B12
#define Fre5_EXTI_PortSource     GPIO_PortSourceGPIOB
#define Fre5_EXTI_PinSource      GPIO_PinSource12
//B13
#define Fre6_EXTI_PortSource     GPIO_PortSourceGPIOB
#define Fre6_EXTI_PinSource      GPIO_PinSource13
//B14
#define Fre7_EXTI_PortSource     GPIO_PortSourceGPIOB
#define Fre7_EXTI_PinSource      GPIO_PinSource14
//B15
#define Fre8_EXTI_PortSource     GPIO_PortSourceGPIOB
#define Fre8_EXTI_PinSource      GPIO_PinSource15

#define EXTI_AFIO_CLK             RCC_APB2Periph_AFIO

//GPIOA_4~7
#define FRE1_4_EXTI_PORT 					  GPIOA
#define FRE1_EXTI_PIN   				  GPIO_Pin_4
#define FRE2_EXTI_PIN        		  GPIO_Pin_5
#define FRE3_EXTI_PIN   				  GPIO_Pin_6
#define FRE4_EXTI_PIN        		  GPIO_Pin_7
//GPIOB_12~15
#define FRE5_8_EXTI_PORT 					  GPIOB
#define FRE5_EXTI_PIN        		  GPIO_Pin_12
#define FRE6_EXTI_PIN        		  GPIO_Pin_13
#define FRE7_EXTI_PIN        		  GPIO_Pin_14
#define FRE8_EXTI_PIN        		  GPIO_Pin_15

//EXTI_Line
#define Fre1_INT_EXTI_Line        EXTI_Line4
#define Fre2_INT_EXTI_Line        EXTI_Line5
#define Fre3_INT_EXTI_Line        EXTI_Line6
#define Fre4_INT_EXTI_Line        EXTI_Line7

#define Fre5_INT_EXTI_Line        EXTI_Line12
#define Fre6_INT_EXTI_Line        EXTI_Line13
#define Fre7_INT_EXTI_Line        EXTI_Line14
#define Fre8_INT_EXTI_Line        EXTI_Line15

//中断源们
#define FRE1_EXTI_IRQn 				EXTI4_IRQn
#define FRE2_4_EXTI_IRQn		  EXTI9_5_IRQn
#define FRE5_8_EXTI_IRQn		  EXTI15_10_IRQn
//中断输入GPIO时钟
#define FRE_GPIO_CLK     RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB



//配置NVIC
static void NVIC_Configer(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	//优先级组在USART初始化时设置过了
	//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	//配置抢占优先级2
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	//使能中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	
	//配置中断源1
	NVIC_InitStructure.NVIC_IRQChannel = FRE1_EXTI_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	//配置中断源2
	NVIC_InitStructure.NVIC_IRQChannel = FRE2_4_EXTI_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructure);
	//配置中断源3
	NVIC_InitStructure.NVIC_IRQChannel = FRE5_8_EXTI_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
	NVIC_Init(&NVIC_InitStructure);
}

static void Fre_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	//开启按键端口时钟
	RCC_APB2PeriphClockCmd(FRE_GPIO_CLK,ENABLE);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//下拉输入
	
	//配置Fre1~4
	GPIO_InitStructure.GPIO_Pin = FRE1_EXTI_PIN | FRE2_EXTI_PIN | FRE3_EXTI_PIN | FRE4_EXTI_PIN;
	GPIO_Init(FRE1_4_EXTI_PORT,&GPIO_InitStructure);
	//配置Fre5~8
	GPIO_InitStructure.GPIO_Pin = FRE5_EXTI_PIN | FRE6_EXTI_PIN | FRE7_EXTI_PIN | FRE8_EXTI_PIN;
	GPIO_Init(FRE5_8_EXTI_PORT,&GPIO_InitStructure);
	
	//配置EXTI信号源
	GPIO_EXTILineConfig(Fre1_EXTI_PortSource,Fre1_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre2_EXTI_PortSource,Fre2_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre3_EXTI_PortSource,Fre3_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre4_EXTI_PortSource,Fre4_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre5_EXTI_PortSource,Fre5_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre6_EXTI_PortSource,Fre6_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre7_EXTI_PortSource,Fre7_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre8_EXTI_PortSource,Fre8_EXTI_PinSource);
}

//初始化EXTI
void Fre_EXTI_Init(void)
{
	EXTI_InitTypeDef EXTI_InitStructure;
	//配置NVIC
	NVIC_Configer();
	//配置GPIO
	Fre_GPIO_Init();
	//开AFIO时钟
	RCC_APB2PeriphClockCmd(EXTI_AFIO_CLK, ENABLE);
	//中断模式
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	//上升沿中断
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	//使能中断
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	//选择EXTI信号源
	EXTI_InitStructure.EXTI_Line = Fre1_INT_EXTI_Line;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = Fre2_INT_EXTI_Line;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = Fre3_INT_EXTI_Line;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = Fre4_INT_EXTI_Line;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = Fre5_INT_EXTI_Line;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = Fre6_INT_EXTI_Line;
	EXTI_Init(&EXTI_InitStructure);
    EXTI_InitStructure.EXTI_Line = Fre7_INT_EXTI_Line;
	EXTI_Init(&EXTI_InitStructure);
	EXTI_InitStructure.EXTI_Line = Fre8_INT_EXTI_Line;
	EXTI_Init(&EXTI_InitStructure);
	
}

发生的错误是PA4 PA5 PA6 PA7可以检测到上升沿并进入中断,但是PB12~PB15却死活进入不了中断,进入调试模式时发现PB13 PB14会无故检测到上升沿。
睡了一觉之后发现了问题的原因:
我在函数 Fre_GPIO_Init() 中调用了 GPIO_EXTILineConfig()

void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
  uint32_t tmp = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
  assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
  
  tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));
  //这里包含了对AFIO_EXTICR的操作,但是我在这之前并没有使能AFIO,所以会出现异常
  
  AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;
  AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
}

数据手册上说了
在这里插入图片描述

所以正确的写法应该是

static void Fre_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	//开启按键端口时钟
	RCC_APB2PeriphClockCmd(FRE_GPIO_CLK,ENABLE);
	//开AFIO时钟
	RCC_APB2PeriphClockCmd(EXTI_AFIO_CLK, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//下拉输入
	
	//配置Fre1~4
	GPIO_InitStructure.GPIO_Pin = FRE1_EXTI_PIN | FRE2_EXTI_PIN | FRE3_EXTI_PIN | FRE4_EXTI_PIN;
	GPIO_Init(FRE1_4_EXTI_PORT,&GPIO_InitStructure);
	//配置Fre5~8
	GPIO_InitStructure.GPIO_Pin = FRE5_EXTI_PIN | FRE6_EXTI_PIN | FRE7_EXTI_PIN | FRE8_EXTI_PIN;
	GPIO_Init(FRE5_8_EXTI_PORT,&GPIO_InitStructure);
	
	//配置EXTI信号源
	GPIO_EXTILineConfig(Fre1_EXTI_PortSource,Fre1_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre2_EXTI_PortSource,Fre2_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre3_EXTI_PortSource,Fre3_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre4_EXTI_PortSource,Fre4_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre5_EXTI_PortSource,Fre5_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre6_EXTI_PortSource,Fre6_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre7_EXTI_PortSource,Fre7_EXTI_PinSource);
	GPIO_EXTILineConfig(Fre8_EXTI_PortSource,Fre8_EXTI_PinSource);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值