Arduino 中斷

2020-10-21 16:49 更新

中斷(interrupt)停止Arduino的當(dāng)前工作,以便可以完成一些其他工作。

假設(shè)你坐在家里和別人聊天。突然電話響了。停止聊天,拿起電話與來(lái)電者通話。當(dāng)你完成電話交談后,你回去和電話響之前的那個(gè)人聊天。

同樣,你可以把主程序想象成是與某人聊天,電話鈴聲使你停止聊天。中斷服務(wù)程序是在電話上通話的過(guò)程。當(dāng)通話結(jié)束后,你回到你聊天的主程序。這個(gè)例子準(zhǔn)確地解釋了中斷如何使處理器執(zhí)行操作。

主程序在電路中運(yùn)行并執(zhí)行一些功能。但是,當(dāng)發(fā)生中斷時(shí),主程序在另一個(gè)程序執(zhí)行時(shí)停止。當(dāng)這個(gè)程序結(jié)束時(shí),處理器再次返回主程序。

中斷

重要特征

這里有一些關(guān)于中斷的重要特征:

  • 中斷可以來(lái)自各種來(lái)源。在這種情況下,我們使用的是由數(shù)字引腳上的狀態(tài)改變觸發(fā)的硬件中斷。

  • 大多數(shù)Arduino設(shè)計(jì)有兩個(gè)硬件中斷(稱(chēng)為“interrupt0”和“interrupt1”)分別硬連接到數(shù)字I/O引腳2和3。

  • Arduino Mega有六個(gè)硬件中斷,包括引腳21,20,19和18上的附加中斷(“interrupt2”到“interrupt5”)。

  • 你可以使用稱(chēng)為“中斷服務(wù)程序”(Interrupt Service Routine,通常稱(chēng)為ISR)的特殊函數(shù)來(lái)定義程序。

  • 你可以定義該程序并指定上升沿,下降沿或兩者的條件。在這些特定條件下,將處理中斷。

  • 每次在輸入引腳上發(fā)生事件時(shí),都可以自動(dòng)執(zhí)行該函數(shù)。

中斷類(lèi)型

有兩種類(lèi)型的中斷:

  • 硬件中斷 - 它們響應(yīng)外部事件而發(fā)生,例如外部中斷引腳變?yōu)楦唠娖交虻碗娖健?/span>

  • 軟件中斷 - 它們響應(yīng)于在軟件中發(fā)送的指令而發(fā)生。“Arduino語(yǔ)言”支持的唯一類(lèi)型的中斷是attachInterrupt()函數(shù)。

在Arduino中使用中斷

中斷在 Arduino 程序中非常有用,因?yàn)樗兄诮鉀Q時(shí)序問(wèn)題。中斷的良好應(yīng)用是讀取旋轉(zhuǎn)編碼器或觀察用戶(hù)輸入。一般情況下,ISR 應(yīng)盡可能短且快。如果你的草圖使用多個(gè) ISR,則一次只能運(yùn)行一個(gè)。其他中斷將在當(dāng)前完成之后執(zhí)行,其順序取決于它們的優(yōu)先級(jí)。

通常,全局變量用于在 ISR 和主程序之間傳遞數(shù)據(jù)。為了確保在 ISR 和主程序之間共享的變量正確更新,請(qǐng)將它們聲明為 volatile。

Arduino 中主要有時(shí)鐘中斷和外部中斷,本文所說(shuō)的中斷指的是外部中斷。Arduino 中的外部中斷通常是由Pin 口(數(shù)字 Pin 口,不是模擬口)電平改變觸發(fā)的。每種型號(hào)的 Arduino 版都有數(shù)個(gè) Pin 口可以用來(lái)注冊(cè)中斷,具體如下:

開(kāi)發(fā)板 可以用來(lái)注冊(cè)中斷的Pin口
Uno, Nano, Mini, other 328-based 2, 3
Uno WiFi Rev.2 所有數(shù)字口
Mega, Mega2560, MegaADK 2, 3, 18, 19, 20, 21
Micro, Leonardo, other 32u4-based 0, 1, 2, 3, 7
Zero 除了4號(hào)口外的所有數(shù)字口
MKR Family boards 0, 1, 4, 5, 6, 7, 8, 9, A1, A2
Due 所有數(shù)字口
101 所有數(shù)字口 (只有 2, 5, 7, 8, 10, 11, 12, 13數(shù)字口可以使用 ?CHANGE類(lèi)型中斷,中斷類(lèi)型在下文有介紹)

注冊(cè)中斷主要是通過(guò)? attachInterrupt() ?函數(shù)實(shí)現(xiàn)的,其原型為:

