STM32外部中斷操作
NVIC
NVICNestedVectoredInterruptController嵌套向量中斷控制。在STM32的標(biāo)準(zhǔn)外設(shè)庫(kù)和MDK定義的中斷相關(guān)的變量和結(jié)構(gòu)體類型,大多都是以NVIC開頭的,例如NVIC_InitTypeDef。
NVIC_Type
NVIC寄存器結(jié)構(gòu)體。在MDK380a中,這個(gè)結(jié)構(gòu)體是定義在stm32f10x_map.h中,具體的定義如下
typedefstruct
{
vu32ISER[2];
u32RESERVED0[30];
vu32ICER[2];
u32RSERVED1[30];
vu32ISPR[2];
u32RESERVED2[30];
vu32ICPR[2];
u32RESERVED3[30];
vu32IABR[2];
u32RESERVED4[62];
vu32IPR[15];
}NVIC_TypeDef;
ISERInterruptSet-EnableRegister中斷使能寄存器組,兩個(gè)字,共63位,用了60位,一個(gè)位對(duì)應(yīng)一個(gè)中斷,寫1中斷有效,寫0無(wú)意義。
ICERInterruptClear-EnableRegister中斷除能寄存器組,也是兩個(gè)字,和上面的使能寄存器組功能剛好相反,寫1中斷失效,寫0無(wú)意義。
ISPRInterruptSet-PendingRegister中斷掛起控制寄存器組。用了60個(gè)位,對(duì)應(yīng)60個(gè)中斷。寫1有效,可以將正在運(yùn)行的中斷掛起,從而執(zhí)行同級(jí)別或者更高級(jí)別的中斷。寫0無(wú)意義。
ICPRInterruptClear-PendingRegister中斷解掛寄存器組。和上面的掛起寄存組功能剛好相反。寫1有效,寫0無(wú)意義。
IABRInterruptActiveBitRegister中斷激活標(biāo)志位寄存器組。這是一個(gè)只讀寄存器,通過(guò)讀這個(gè)寄存器,可以知道那個(gè)中斷正在被執(zhí)行,對(duì)應(yīng)的位會(huì)被置1。中斷執(zhí)行完后對(duì)應(yīng)位清零。
IPRInterruptPriorityRegister中斷優(yōu)先級(jí)寄存器15個(gè)字,共60個(gè)字節(jié),每個(gè)字節(jié)對(duì)應(yīng)一個(gè)中斷,每個(gè)字節(jié)只用到了高四位,剩余四位保留。這有效4位,又分為搶占優(yōu)先級(jí)和子優(yōu)先級(jí)。搶占優(yōu)先級(jí)在前,子優(yōu)先級(jí)在后。而這兩個(gè)優(yōu)先級(jí)各占幾個(gè)位又要根據(jù)SCB->AIRCR中中斷分組的設(shè)置來(lái)決定。
SCB->AIRCR
STM32的中斷分組:STM32將中斷分為5個(gè)組,組0~4。該分組的設(shè)置是由SCB->AIRCR寄存器的bit10~8來(lái)定義的。具體的分配關(guān)系如下表所示:組 | AIRCR[10:8] | bit[7:4]分配情況 | 分配結(jié)果 |
0 | 111 | 0:4 | 0位搶占優(yōu)先級(jí),4位響應(yīng)優(yōu)先級(jí) |
1 | 110 | 1:3 | 1位搶占優(yōu)先級(jí),3位響應(yīng)優(yōu)先級(jí) |
2 | 101 | 2:2 | 2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí) |
3 | 100 | 3:1 | 3位搶占優(yōu)先級(jí),1位響應(yīng)優(yōu)先級(jí) |
4 | 011 | 4:0 | 4位搶占優(yōu)先級(jí),0位響應(yīng)優(yōu)先級(jí) |
通過(guò)這個(gè)表,我們就可以清楚的看到組0~4對(duì)應(yīng)的配置關(guān)系,例如組設(shè)置為3,那么此時(shí)所有的60個(gè)中斷,每個(gè)中斷的中斷優(yōu)先寄存器的高四位中的最高3位是搶占優(yōu)先級(jí),低1位是響應(yīng)優(yōu)先級(jí)。每個(gè)中斷,你可以設(shè)置搶占優(yōu)先級(jí)為0~7,響應(yīng)優(yōu)先級(jí)為1或0。搶占優(yōu)先級(jí)的級(jí)別高于響應(yīng)優(yōu)先級(jí)。而數(shù)值越小所代表的優(yōu)先級(jí)就越高。
這里需要注意2點(diǎn):
1,如果兩個(gè)中斷的搶占優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí)都是一樣的話,則看哪個(gè)中斷先發(fā)生就先執(zhí)行。
2,高優(yōu)先級(jí)的搶占優(yōu)先級(jí)是可以打斷正在進(jìn)行的低搶占優(yōu)先級(jí)中斷的。而搶占優(yōu)先級(jí)相同的中斷,高優(yōu)先級(jí)的響應(yīng)優(yōu)先級(jí)不可以打斷低響應(yīng)優(yōu)先級(jí)的中斷。
而在老版本的STM32標(biāo)準(zhǔn)外設(shè)庫(kù)中也是有這樣一個(gè)stm32f10x_map.h文件的。定義和上面的差不多,不同地方可能就是長(zhǎng)度不同。
我現(xiàn)在手里拿的是最新的STM32標(biāo)準(zhǔn)外設(shè)庫(kù)(3.5版),里面已經(jīng)沒(méi)有了stm32f10x_map.h這個(gè)文件了,要知道stm32f10x_map.h這個(gè)文件中定義了所有外設(shè)寄存器的結(jié)構(gòu)和內(nèi)存映射,像各個(gè)寄存器的結(jié)構(gòu)體,基址,地址等等。
在新版的STM32的標(biāo)準(zhǔn)外設(shè)庫(kù)中,將這些文件分開定義了,去掉了stm32f10x_map.h這個(gè)頭文件后,新加入了stm32f10x.h和core_cm3.h兩個(gè)頭文件。
在core_cm3.h中,定義了:
1.NVIC_Type,
2.SCB_Type,
3.ITM_Type,
4.InterruptType_Type,
5.MPU_Type,
6.CoreDebug_Type。
在stm32f10x.h,定義了
7.ADC_TypeDef,
8.BKP_TypeDef,
9.CAN_TxMailBox_TypeDef,
10.CAN_FIFOMailBox_TypeDef,
11.CAN_FilterRegister_TypeDef,
12.CAN_TypeDef,
13.CEC_TypeDef,
14.CRC_TypeDef,
15.DAC_TypeDef,
16.DBGMCU_TypeDef,
17.DMA_Channel_TypeDef,
18.DMA_TypeDef,
19.ETH_TypeDef,
20.EXTI_TypeDef,
21.FLASH_TypeDef,
22.OB_TypeDef,
23.FSMC_Bank1_TypeDef,
24.FSMC_Bank1E_TypeDef,
25.FSMC_Bank2_TypeDef,
26.FSMC_Bank3_TypeDef,
27.FSMC_Bank4_TypeDef,
28.GPIO_TypeDef,
29.AFIO_TypeDef,
30.I2C_TypeDef,
31.IWDG_TypeDef,
32.PWR_TypeDef,
33.RCC_TypeDef,
34.RTC_TypeDef,
35.SDIO_TypeDef,
36.SPI_TypeDef,
37.TIM_TypeDef,
38.USART_TypeDef,
39.WWDG_TypeDef
而在stm32f10x_map.h中定義了34個(gè)類型,和stm32f10x.h基本相似。
EXTI_TypeDef
外部中斷的設(shè)置,還需要配置相關(guān)寄存器才可以。下面就介紹外部中斷的配置和使用。
STM32的EXTI控制器支持19個(gè)外部中斷/事件請(qǐng)求。每個(gè)中斷設(shè)有狀態(tài)位,每個(gè)中斷/事件都有獨(dú)立的觸發(fā)和屏蔽設(shè)置。STM32的19個(gè)外部中斷為:
線0~15:對(duì)應(yīng)外部IO口的輸入中斷。
線16:連接到PVD輸出。
線17:連接到RTC鬧鐘事件。
線18:連接到USB喚醒事件。
對(duì)于外部中斷EXTI控制MDK定義了如下結(jié)構(gòu)體:
typedefstruct
{
vu32IMR;
vu32EMR;
vu32RTSR;
vu32FTSR;
vu32SWIER;
vu32PR;
}EXTI_TypeDef;
在新的標(biāo)準(zhǔn)外設(shè)庫(kù)中,這個(gè)結(jié)構(gòu)體的定義位于10x.h中。
IMR:中斷屏蔽寄存器。這是一個(gè)32寄存器。但是只有前19位有效。當(dāng)位x設(shè)置為1時(shí),則開啟這個(gè)線上的中斷,否則關(guān)閉該線上的中斷。
EMR:事件屏蔽寄存器,同IMR,只是該寄存器是針對(duì)事件的屏蔽和開啟。
RTSR:上升沿觸發(fā)選擇寄存器。該寄存器同IMR,也是一個(gè)32為的寄存器,只有前19位有效。位x對(duì)應(yīng)線x上的上升沿觸發(fā),如果設(shè)置為1,則是允許上升沿觸發(fā)中斷/事件。否則,不允許。
FTSR:下降沿觸發(fā)選擇寄存器。同PTSR,不過(guò)這個(gè)寄存器是設(shè)置下降沿的。下降沿和上升沿可以被同時(shí)設(shè)置,這樣就變成了任意電平觸發(fā)了。
SWIER:軟件中斷事件寄存器。通過(guò)向該寄存器的位x寫入1,在未設(shè)置IMR和EMR的時(shí)候,將設(shè)置PR中相應(yīng)位掛起。如果設(shè)置了IMR和EMR時(shí)將產(chǎn)生一次中斷。被設(shè)置的SWIER位,將會(huì)在PR中的對(duì)應(yīng)位清除后清除。
PR:掛起寄存器。當(dāng)外部中斷線上發(fā)生了選擇的邊沿事件,該寄存器的對(duì)應(yīng)位會(huì)被置為1。0,表示對(duì)應(yīng)線上沒(méi)有發(fā)生觸發(fā)請(qǐng)求。通過(guò)向該寄存器的對(duì)應(yīng)位寫入1可以清除該位。在中斷服務(wù)函數(shù)里面經(jīng)常會(huì)要向該寄存器的對(duì)應(yīng)位寫1來(lái)清除中斷請(qǐng)求。
IO復(fù)用里的外部中斷配置寄存器EXTICR
EXTICR在AFIO的結(jié)構(gòu)體中定義,如下:
typedefstruct
{
vu32EVCR;
vu32MAPR;
vu32EXTICR[4];
}AFIO_TypeDef;
在新的標(biāo)準(zhǔn)外設(shè)庫(kù)中,這個(gè)結(jié)構(gòu)體的定義位于10x.h中。
這個(gè)結(jié)構(gòu)體存在的原因是STM32的每個(gè)IO都可以配置成中斷輸入口。但是線0~15:對(duì)應(yīng)外部IO口的輸入中斷。只有16個(gè)。資源就不足了。為了確定是那一組IO的哪個(gè)口配置成中斷,用到了EXTICR[4]。這雖然是一個(gè)32位的數(shù)組,但是只用到了16位,四位分成1組,這樣就有了16組,從低到高,對(duì)應(yīng)16個(gè)IO口,每組的四位數(shù)從0-6組成7種狀態(tài),對(duì)應(yīng)A—G。
例如,我要設(shè)置PA3口為外部中斷輸入,EXTICR就要這樣設(shè)置:首先PA3對(duì)應(yīng)的是EXTICR[0],它管口0-3,口3對(duì)應(yīng)的是EXTICR[0]的15-12位;要設(shè)置成PA,對(duì)應(yīng)的就是xxxxxxxx(高16保留)00xxxxxx(xx表示4bit).
具體步驟是:
1.中斷分組,確定系統(tǒng)要使用什么樣的中斷系統(tǒng),為后面的整個(gè)設(shè)置定下基調(diào)。落實(shí)到寄存器就設(shè)置SCB-AIRCR.
2.設(shè)置中斷優(yōu)先級(jí)。分完組定下基調(diào)就是該設(shè)置優(yōu)先級(jí)了。落實(shí)到寄存器級(jí)別就是設(shè)置vu32IPR[15]這個(gè)數(shù)組了。上面提到了,8bit表示一個(gè)中斷設(shè)置,但是只用到了4個(gè)bit,而且從低到高是對(duì)應(yīng)中斷的從低到高。此時(shí)你要開啟的中斷Channel也基本就確定了。設(shè)置完成后就確定這個(gè)中斷的搶占優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí)。
3.開啟對(duì)應(yīng)的中斷。落實(shí)到寄存器就是ISER[2]。60bit從低到高依次排開。至此,嵌套向量中斷控制基本設(shè)置完成。但是中斷還是不能用。因?yàn)檫€沒(méi)有設(shè)置外部中斷。
4.設(shè)置外部中斷。STM32支持19個(gè)外部中斷。外部中斷占據(jù)整個(gè)中斷系統(tǒng)的低19個(gè)位。落實(shí)到寄存器就是設(shè)置EXTI_TypeDef結(jié)構(gòu)體中的IMR(負(fù)責(zé)開啟事件中斷),EMR(負(fù)責(zé)屏蔽時(shí)間中斷)RTSR和FTSR(負(fù)責(zé)中斷方式)。這樣設(shè)置完后外部中斷還是不能用。因?yàn)檫€沒(méi)有映射到具體IO口。
5.映射到具體IO口。STM32的設(shè)計(jì)是每一個(gè)IO口都可以充當(dāng)中斷引腳,這一點(diǎn)和51內(nèi)核的單片機(jī)有很大的區(qū)別。16個(gè)外部中斷對(duì)應(yīng)每個(gè)端口的16個(gè)IO,但是端口可能是A-G,如何確定映射到哪個(gè)IO就成了問(wèn)題。CM3的解決方法是AFIO_TypeDef結(jié)構(gòu)體中的EXTICR[4]數(shù)組來(lái)確定。具體思路就是用這個(gè)數(shù)組4個(gè)元素的低16位,每四位對(duì)應(yīng)一個(gè)IO,從低到高一一對(duì)應(yīng),四位同時(shí)變換出7種狀態(tài)對(duì)應(yīng)端口的A-G。這樣IO就確定下來(lái)了。
更為嚴(yán)謹(jǐn)步驟是設(shè)置完成最后開啟中斷。剩下的工作就是編寫中斷服務(wù)函數(shù)了。
設(shè)置完這四個(gè)結(jié)構(gòu)體,外部中斷就可以用了。
評(píng)論