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