void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode);
  1. 第一個(gè)參數(shù)為中斷號(hào),Arduino上每個(gè)可以注冊(cè)中斷的Pin口都會(huì)被分配一個(gè)中斷號(hào),這里需要傳入的是中斷號(hào)而不是Pin口號(hào)。但是不同的Arduino開(kāi)發(fā)板上面的中斷號(hào)分配并不完全一樣。各個(gè)開(kāi)發(fā)板的Pin口號(hào)和中斷號(hào)對(duì)應(yīng)關(guān)系如下:
     開(kāi)發(fā)板  中斷號(hào)0  中斷號(hào)1  中斷號(hào)2  中斷號(hào)3  中斷號(hào)4  中斷號(hào)5
     Uno, Ethernet  PIN 2  PIN 3        
     Mega2560  PIN 2  PIN 3  PIN 21  PIN 20  PIN 19  PIN 18
     基于32u4的開(kāi)發(fā)板 如 Leonardo, Micro  PIN 3  PIN 2  PIN 0  PIN 1  PIN 7  
    從上表中可以看出同一個(gè) Pin 口在不同的開(kāi)發(fā)板上可能會(huì)有不同的中斷號(hào),這勢(shì)必會(huì)影響程序的可移植性。幸運(yùn)的是,Arduino 還提供了另一個(gè)函數(shù) digitalPinToInterrupt(int)。從名字就能看出,這個(gè)函數(shù)能輸入 Pin 口號(hào)并輸出對(duì)應(yīng)的中斷號(hào)。需要注意的是,輸入的 Pin 口號(hào)需要在上述的支持列表當(dāng)中。所以,Arduino 官方推薦我們使用 
    attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); 
    這種方式來(lái)注冊(cè)中斷號(hào)。
  2. 第二個(gè)參數(shù)是中斷服務(wù)例程(ISR)的函數(shù)指針,在 C/C++ 中直接寫(xiě)該函數(shù)的函數(shù)名即可。在觸發(fā)時(shí),該函數(shù)將會(huì)被調(diào)用。該函數(shù)必須沒(méi)有任何的參數(shù)也沒(méi)有任何的返回值。
  3. 第三個(gè)參數(shù)是中斷觸發(fā)條件,由幾個(gè)可選的值:
    LOW 當(dāng)中斷所在 Pin 口處于低電平時(shí)觸發(fā)
    CHANGE 當(dāng)中斷所在 Pin口電平改變時(shí)觸發(fā)
    RISING 當(dāng)中斷所在Pin口從低電平變?yōu)楦唠娖?上升沿)時(shí)觸發(fā)
    FALLING 當(dāng)中斷所在Pin口從高電平變?yōu)榈碗娖?下降沿)時(shí)觸發(fā)
    對(duì)于 Due,Zero 和 MKR1000開(kāi)發(fā)板,還有一個(gè) HIGH 表示當(dāng)中斷所在 Pin 口處于高電平時(shí)觸發(fā)

示例

int pin = 2; //define interrupt pin to 2
volatile int state = LOW; // To make sure variables shared between an ISR
//the main program are updated correctly,declare them as volatile.

void setup() {
   pinMode(13, OUTPUT); //set pin 13 as output
   attachInterrupt(digitalPinToInterrupt(pin), blink, CHANGE);
   //interrupt at pin 2 blink ISR when pin to change the value
} 
void loop() { 
   digitalWrite(13, state); //pin 13 equal the state value
} 

void blink() { 
   //ISR function
   state = !state; //toggle the state when the interrupt occurs
}

attachInterrupt語(yǔ)句語(yǔ)法

attachInterrupt(digitalPinToInterrupt(pin),ISR,mode);//recommended for arduino board
attachInterrupt(pin, ISR, mode) ; //recommended Arduino Due, Zero only
//argument pin: the pin number
//argument ISR: the ISR to call when the interrupt occurs; 
   //this function must take no parameters and return nothing. 
   //This function is sometimes referred to as an interrupt service routine.
//argument mode: defines when the interrupt should be triggered.

在 Arduino 中使用中斷需要注意的問(wèn)題

  1. 由于中斷會(huì)打斷正常代碼的運(yùn)行,因此 ISR 的應(yīng)該盡可能快地執(zhí)行完畢。
  2. 在 ISR 中修改的全局變量要用 volatile 修飾符修飾以防止編譯器優(yōu)化
  3. 在 ISR 中不能使用其他用中斷實(shí)現(xiàn)的函數(shù),如 millis() delay() 等。延時(shí)可以使用  delayMicroseconds(),它不是用中斷實(shí)現(xiàn)的。





以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)