專(zhuān)注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> STM32 >> 瀏覽文章

STM32中斷嵌套及外部中斷全程攻略

作者:huqin   來(lái)源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年03月31日   【字體:

斷斷續(xù)續(xù)學(xué)習(xí)STM32一學(xué)期了,時(shí)間過(guò)的好快,現(xiàn)在對(duì)STM32F103系列單片機(jī)的中斷嵌套及外部中斷做一個(gè)總結(jié),全當(dāng)學(xué)習(xí)筆記。廢話不多說(shuō),ARM公司的Cortex-m3 內(nèi)核,支持256個(gè)中斷,其中包含16個(gè)內(nèi)核中斷和240個(gè)外部中斷,并且具有256級(jí)的可編程中斷設(shè)置。在ST公司的STM32單片機(jī)中最多有84個(gè)中斷,包括16個(gè)內(nèi)核中斷(這16個(gè)內(nèi)部中斷是任何半導(dǎo)體商也改不了的),和68個(gè)可屏蔽中斷,具有16級(jí)可編程的中斷優(yōu)先級(jí)。但是在STM32F103系列中只有60個(gè)可屏蔽中斷,(107系列有68個(gè))。

針對(duì)這60個(gè)可屏蔽中斷,重點(diǎn)掌握它的一個(gè)中斷優(yōu)先級(jí)寄存器組IPR,全稱(chēng)Interrupt Priority Registers。這個(gè)寄存器組包含15個(gè)32位的寄存器,一個(gè)可屏蔽中斷占用8bit,那么一個(gè)寄存器可以控制4個(gè)可屏蔽中斷,一共15*4=60。然而在這占用的8bit中又只使用了高4bit,這高4bit的分配才是STM32F103系列單片機(jī)中斷嵌套的設(shè)置所在。STM32F103系列的中斷嵌套分為5個(gè)組,分別是0、1、2、3、4  這5個(gè)組,下面是5個(gè)組與中斷嵌套的對(duì)應(yīng)關(guān)系。

分配結(jié)果
0
0位搶占優(yōu)先級(jí),4位響應(yīng)優(yōu)先級(jí)
1
1位搶占優(yōu)先級(jí),3位響應(yīng)優(yōu)先級(jí)
2
2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí)
3
3位搶占優(yōu)先級(jí),1位響應(yīng)優(yōu)先級(jí)
4
4位搶占優(yōu)先級(jí),0位響應(yīng)優(yōu)先級(jí)

 
對(duì)于搶占優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí),只需記住兩點(diǎn),第一、搶占任何優(yōu)先級(jí)比都比所有響應(yīng)優(yōu)先級(jí)優(yōu)先級(jí)高。只有搶占優(yōu)先級(jí)更高的具有中斷嵌套功能。(即打斷其他正在執(zhí)行的中斷)。第二、數(shù)字越小優(yōu)先級(jí)越高 ,搶占優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí)都一樣時(shí),首先響應(yīng)中斷通道對(duì)應(yīng)中斷向量地址低的那個(gè)中斷。

下面對(duì)0組和1組的情況做一個(gè)分析。
0組對(duì)應(yīng)是0位搶占優(yōu)先級(jí),4位響應(yīng)優(yōu)先級(jí),那么無(wú)搶占優(yōu)先級(jí),響應(yīng)優(yōu)先級(jí)可設(shè)置為0到15級(jí)(2的4次方種)中的任意一種。
1組對(duì)應(yīng)是1位搶占優(yōu)先級(jí),3位響應(yīng)優(yōu)先級(jí),那么搶占優(yōu)先級(jí)只可設(shè)置為0級(jí)或者1級(jí)中的任意一種(2的1次方種),響應(yīng)優(yōu)先級(jí)可設(shè)置為0到7級(jí)(2的3次方種)中的任意一種。
上電復(fù)位時(shí),中斷配置為4組,并且60個(gè)外部中斷都是搶占優(yōu)先級(jí)為0級(jí),無(wú)響應(yīng)優(yōu)先級(jí)。

所以可以看出判斷兩個(gè)中斷的優(yōu)先級(jí)時(shí)先看搶占優(yōu)先級(jí)的高低,如果相同再看響應(yīng)優(yōu)先級(jí)的高低。如果全都相同最后看中斷通道向量地址。
一般來(lái)說(shuō)在使用過(guò)程中,一個(gè)系統(tǒng)使用一個(gè)組別就完全可以滿足需要。所以在使用一個(gè)組別后一般不要在系統(tǒng)中再改動(dòng)組別,骨灰級(jí)玩家可以去試試(小心芯片燒了)。

外部中斷:
STM32F103的外部中斷EXTI支持19個(gè)外部中斷/事件請(qǐng)求。每個(gè)中斷/事件都有獨(dú)立的觸發(fā)和屏蔽設(shè)置。
0到15線:對(duì)應(yīng)外部I/O口輸入中斷
線16:接到PVD輸出
線17:接到RCT鬧鐘事件
線18:接到USB喚醒事件
線16到線18我自己都沒(méi)用過(guò),主要對(duì)線0到15的I/O輸入中斷做一個(gè)總結(jié),有個(gè)注意的地方是這0到15線的外部中斷,其中0到4線,這5個(gè)外部中斷都有自己?jiǎn)为?dú)的中斷響應(yīng)函數(shù)。5到9線公用一個(gè)中斷服務(wù)函數(shù),10到15線公用一個(gè)中斷服務(wù)函數(shù)。
外部中斷配置寄存器組EXTICR包含4個(gè)32位的寄存器,分別是EXTICR0、EXTICR1、EXTICR2、EXTICR3、但每一個(gè)寄存器只用了低16位,每4位控制一個(gè)I/O口,一個(gè)寄存器控制4個(gè)I/O口,EXTICR寄存器組控制16個(gè)I/O口,剛好一個(gè)GPIO的I/O口數(shù)。下面以 EXTICR0為例,用一個(gè)表格表示:


