【STM库应用】stm32 之 中断按键初始化(注意事项)

之前做终端按键的时候都是只做了一个,没有做多个,昨天在把所有按键都设置成中断模式的时候遇到问题,于是乎还跟一个网上的哥们进行了热议,后来还是我发现了问题!最终把问题给解决了!

【STM库应用】stm32 之 中断按键初始化(注意事项)_第1张图片

我的按键的GPIO连接有点奇葩,他不是连续的,这可能就是竞赛板故意设置的难度吧!

首先管脚初始化:

GPIO_InitTypeDef key;
	
	RCC->APB2ENR |= ((1<<0)|(1<<2)|(1<<3));
	
	key.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;       
  key.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOA, &key);
	
	key.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
  key.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOB, &key);

全部设置成输入模式,AFIO再时钟使能的时候不要忘记了!这里我就不多说了!

然后就是中断组设置: NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

NVIC初始化:

	key_nvic.NVIC_IRQChannel = EXTI0_IRQn;
	key_nvic.NVIC_IRQChannelCmd = ENABLE;
	key_nvic.NVIC_IRQChannelPreemptionPriority = 0;
	key_nvic.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&key_nvic);

重点都不在这,值得注意的是下面:

我第一次在配置EXTI Line的时候这样配置!

GPIO_EXTILineConfig(GPIO_PortSourceGPIOA|GPIO_PortSourceGPIOB,\

GPIO_PinSource0|GPIO_PinSource1|GPIO_PinSource2|GPIO_PinSource8);

大致一看,貌似很正常啊!但是问题就出在这!

我们跳转到GPIO_PinSourcex和GPIO_PortSourceGPIOx哪里看看:

#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)

#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)
我们来计算下:

GPIO_PortSourceGPIOA  |   GPIO_PortSourceGPIOB = 0x00 | 0x01 = 0x01 = GPIO_PortSourceGPIOB

GPIO_PinSource0 | GPIO_PinSource1  | GPIO_PinSource2 | GPIO_PinSource8 = 0x00 | 0x01 | 0x02 | 0x08 = 0x0b = GPIO_PinSource11

所以我最后初始化后的中断就成为:         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource11);
最终让我事与愿违了。发现这个问题后,我仔细研究了一下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[GPIO_PinSource >> 0x02] &= ~tmp;
  AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
}

明白了,没有什么好纠结的了!

最后,我就感叹,他这个中断函数写的一点都不灵活!我还是喜欢我写的这个,详情看前面中断按键!

void init_interrupt(u8 group,u8 inter_id,u8 preempting,u8 subpriority)
{
	u32 aircr;
	u8  ip;
	
		/* Set Group :2 */
	aircr = SCB->AIRCR;		//Get AIRCR register
	aircr &= 0x0000f8ff;	//Clear Password & PriGroup
	aircr |= 0x05fa0000;	//Set Password
	aircr |= ((~group&0x7)<<8);		//Set PriGroup Group:2 0000 0010 => 1111 1101 [5 = 0101b]<<8
	SCB->AIRCR = aircr;		//Set AIRCR
		
		/* 
		 * Group 2  2:2
		 * 0~3 : 0~3
		 * Set Preempting = 0  Subpriority = 0
		 * 1001 0000b = 0x00;
		 */
	if(inter_id<32)
		NVIC->ISER[0] = 1<< inter_id;
	else
		NVIC->ISER[1] = 1<<(inter_id-32);	//EXIT15_10 vector:37
	switch(group)
	{
		case 0: ip = 0x0f&subpriority;break;
		case 1: ip = (0x08&preempting) | (0x07&subpriority);break;
		case 2: ip = (0x0C&preempting) | (0x03&subpriority);break;
		case 3: ip = (0x0e&preempting) | (0x01&subpriority);break;
		case 4: ip = 0x0f&preempting;break;
		default: ip = 0x00;break;
	}
	NVIC->IP[inter_id] = 0xf0&(ip<<4);
}
不要看我的一些注释,那些注释是给我自己看的!没有什么参考价值!

这个问题搞清楚了,就没有什么容易出错的了,下面是代码:

void ITkey_init(void)
{
	EXTI_InitTypeDef key_exti;
	NVIC_InitTypeDef key_nvic;
	GPIO_InitTypeDef key;
	
	RCC->APB2ENR |= ((1<<0)|(1<<2)|(1<<3));
	
	key.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;       
  key.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOA, &key);
	
	key.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
  key.GPIO_Mode = GPIO_Mode_IPD;
  GPIO_Init(GPIOB, &key);
	

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

	key_nvic.NVIC_IRQChannel = EXTI0_IRQn;
	key_nvic.NVIC_IRQChannelCmd = ENABLE;
	key_nvic.NVIC_IRQChannelPreemptionPriority = 0;
	key_nvic.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&key_nvic);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
	key_exti.EXTI_Line = EXTI_Line0;
	key_exti.EXTI_LineCmd = ENABLE;
	key_exti.EXTI_Mode = EXTI_Mode_Interrupt;
	key_exti.EXTI_Trigger = EXTI_Trigger_Rising;
	EXTI_Init(&key_exti);
	
	
	key_nvic.NVIC_IRQChannel = EXTI9_5_IRQn;
	NVIC_Init(&key_nvic);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource8);
	key_exti.EXTI_Line = EXTI_Line8;
	EXTI_Init(&key_exti);

	key_nvic.NVIC_IRQChannel = EXTI1_IRQn;
	NVIC_Init(&key_nvic);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);
	key_exti.EXTI_Line = EXTI_Line1;
	EXTI_Init(&key_exti);
	
	key_nvic.NVIC_IRQChannel = EXTI2_IRQn;
	NVIC_Init(&key_nvic);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource2);
	key_exti.EXTI_Line = EXTI_Line2;
	EXTI_Init(&key_exti);

}







你可能感兴趣的:(stm32)