考慮一個簡單的數字手表,它被編程為只顯示時間,現在想象你想改變它的時區。你會怎么做?您只需按下一個按鈕,即可更改為使您能夠更改時區的菜單。在這里,系統無法預測您對其計時過程的外部中斷,也無法要求您等待,因為它正忙于增加您手表上的秒值。這就是中斷派上用場的地方。
中斷不一定是外部的;它也可以是內部的。大多數情況下,嵌入式中斷還有助于 CPU 的兩個外設之間的通信。考慮一個預設定時器被復位,當時間達到定時器寄存器中的值時觸發中斷。中斷處理程序可用于啟動其他外設,如 DMA。
在本教程中,我們使用了MSP430 上的外部中斷來切換不同的 LED。當使用按鈕通過狀態改變給出外部中斷時,控制權被轉移(搶占)到 ISR 并且它完成了必要的工作。
為什么我們需要中斷?
需要中斷來節省嵌入式系統中的輪詢開銷。當需要通過搶占當前正在運行的任務來執行優先級較高的任務時調??用它們。它也可用于將 CPU 從低功耗模式喚醒。當通過 GPIO 端口被外部信號的邊沿轉換喚醒時,執行 ISR 并且 CPU 再次返回低功耗模式。
MSP430 中的中斷類型
MSP430 中的中斷分為以下類型-
系統重置
不可屏蔽中斷
可屏蔽中斷
向量和非向量中斷
系統重置:
它可能由于電源電壓 (Vcc) 和選擇了復位模式的 RST/NMI 引腳中的低信號而發生,也可能由于看門狗定時器溢出和安全密鑰違規等原因而發生。
不可屏蔽中斷:
這些中斷不能被 CPU 指令屏蔽。一旦啟用了通用中斷,不可屏蔽的中斷就不能從處理中轉移。這是由振蕩器故障和手動提供給 RST/NMI(在 NMI 模式下)的邊沿等源產生的。
可屏蔽中斷:
當中斷發生時,如果它可以被 CPU 指令屏蔽,那么它就是可屏蔽中斷。它們不必總是外部的。它們還依賴于外圍設備及其功能。這里使用的外部端口中斷屬于這一類。
向量中斷和非向量中斷:
Vectored:在這種情況下,中斷設備通過傳遞中斷向量地址為我們提供中斷源。這里ISR 的地址是固定的,控制權轉移到該地址,ISR 負責其余的工作。
Non-Vectored: 這里所有的中斷都有共同的 ISR。當來自非向量源的中斷發生時,控制權被轉移到所有非向量中斷共享的公共地址。
MSP430 中的中斷程序控制
當中斷發生時,MCLK 開啟,CPU 從關閉狀態回調。由于在中斷發生后程序的控制權被轉移到 ISR 地址,程序計數器和狀態寄存器中的值被移入堆棧。
連續清除狀態寄存器,從而清除 GIE 并終止低功耗模式。通過將中斷向量地址放入程序計數器來選擇并執行具有最高優先級的中斷。在我們了解MSP430 GPIO 中斷示例代碼之前,了解其中涉及的端口寄存器的工作非常重要。
MSP430 上用于 GPIO 控制的端口寄存器:
PxDIR:端口方向控制寄存器。它允許程序員通過寫入 0 或 1 來專門選擇其功能。如果一個引腳被選擇為 1,則它充當輸出。將端口 1 視為 8 位端口,如果將引腳 2 和 3 分配為輸出端口,則必須將 P1DIR 寄存器的值設置為 0x0C。
PxIN:它是一個只讀寄存器,可以使用該寄存器讀取端口中的當前值。
PxOUT:此特定寄存器可用于將值直接寫入端口。這只有在上拉/下拉寄存器被禁用時才有可能。
PxREN:它是一個 8 位寄存器,用于啟用或禁用上拉/下拉寄存器。當一個引腳在 PxREN 和 PxOUT 寄存器中都設置為 1 時,特定引腳被上拉。
PxSEL 和 PxSEL2:由于 MSP430 中的所有引腳都是多路復用的,因此在使用它之前必須選擇特定的功能。當特定引腳的 PxSEL 和 PxSEL2 寄存器都設置為 0 時,則選擇通用 I/O。當 PxSEL 設置為 1 時,選擇主要外圍功能,依此類推。
PxIE:它啟用或禁用端口 x 中特定引腳的中斷。
PxIES:它選擇產生中斷的邊沿。為 0,選擇上升沿,為 1,選擇下降沿。
用于測試 GPIO 中斷的 MSP430 電路
用于測試我們的MSP430 中斷示例代碼的 MSP430 電路如下所示。
電路板的接地用于將 LED 和按鈕接地。按鈕的對角兩側為常開端子,按下按鈕時連接。在 LED 之前連接一個電阻器,以避免 LED 的高電流消耗。通常,使用 100 歐姆 - 220 歐姆范圍內的低電阻。
我們使用 3 種不同的代碼來更好地理解端口中斷。前兩個代碼使用與電路圖 1 中相同的電路。讓我們深入研究代碼。建立連接后,我的設置如下所示。
對 MSP430 進行中斷編程
完整的MSP430 中斷程序可以在本頁底部找到,代碼解釋如下。
下面的行使看門狗定時器停止運行。看門狗定時器通常執行兩個操作。一種是通過重置控制器來防止控制器無限循環,另一種是使用內置計時器觸發周期性事件。當微控制器復位(或上電)時,它處于定時器模式,并傾向于在 32 毫秒后復位 MCU。此行阻止控制器執行此操作。
WDTCTL = WDTPW + WDTHOLD;
將P1DIR寄存器設置為值 0x07 將 pin0、pin1 和 pin2 的方向設置為輸出。將P1OUT設置為 0x30 可將其配置為在 pin4 和 pin5 上啟用內部上拉電阻的輸入。將P1REN設置為 0x30 會啟用這些引腳上的內部上拉電阻。P1IE使能中斷,其中 P1IES 選擇從高到低的轉換作為這些引腳上的中斷沿。
P1DIR |= 0x07;
P1OUT = 0x30;
P1REN |= 0x30;
P1IE |= 0x30;
P1IES |= 0x30;
P1IFG &= ~0x30;
下一行啟用低功耗模式并啟用狀態寄存器中的GIE,以便可以接收中斷。
__bis_SR_register(LPM4bits+GIE)
程序計數器使用宏設置為端口 1 向量的地址。
PORT1_VECTOR。
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
下面的代碼一個接一個地切換連接到 pin0、pin1、pin2 的每個 LED。
if(count%3==0)
{
P1OUT ^= BIT1;
P1IFG &= ~0x30;
計數++;
}
else if(count%3==1) { P1OUT ^= BIT1; P1IFG &= ~0x30; 計數++; } 其他 { P1OUT ^= BIT2; P1IFG &= ~0x30; 計數++; }
電路圖2:
同樣,讓我們??嘗試一個不同的引腳來更好地理解這個概念。所以這里的按鈕連接到針腳 2.0 而不是針腳 1.5。修改后的電路如下。該電路再次用于測試MSP430 按鈕中斷程序。
這里的端口 2 用于輸入。所以必須使用不同的中斷向量。P1.4和P2.0接受輸入。
由于端口 2 僅用于輸入,P2DIR 設置為 0。要將端口 2 的 pin0 設置為輸入并啟用內部上拉電阻,寄存器 P2OUT 和 P2REN 必須設置為 1。要啟用端口 2 的 pin0 上的中斷以及選擇中斷的邊沿,P2IE 和 P2IES 的值設置為 1。要重置端口 2 中的標志,P2IFG 被清除,這樣標志可以再次設置在中斷的發生。
P2DIR |= 0x00;
P2OUT = 0x01;
P2REN |= 0x01;
P2IE |= 0x01;
P2IES |= 0x01;
P2IFG &= ~0x01;
當中斷源來自端口 1 時,連接到端口 1 引腳 1 的 LED 會發光。當中斷源屬于端口 2 時,連接到端口 1 的 pin2 的 LED 會發光。
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^= BIT1;
P1IFG &= ~0x10;
for(i=0;i《20000;i++)
{
}
P1OUT ^= BIT1;
}
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
P1OUT ^= BIT2;
P2IFG &= ~0x01;
for(j=0;j《20000;j++)
{
}
P1OUT ^= BIT2;
}
從 CCS 上傳程序到 MSP430
要將項目加載到啟動板并對其進行調試,請選擇項目,然后單擊工具欄中的調試圖標。或者,按 F11 或單擊 RunàDebug 進入調試模式。
進入調試模式后,按下綠色運行按鈕即可在 MCU 中自由運行加載的代碼。現在,當按下按鈕時,邊沿的變化觸發中斷,從而提示 LED 狀態的變化。
MSP430 上的中斷程序
代碼上傳成功后,我們可以通過簡單的按鈕進行測試。每當使用按鈕發出中斷時,LED 模式將根據我們的程序發生變化。
#項目1:
#include
整數計數 = 0;
詮釋主要(無效)
{
WDTCTL = WDTPW + WDTHOLD;
P1DIR |= 0x07;
P1OUT = 0x30;
P1REN |= 0x30;
P1IE |= 0x30;
P1IES |= 0x30;
P1IFG &= ~0x30;
__bis_SR_register(LPM4_bits + GIE); // 進入帶中斷的 LPM4
}
// 端口 1 中斷服務程序
#pragma 向量=PORT1_VECTOR
__interrupt 無效端口_1(無效)
{
如果(計數%3==0)
{
P1OUT ^= BIT1;
P1IFG &= ~0x30;
計數++;
}
否則 if(count%3==1)
{
P1OUT ^= BIT1;
P1IFG &= ~0x30;
計數++;
}
別的
{
P1OUT ^= BIT2;
P1IFG &= ~0x30;
計數++;
}
}
#項目2:
#include
整數 i, j;
詮釋主要(無效)
{
WDTCTL = WDTPW + WDTHOLD;
P1DIR |= 0x06;
P1OUT = 0x10;
P1REN |= 0x10;
P1IE |= 0x10;
P1IES |= 0x10;
P1IFG &= ~0x10;
P2DIR |= 0x00;
P2OUT = 0x01;
P2REN |= 0x01;
P2IE |= 0x01;
P2IES |= 0x01;
P2IFG &= ~0x01;
__bis_SR_register(LPM4_bits + GIE); // 進入帶中斷的 LPM4
}
// 端口 1 中斷服務程序
#pragma 向量=PORT1_VECTOR
__interrupt 無效端口_1(無效)
{
P1OUT ^= BIT1;
P1IFG &= ~0x10;
for(i=0;i<20000;i++)
{
}
P1OUT ^= BIT1;
}
#pragma 向量=PORT2_VECTOR
__interrupt 無效端口_2(無效)
{
P1OUT ^= BIT2;
P2IFG &= ~0x01;
對于(j=0;j<20000;j++)
{
}
P1OUT ^= BIT2;
}
-
led
+關注
關注
242文章
23355瀏覽量
663160 -
msp430
+關注
關注
180文章
2403瀏覽量
229611 -
外部中斷
+關注
關注
1文章
132瀏覽量
15883
發布評論請先 登錄
相關推薦
評論