<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>
"); //-->

博客專(zhuān)欄

EEPW首頁(yè) > 博客 > 如何開(kāi)發(fā)嵌入式中斷控制系統?

如何開(kāi)發(fā)嵌入式中斷控制系統?

發(fā)布人:美男子玩編程 時(shí)間:2023-12-18 來(lái)源:工程師 發(fā)布文章

在嵌入式開(kāi)發(fā)過(guò)程中,中斷處理是一個(gè)不可或缺的環(huán)節。本篇博文將以STM32微控制器為核心案例,深入解析中斷處理在MCU開(kāi)發(fā)中的關(guān)鍵步驟和策略。

主要有以下幾個(gè)關(guān)鍵點(diǎn):

  • 中斷向量表。

  • NVIC(內嵌向量中斷控制器)。

  • 中斷使能。

  • 中斷服務(wù)函數。

通過(guò)這篇博文,讀者將獲得對STM32 MCU中斷處理流程和邏輯的全面理解。

1

中斷向量表

中斷向量表是關(guān)鍵的數據結構,用于存儲中斷服務(wù)程序的入口地址,這些地址被稱(chēng)為中斷向量。具體來(lái)說(shuō),當一個(gè)中斷發(fā)生時(shí),系統會(huì )自動(dòng)跳轉到中斷向量表中對應的地址,從而執行相應的中斷服務(wù)程序(函數)。這個(gè)表由半導體制造商預先定義,確保每個(gè)中斷都有一個(gè)唯一的入口地址。

在程序架構中,中斷向量表位于最前面,起到了連接硬件中斷信號和相應處理程序的橋梁作用。中斷向量表在整個(gè)程序的最前面,比如 STM32F103 的中斷向量表如下所示:


圖片


中斷向量表都是鏈接到代碼的最前面,比如一般 ARM 處理器都是從地址 0X00000000 開(kāi)始執行指令的,那么中斷向量表就是從 0X00000000 開(kāi)始存放的。代碼第 1 行的“__initial_sp”就是第一條中斷向量,存放的是棧頂指針,接下來(lái)是第 2 行復位中斷復位函數 Reset_Handler 的入口地址,依次類(lèi)推,直到第 27 行的最后一個(gè)中斷服務(wù)函數DMA2_Channel4_5_IRQHandler 的入口地址,這樣 STM32F103 的中斷向量表就建好了。

雖然ARM處理器默認從地址0X00000000開(kāi)始執行程序,但在學(xué)習STM32時(shí),我們通常將代碼下載到從0X8000000地址開(kāi)始的存儲區域。這一做法似乎與處理器的初始執行地址不符,看起來(lái)可能導致錯誤。然而,為了解決這一潛在問(wèn)題,Cortex-M架構引入了中斷向量表偏移的概念。這使得開(kāi)發(fā)者可以將中斷向量表放置在任何所需的地址位置。中斷向量表的具體偏移配置是在'SystemInit'函數中完成的,方法是向SCB_VTOR寄存器寫(xiě)入新的中斷向量表首地址。這種靈活的配置方式有效地克服了初始地址和程序存儲地址之間的潛在沖突,確保了中斷處理的正確進(jìn)行。

代碼如下所示:


圖片


第 8 行和第 10 行就是設置中斷向量表偏移,第 8 行是將中斷向量表設置到 RAM 中,第10 行是將中斷向量表設置到 ROM 中,基本都是將中斷向量表設置到 ROM 中,也就是地址0X8000000 處。第 10 行用到了 FALSH_BASE 和 VECT_TAB_OFFSET,這兩個(gè)都是宏,定義如下所示:



#define FLASH_BASE ((uint32_t)0x08000000)#define VECT_TAB_OFFSET 0x0

因此第 10 行的代碼就是:SCB->VTOR=0X080000000,中斷向量表偏移設置完成。

2

NVIC(內嵌向量中斷控制器)

NVIC(Nested Vectored Interrupt Controller)是ARM Cortex-M微控制器的一個(gè)關(guān)鍵組件,用于管理中斷。各個(gè)芯片廠(chǎng)商在設計芯片的時(shí)候會(huì )對Cortex-M內核里面的NVIC進(jìn)行裁剪,把不需要的部分去掉,所以說(shuō)STM32的NVIC是Cortex-M3的NVIC 的一個(gè)子集。


圖片


