斷斷續(xù)續(xù)學(xué)習(xí)STM32一學(xué)期了,時(shí)間過的好快,現(xiàn)在對(duì)STM32F103系列單片機(jī)的中斷嵌套及外部中斷做一個(gè)總結(jié),全當(dāng)學(xué)習(xí)筆記。廢話不多說,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ì)0組和1組的情況做一個(gè)分析。 0組對(duì)應(yīng)是0位搶占優(yōu)先級(jí),4位響應(yīng)優(yōu)先級(jí),那么無搶占優(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í),無響應(yīng)優(yōu)先級(jí)。 所以可以看出判斷兩個(gè)中斷的優(yōu)先級(jí)時(shí)先看搶占優(yōu)先級(jí)的高低,如果相同再看響應(yīng)優(yōu)先級(jí)的高低。如果全都相同最后看中斷通道向量地址。 一般來說在使用過程中,一個(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我自己都沒用過,主要對(duì)線0到15的I/O輸入中斷做一個(gè)總結(jié),有個(gè)注意的地方是這0到15線的外部中斷,其中0到4線,這5個(gè)外部中斷都有自己單獨(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è)表格表示:
這里有一個(gè)問題,如果要配置GPIOA.0和GPIOB.0,會(huì)引起沖突,不知道是不是分時(shí)配置解決的。我用的固體庫的方式,不需要考慮這些,呵呵。注意使用固件庫時(shí)中斷復(fù)位函數(shù)是寫在stm32f10x_it.c這個(gè)文件里的。 下面結(jié)合外部中斷附上固件庫版本的程序: 主函數(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à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à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); } } |
|