<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > STM32外部中斷學(xué)習(xí)筆記

          STM32外部中斷學(xué)習(xí)筆記

          作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
          中斷分類

          STM32的EXTI控制器支持19 個外部中斷/ 事件請求。每個中斷設(shè)有狀態(tài)位,每個中斷/ 事件都有獨立的觸發(fā)和屏蔽設(shè)置。
          STM32的19個外部中斷對應(yīng)著19路中斷線,分別是EXTI_Line0-EXTI_Line18:

          本文引用地址:http://www.ex-cimer.com/article/201611/318699.htm

          線0~15:對應(yīng)外部 IO口的輸入中斷。
          線16:連接到 PVD 輸出。
          線17:連接到 RTC 鬧鐘事件。
          線18:連接到 USB 喚醒事件。

          觸發(fā)方式:STM32 的外部中斷是通過邊沿來觸發(fā)的,不支持電平觸發(fā)。

          外部中斷分組:STM32 的每一個GPIO都能配置成一個外部中斷觸發(fā)源,STM32 通過根據(jù)引腳的序號不同將眾多中斷觸發(fā)源分成不同的組,比如:PA0,PB0,PC0,PD0,PE0,PF0,PG0為第一組,那么依此類推,我們能得出一共有16 組,STM32 規(guī)定,每一組中同時只能有一個中斷觸發(fā)源工作,那么,最多工作的也就是16個外部中斷。

          寄存器組

          EXTICR寄存器組,總共有4 個,因為編譯器的寄存器組都是從0 開始編號的,所以EXTICR[0]~ EXTICR[3],對應(yīng)《STM32參考手冊》里的 EXTICR1~ EXTICR 4(查了好久才搞明白這個數(shù)組的含義!?。?。每個 EXTICR只用了其低16 位。

          EXTICR[0] ~EXTICR[3]的分配如下:

          EXTI寄存器的結(jié)構(gòu)體:

          typedef struct { vu32 IMR; vu32 EMR; vu32 RTSR; vu32 FTSR; vu32 SWIER; vu32 PR; } EXTI_TypeDef;
          IMR:中斷屏蔽寄存器

          這是一個 32 寄存器。但是只有前 19 位有效。當(dāng)位 x 設(shè)置為1 時,則開啟這個線上的中斷,否則關(guān)閉該線上的中斷。

          EMR:事件屏蔽寄存器

          同IMR ,只是該寄存器是針對事件的屏蔽和開啟。

          RTSR:上升沿觸發(fā)選擇寄存器

          該寄存器同IMR ,也是一個32為的寄存器,只有前 19位有效。位 x 對應(yīng)線x 上的上升沿觸發(fā),如果設(shè)置為 1 ,則是允許上升沿觸發(fā)中斷/ 事件。否則,不允許。

          FTSR:下降沿觸發(fā)選擇寄存器

          同 PTSR,不過這個寄存器是設(shè)置下降沿的。下降沿和上升沿可以被同時設(shè)置,這樣就變成了任意電平觸發(fā)了。

          SWIER:軟件中斷事件寄存器

          通過向該寄存器的位x 寫入 1 ,在未設(shè)置 IMR 和EMR的時候,將設(shè)置PR中相應(yīng)位掛起。如果設(shè)置了IMR 和EMR時將產(chǎn)生一次中斷。被設(shè)置的SWIER位,將會在PR中的對應(yīng)位清除后清除。

          PR:掛起寄存器

          0 ,表示對應(yīng)線上沒有發(fā)生觸發(fā)請求。

          1,表示外部中斷線上發(fā)生了選擇的邊沿事件。通過向該寄存器的對應(yīng)位寫入 1 可以清除該位。

          在中斷服務(wù)函數(shù)里面經(jīng)常會要向該寄存器的對應(yīng)位寫1 來清除中斷請求。

          Ex_NVIC_Config基本是按照這個結(jié)構(gòu)來編寫的

          中斷配置步驟

          STM32的每個IO口都可以作為中斷輸入,這點很好用。要把IO口作為外部中斷輸入,有以下幾個步驟:

          1)初始化IO口為輸入。

          這一步設(shè)置你要作為外部中斷輸入的IO口的狀態(tài),可以設(shè)置為上拉/下拉輸入,也可以設(shè)置為浮空輸入,但浮空的時候外部一定要帶上拉,或者下拉電阻。否則可能導(dǎo)致中斷不停的觸發(fā)。在干擾較大的地方,就算使用了上拉/下拉,也建議使用外部上拉/下拉電阻,這樣可以一定程度防止外部干擾帶來的影響。

          2)開啟IO口復(fù)用時鐘,設(shè)置IO口與中斷線的映射關(guān)系。

          STM32的IO口與中斷線的對應(yīng)關(guān)系需要配置外部中斷配置寄存器EXTICR,這樣我們要先開啟復(fù)用時鐘,然后配置IO口與中斷線的對應(yīng)關(guān)系。才能把外部中斷與中斷線連接起來。
          3)開啟與該IO口相對的線上中斷/事件,設(shè)置觸發(fā)條件。
          這一步,我們要配置中斷產(chǎn)生的條件,STM32可以配置成上升沿觸發(fā),下降沿觸發(fā),或者任意電平變化觸發(fā),但是不能配置成高電平觸發(fā)和低電平觸發(fā)。這里根據(jù)自己的實際情況來配置。同時要開啟中斷線上的中斷,這里需要注意的是:如果使用外部中斷,并設(shè)置該中斷的EMR位的話,會引起軟件仿真不能跳到中斷,而硬件上是可以的。而不設(shè)置EMR,軟件仿真就可以進入中斷服務(wù)函數(shù),并且硬件上也是可以的。建議不要配置EMR位。
          4)配置中斷分組(NVIC),并使能中斷。
          這一步,我們就是配置中斷的分組,以及使能,對STM32的中斷來說,只有配置了NVIC的設(shè)置,并開啟才能被執(zhí)行,否則是不會執(zhí)行到中斷服務(wù)函數(shù)里面去的。關(guān)于NVIC的詳細(xì)介紹,請參考前面章節(jié)。
          5)編寫中斷服務(wù)函數(shù)。

          這是中斷設(shè)置的最后一步,中斷服務(wù)函數(shù),是必不可少的,如果在代碼里面開啟了中斷,但是沒編寫中斷服務(wù)函數(shù),就可能引起硬件錯誤,從而導(dǎo)致程序崩潰!所以在開啟了某個中斷后,一定要記得為該中斷編寫服務(wù)函數(shù)。在中斷服務(wù)函數(shù)里面編寫你要執(zhí)行的中斷后的操作。

          實驗4--外部中斷實驗exit.c函數(shù)如下:

          [cpp]view plaincopy
          1. #include"exti.h"
          2. #include"led.h"
          3. #include"key.h"
          4. #include"delay.h"
          5. #include"usart.h"
          6. //外部中斷0服務(wù)程序
          7. voidEXTI0_IRQHandler(void)
          8. {
          9. delay_ms(10);//消抖
          10. if(KEY2==1)//按鍵2
          11. {
          12. LED0=!LED0;
          13. LED1=!LED1;
          14. }
          15. EXTI->PR=1<<0;//清除LINE0上的中斷標(biāo)志位
          16. }
          17. //外部中斷15~10服務(wù)程序
          18. voidEXTI15_10_IRQHandler(void)
          19. {
          20. delay_ms(10);//消抖
          21. if(KEY0==0)//按鍵0
          22. {
          23. LED0=!LED0;
          24. }elseif(KEY1==0)//按鍵1
          25. {
          26. LED1=!LED1;
          27. }
          28. EXTI->PR=1<<13;//清除LINE13上的中斷標(biāo)志位
          29. EXTI->PR=1<<15;//清除LINE15上的中斷標(biāo)志位
          30. }
          31. //外部中斷初始化程序
          32. //初始化PA0,PA13,PA15為中斷輸入.
          33. voidEXTIX_Init(void)
          34. {
          35. RCC->APB2ENR=1<<2;//使能PORTA時鐘
          36. JTAG_Set(JTAG_SWD_DISABLE);//關(guān)閉JTAG和SWD
          37. GPIOA->CRL&=0XFFFFFFF0;//PA0設(shè)置成輸入
          38. GPIOA->CRL=0X08;
          39. GPIOA->CRH&=0X0F0FFFFF;//PA13,15設(shè)置成輸入
          40. GPIOA->CRH=0X80800;
          41. GPIOA->ODR=1<<13;//PA13上拉,PA0默認(rèn)下拉
          42. GPIOA->ODR=1<<15;//PA15上拉
          43. Ex_NVIC_Config(GPIO_A,0,RTIR);//上升沿觸發(fā)
          44. Ex_NVIC_Config(GPIO_A,13,FTIR);//下降沿觸發(fā)
          45. Ex_NVIC_Config(GPIO_A,15,FTIR);//下降沿觸發(fā)
          46. MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);//搶占2,子優(yōu)先級2,組2
          47. MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);//搶占2,子優(yōu)先級1,組2
          48. }

          其中的兩個函數(shù):Ex_NVIC_Config(GPIO_A,0,RTIR);和MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);這兩個函數(shù)都是在sys.c里定義,分別完成了步驟2、3、4.函數(shù)原型如下:

          [cpp]view plaincopy
          1. //外部中斷配置函數(shù)
          2. //只針對GPIOA~G;不包括PVD,RTC和USB喚醒這三個
          3. //參數(shù):GPIOx:0~6,代表GPIOA~G;BITx:需要使能的位;TRIM:觸發(fā)模式,1,下升沿;2,上降沿;3,任意電平觸發(fā)
          4. //該函數(shù)一次只能配置1個IO口,多個IO口,需多次調(diào)用
          5. //該函數(shù)會自動開啟對應(yīng)中斷,以及屏蔽線
          6. //待測試...
          7. voidEx_NVIC_Config(u8GPIOx,u8BITx,u8TRIM)
          8. {
          9. u8EXTADDR;
          10. u8EXTOFFSET;
          11. EXTADDR=BITx/4;//得到中斷寄存器組的編號
          12. EXTOFFSET=(BITx%4)*4;
          13. RCC->APB2ENR=0x01;//使能io復(fù)用時鐘
          14. AFIO->EXTICR[EXTADDR]&=~(0xF<
          15. AFIO->EXTICR[EXTADDR]=GPIOx<
          16. //自動設(shè)置
          17. EXTI->IMR=1<
          18. //EXTI->EMR=1<
          19. if(TRIM&0x01)EXTI->FTSR=1<
          20. if(TRIM&0x02)EXTI->RTSR=1<
          21. }

          這個函數(shù)完成了兩個步驟:

          2、開啟IO口復(fù)用時鐘,設(shè)置IO口與中斷線的映射關(guān)系

          3、開啟與該IO口相對的線上的中斷/時間,設(shè)置觸發(fā)條件

          [cpp]view plaincopy
          1. //設(shè)置NVIC
          2. //NVIC_PreemptionPriority:搶占優(yōu)先級
          3. //NVIC_SubPriority:響應(yīng)優(yōu)先級
          4. //NVIC_Channel:中斷編號
          5. //NVIC_Group:中斷分組0~4
          6. //注意優(yōu)先級不能超過設(shè)定的組的范圍!否則會有意想不到的錯誤
          7. //組劃分:
          8. //組0:0位搶占優(yōu)先級,4位響應(yīng)優(yōu)先級
          9. //組1:1位搶占優(yōu)先級,3位響應(yīng)優(yōu)先級
          10. //組2:2位搶占優(yōu)先級,2位響應(yīng)優(yōu)先級
          11. //組3:3位搶占優(yōu)先級,1位響應(yīng)優(yōu)先級
          12. //組4:4位搶占優(yōu)先級,0位響應(yīng)優(yōu)先級
          13. //NVIC_SubPriority和NVIC_PreemptionPriority的原則是,數(shù)值越小,越優(yōu)先
          14. //CHECKOK
          15. //100329
          16. voidMY_NVIC_Init(u8NVIC_PreemptionPriority,u8NVIC_SubPriority,u8NVIC_Channel,u8NVIC_Group)
          17. {
          18. u32temp;
          19. u8IPRADDR=NVIC_Channel/4;//每組只能存4個,得到組地址
          20. u8IPROFFSET=NVIC_Channel%4;//在組內(nèi)的偏移
          21. IPROFFSET=IPROFFSET*8+4;//得到偏移的確切位置
          22. MY_NVIC_PriorityGroupConfig(NVIC_Group);//設(shè)置分組
          23. temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
          24. temp=NVIC_SubPriority&(0x0f>>NVIC_Group);
          25. temp&=0xf;//取低四位
          26. if(NVIC_Channel<32)NVIC->ISER[0]=1<
          27. elseNVIC->ISER[1]=1<<(NVIC_Channel-32);
          28. NVIC->IPR[IPRADDR]=temp<



          關(guān)鍵詞: stm32外部中

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();