其主要功能包括:

  • 中斷優(yōu)先級管理:NVIC允許為每個(gè)中斷分配不同的優(yōu)先級。這樣,當多個(gè)中斷同時(shí)發(fā)生時(shí),處理器可以根據優(yōu)先級來(lái)確定處理的順序,確保更重要的任務(wù)得到優(yōu)先處理。

  • 嵌套中斷處理:NVIC支持中斷的嵌套。這意味著(zhù)一個(gè)高優(yōu)先級的中斷可以打斷一個(gè)低優(yōu)先級的中斷服務(wù)例程,使得系統能夠及時(shí)響應更緊急的任務(wù)。

  • 向量化中斷處理:每個(gè)中斷都有一個(gè)唯一的向量地址,該地址指向相應的中斷服務(wù)例程。當中斷發(fā)生時(shí),處理器可以直接跳轉到相應的服務(wù)例程,無(wú)需通過(guò)傳統的中斷查詢(xún)方式,從而提高了處理速度。

  • 中斷屏蔽與啟用:NVIC允許程序動(dòng)態(tài)地使能或禁用特定中斷。這種靈活性使得系統可以在不同的操作環(huán)境下,根據需要調整其中斷響應。

  • 中斷掛起與恢復:NVIC能夠掛起正在執行的中斷,并在適當的時(shí)候恢復中斷的處理。這對于管理復雜的中斷場(chǎng)景尤為重要。

  • 中斷狀態(tài)管理:NVIC提供接口來(lái)查詢(xún)中斷的狀態(tài),例如檢查哪些中斷處于掛起狀態(tài)或哪些中斷正在被處理。這有助于更好地理解和控制系統的行為。

  • 低功耗模式支持:在低功耗模式下,NVIC可以幫助處理器在接收到中斷信號時(shí)喚醒,這對于節能和延長(cháng)電池使用壽命至關(guān)重要。

  • 系統復位管理:NVIC還負責處理來(lái)自系統的復位請求,確保系統能夠在出現問(wèn)題時(shí)安全地重新啟動(dòng)。

通過(guò)查看STM32 NVIC寄存器,可以更清晰的解NVIC的主要功能:



















/**  中斷   NVIC 結構體定義 */typedef struct{  __IO uint32_t ISER[8];                 /*!<offset: 0x000="" 中斷使能寄存器="" *="" uint32_t RESERVED0[24];                                     __IO uint32_t ICER[8];                 /*!<offset: 0x080="" 中斷清除寄存器="" *="" uint32_t RSERVED1[24];                                      __IO uint32_t ISPR[8];               /*!<offset: 0x100="" 中斷使能懸起寄存器="" *="" uint32_t RESERVED2[24];                                     __IO uint32_t ICPR[8];                 /*!<offset: 0x180="" 中斷清除懸起寄存器="" *="" uint32_t RESERVED3[24];                                      __IO uint32_t IABR[8];               /*!<offset:0x200 中斷有效位寄存器="" *="" uint32_t RESERVED4[56];                                     __IO uint8_t  IP[240];                 /*!< Offset: 0x300  中斷優(yōu)先級寄存器 (8Bit wide) */  uint32_t RESERVED5[644];                                    __O  uint32_t STIR;                    /*!< Offset: 0xE00  軟件觸發(fā)中斷寄存器     */}  NVIC_Type;

3

中斷使能

中斷使能是指允許特定的中斷源向處理器發(fā)出中斷請求的過(guò)程。當一個(gè)中斷被使能后,如果相應的事件發(fā)生(如外部信號、定時(shí)器溢出等),中斷控制器會(huì )捕捉到這個(gè)事件,并通知處理器中斷程序需要被執行。

中斷使能通常通過(guò)設置特定的控制寄存器來(lái)完成。這些寄存器可能是微控制器的一部分,也可能位于外部設備中。通過(guò)編寫(xiě)特定的值到這些寄存器,可以選擇性地使能或禁用特定的中斷。

要使用某個(gè)外設的中斷,肯定要先使能這個(gè)外設的中斷,以 STM32F103 的 PE2 這個(gè) IO 為例,假如我們要使用 PE2 的輸入中斷肯定要使用如下代碼來(lái)使能對應的中斷:






NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //搶占優(yōu)先級 2,NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;        //子優(yōu)先級 2NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;              //使能外部中斷通道NVIC_Init(&NVIC_InitStructure);

4

中斷服務(wù)函數

中斷服務(wù)函數是響應中斷的專(zhuān)門(mén)函數。當特定的中斷事件發(fā)生時(shí),系統自動(dòng)調用對應的中斷服務(wù)函數來(lái)處理該事件。

當中斷發(fā)生時(shí),處理器暫停當前正在執行的任務(wù),保存當前任務(wù)的上下文(如寄存器狀態(tài)),然后跳轉到相應的中斷服務(wù)函數執行中斷處理。一旦中斷處理完成,處理器恢復之前任務(wù)的上下文,并繼續執行被中斷的任務(wù)。


圖片


同樣以 STM32F103 的 PE2 為例,其中斷服務(wù)函數如下所示:






/* 外部中斷 2 服務(wù)程序 */void EXTI2_IRQHandler(void){    /* 中斷處理代碼 */}

當 PE2 引腳的中斷觸發(fā)以后就會(huì )調用其對應的中斷處理函數 EXTI2_IRQHandler,我們可以在函數 EXTI2_IRQHandler 中添加中斷處理代碼。

*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。



關(guān)鍵詞: 嵌入式

相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>