I/O口3
I/O口2
I/O口1
I/O口0
0000    GPIOA
0000    GPIOA
0000    GPIOA
0000    GPIOA
0001    GPIOB
0001    GPIOB
0001    GPIOB
0001    GPIOB
0010    GPIOC
0010    GPIOC
0010    GPIOC
0010    GPIOC
0011    GPIOD
0011    GPIOD
0011    GPIOD
0011    GPIOD
0100    GPIOE
0100    GPIOE
0100    GPIOE
0100    GPIOE
0101    GPIOF
0101    GPIOF
0101    GPIOF
0101    GPIOF
0110    GPIOG
0110    GPIOG
0110    GPIOG
0110    GPIOG


 
比如配置GPIOA.0就是將EXTICR0的低4位配置成0000,若配置GPIOB.1就是配置EXTICR0的4到7位,為0001。
這里有一個(gè)問(wèn)題,如果要配置GPIOA.0和GPIOB.0,會(huì)引起沖突,不知道是不是分時(shí)配置解決的。我用的固體庫(kù)的方式,不需要考慮這些,呵呵。注意使用固件庫(kù)時(shí)中斷復(fù)位函數(shù)是寫(xiě)在stm32f10x_it.c這個(gè)文件里的。


下面結(jié)合外部中斷附上固件庫(kù)版本的程序:

主函數(shù)里:

void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitSructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);          //設(shè)置為優(yōu)先級(jí)組2

NVIC_InitSructure.NVIC_IRQChannel = EXTI15_10_IRQn;       //定義外部中斷線13中斷通道
NVIC_InitSructure.NVIC_IRQChannelPreemptionPriority = 0;        //搶占優(yōu)先級(jí)0
NVIC_InitSructure.NVIC_IRQChannelSubPriority = 0;                       //響應(yīng)優(yōu)先級(jí)0
NVIC_InitSructure.NVIC_IRQChannelCmd = ENABLE;                               //使能指定通道
NVIC_Init(&NVIC_InitSructure);                                                                     

NVIC_InitSructure.NVIC_IRQChannel = EXTI15_10_IRQn;        //定義外部中斷線15中斷通道
NVIC_InitSructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitSructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitSructure.NVIC_IRQChannelCmd = ENABLE;                               //使能指定通道
NVIC_Init(&NVIC_InitSructure);

NVIC_InitSructure.NVIC_IRQChannel = EXTI0_IRQn;        //定義外部中斷線0中斷通道
NVIC_InitSructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitSructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitSructure.NVIC_IRQChannelCmd = ENABLE;                               //使能指定通道
NVIC_Init(&NVIC_InitSructure);


}

void EXTI_Configuration(void)
{      
  EXTI_InitTypeDef EXTI_InitStructure;                                                    //初始化結(jié)構(gòu)

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource13);  //指明當(dāng)前哪個(gè)引腳為外部中斷觸發(fā)引腳
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);

  EXTI_ClearITPendingBit(EXTI_Line13);                                      //清除中斷標(biāo)志位 EXTI_Line13對(duì)應(yīng)相應(yīng)的中斷線13
  EXTI_ClearITPendingBit(EXTI_Line15);

  EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt;                            //選擇中斷模式請(qǐng)求
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;                    //下降沿觸發(fā)
  EXTI_InitStructure.EXTI_Line = EXTI_Line13|EXTI_Line15;  // 選擇待使能的外部中斷線
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                                                        // 定義選中線的新?tīng)顟B(tài)  使能
  EXTI_Init(&EXTI_InitStructure);                     //把EXIT_InitStructure中的每一個(gè)參數(shù)按缺省值填入

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);     //指明當(dāng)前哪個(gè)引腳為外部中斷觸發(fā)引腳
  EXTI_ClearITPendingBit(EXTI_Line0);  
  EXTI_InitStructure.EXTI_Mode =EXTI_Mode_Interrupt;                            //選擇中斷模式請(qǐng)求
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;                    //上升沿觸發(fā)
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;            // 選擇待使能的外部中斷線
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                                                        // 定義選中線的新?tīng)顟B(tài)  使能
  EXTI_Init(&EXTI_InitStructure);                     //把EXIT_InitStructure中的每一個(gè)參數(shù)按缺省值填入

}

stm32f10x_it.c這個(gè)文件里
void EXTI15_10_IRQHandler(void)
{
              if(EXTI_GetITStatus(EXTI_Line13)!=RESET)
        {               GPIO_WriteBit( GPIOA,GPIO_Pin_8,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_8))); //LED0翻轉(zhuǎn)
                      EXTI_ClearITPendingBit(EXTI_Line13);
  }
             if(EXTI_GetITStatus(EXTI_Line15)!=RESET)
        {               GPIO_WriteBit( GPIOD,GPIO_Pin_2,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_2))); //LED0翻轉(zhuǎn)
                EXTI_ClearITPendingBit(EXTI_Line15);  

  }

}

void EXTI0_IRQHandler(void)
{
          if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
{ GPIO_WriteBit( GPIOA,GPIO_Pin_8,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_8))); //LED0翻轉(zhuǎn)
    GPIO_WriteBit( GPIOD,GPIO_Pin_2,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_2))); //LED0翻轉(zhuǎn)

  EXTI_ClearITPendingBit(EXTI_Line0);   
}
}
 

關(guān)閉窗口

相關(guān)文章