之前做終端按鍵的時候都是只做了一個,沒有做多個,昨天在把所有按鍵都設置成中斷模式的時候遇到問題,于是乎還跟一個網上的哥們進行了熱議,后來還是我發現了問題!最終把問題給解決了!

我的按鍵的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的第一個程序--LED
- 【菜鳥入門】stm32 之 掃描按鍵
- 【菜鳥入門】stm32 之 中斷按鍵
- 【菜鳥入門】stm32 之 USART
- 【菜鳥入門】stm32 之 iic
- 【菜鳥入門】stm32 之 eeprom
- 【菜鳥入門】stm32 之 pwm
- 【菜鳥入門】stm32 之 ADC 模數轉換
- 【菜鳥入門】stm32 之 實時時鐘
- 【菜鳥入門】stm32 之 DMA
- 【菜鳥入門】stm32 之 DAC
- 【STM庫應用】stm32 之 USART
- 中斷源去抖辦法
- stm32 啟動代碼應用技巧
- 【STM庫應用】stm32 之 IIC應用
- 【STM庫應用】stm32 之 中斷按鍵初始化(注意事項)
- 關于結構體初始化
- 【STM庫應用】stm32 之 TIM (詳解一 通用定時器)
- 【STM庫應用】stm32 之 TIM (詳解二 脈沖寬度、周期測量)
- 【stm32庫應用】SD驅動移植(基于SDIO外設)
- SD卡fat文件系統移植
- stm32 DMA初始化選項研究
- stm32 靈活靜態存儲控制器(FSMC)(NORFLASH\PSRAM)
- 【stm32+uC/OS-II】ucosii移植簡單詳細步驟
- STM32 加入調試信息來調試代碼
- NRF24L01 無線通信模塊使用