啊啊啊,先叫兩聲,釋放釋放今天的壓抑。。搞了一天終于把中斷給搞定。
中斷寄存器怎么說呢,兩個字,復雜,三個字,好復雜,四個字,真的很發展
好吧,開始進入正題。。。
其實中斷也不是很復雜了,歸納下,分為以下幾個步驟:
(1)GPIO config
(2)EXTI config
(3)Set Group of Interrupt vector
(4)Set Preemting & SubPriority
(5)Function of Interrupt
好,先附上代碼,現在我來給大家一步一步解析:
~~~
void inter_sw5_config(void)
{
GPIO_TypeDef *sw5 = GPIOE;
u32 aircr = 0;
RCC->APB2ENR |= 1<<6;
sw5->CRH &= ~(0xf<<(4*6)); //Clear PE14 Register
sw5->CRH |= 8<<(4*6); //Set PE14 Register [TO:pull up / down]
sw5->ODR |= GPIO_Pin_14; //Enable PIN14
/* EXTI CONFIG */
RCC->APB2ENR |= 1<<0; //Start clock of AFIO
AFIO->EXTICR[3] |= 0x04<<8; //Set PE14
//GPIOE 0100b = 0x4
//3 = (int)(14 / 4)
//8 = (14 % 4) * 4
EXTI->IMR |= GPIO_Pin_14; //enable interrupt of PE14
EXTI->EMR |= GPIO_Pin_14; //enable interrupt of PE14
EXTI->RTSR |= GPIO_Pin_14; //Set Rising along the trigger
/* Set Group :2 */
aircr = SCB->AIRCR; //Get AIRCR register
aircr &= 0x0000f8ff; //Clear Password & PriGroup
aircr |= 0x05fa0000; //Set Password
aircr |= (0x5<<8); //Set PriGroup Group:2 [5 = 0101b]<<8
SCB->AIRCR = aircr; //Set AIRCR
/*
* Group 2 2:2
* 0~3 : 0~3
* Set Preempting = 0 Subpriority = 0
* 1001 0000b = 0x00;
*/
NVIC->ISER[1] = 1<<(40-32); //EXIT15_10 vector:40
NVIC->IP[40] = 0x90;
}
~~~
1、GPIO config
前面兩個博客已經進行了解釋,我覺得不用再多說了,說多了浪費時間。
不過我們來解析下APB2ENR寄存器,APB2ENR即外部時鐘寄存器,無論選擇選擇哪個GPIOx或者是特殊功能寄存器,都需要來給他驅動時鐘;

設置對應位為1則打開時鐘,設置對應位為0則關閉
這里我們用的是GPIOE,bit6,所以我們要RCC->APB2ENR |= 1<<6;
后面我們還要用到中斷寄存器,所以我們后面在初始化中斷的時候要RCC->APB2ENR |= 1<<0;
2、EXTI config
在配置EXTI的時候我們要使用特殊功能寄存器AFIO,所以我們先來看下AFIO的結構體(上面關于AFIO的時鐘已經說了,這都不說了)
~~~
typedef struct
{
__IO uint32_t EVCR;
__IO uint32_t MAPR;
__IO uint32_t EXTICR[4];
uint32_t RESERVED0;
__IO uint32_t MAPR2;
} AFIO_TypeDef;
~~~
這里的EXTICR是個長度為4的數組;
這里我舉個例子,我們來研究下EXTICR2寄存器

可以看出EXTICR2管理了4個PIN,即x=4,5,6,7,這里我們用的是PE,所以,在設置的時候設置為0100b=0x4;今天我在搞這個的時候,就是把這個地方的0100b看錯了才讓我糾結了一下午;所以大家在配置寄存器的時候,一定要小心小心再小心;
其實這里就像當于一個坐標,至于為啥,傻子都能看的出來。
由于我們用的是PE14
所以我們要選用EXTICR4【4 = 14/4】寄存器,在結構體中是數組的最后一個,所以我們要配置EXTICR[3]
這樣我們已經選定了PE14,如果還不懂的話,請看datasheet中 8.4 AFIO寄存器的描述
然后我們下面來配置EXTI的寄存,同樣,想看詳細的請看9.3 EXTI寄存器的描述
EXTI->IMR |= GPIO_Pin_14;//enable interrupt of PE14
EXTI->EMR |= GPIO_Pin_14;//enable interrupt of PE14
EXTI->RTSR |= GPIO_Pin_14;//Set Rising along the trigger
從注釋中不難明白,每一句的作用,我沒就來分析其中的一個

bit 31:20是木有用的,主要是19:0,為什么是19呢?看中斷向量表,具體在9.1.2 中斷和異常向量?9.2.5 ?外部中斷/事件線路映像
3、Set Group of Interrupt vector
可能這個AIRCR寄存器不是很好找,我看了好多資料,才找到這個寄存器的map。

看到這里,為來配置中斷寄存器我們只需了解 PRIGROUP,和KEYSTAT,
KEYSTAT上面已經給出了,0x05fa
PRIGROUP看下面的表:

看了這個表,比如我選擇group 2 :那么我們就看劃過紅線的部分,0b101 = 0x5,這樣就不難理解了吧。
4、Set Preemting & SubPriority
在我的設置中,可能有些人會說看不懂,或者說我的錯,可能是咱們的軟件不一樣,我用的是keil 4,庫給我提供的頭文件關于NVIC的結構體如下:
~~~
typedef struct
{
__IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register */
uint32_t RESERVED0[24];
__IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register */
uint32_t RSERVED1[24];
__IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register */
uint32_t RESERVED2[24];
__IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register */
uint32_t RESERVED3[24];
__IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */
uint32_t RESERVED4[56];
__IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */
uint32_t RESERVED5[644];
__O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register */
} NVIC_Type;
~~~

NVIC->ISER[1] = 1<<(40-32);//EXIT15_10 vector:40
NVIC->IP[40] = 0x90;
這里我只說下為什么是ISER[1]和40;
ISER[0]為u32類型,40已經超過32,所以用ISER[1],ISER[1]從32開始來對中斷進行使能。
為什么是40呢,還是看中斷向量表,因為我用的是PE14,EXTI有



看了這個中斷向量表,還有疑問嗎??
5、Function of Interrupt
Function Name 一定要跟中斷向量名一致,這里我舉個例子就算了,不過在函數結束的時候一定要清空中斷向量標志。
~~~
void EXTI15_10_IRQHandler(void)
{
static u8 flag = 0;
if((EXTI->PR & GPIO_Pin_14) != RESET)
{
flag = ~flag;
delay_ms(20);
if(flag)
GPIOE->BRR |= GPIO_Pin_0; //LED ON
else
GPIOE->BSRR |= GPIO_Pin_0;//LED OFF
}
EXTI->PR |= GPIO_Pin_14; //clear flag of interrupt
}
~~~
PR寄存器只要寫入1即可清0.
OK,今天到此結束,明天繼續。請大家多多指點!!
- 前言
- 【菜鳥入門】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 無線通信模塊使用