基礎教程11 Arduino中斷介紹
來自專欄 Arduino 魔法書1 人贊了文章
我是潘,曾經是個工程師。這是為 http://Ardui.Co 製作的 「Arduino 公開課」 系列的入門教程。前面我們已經學會了Arduino最基本的使用,現在要介紹一些更高級的玩法:中斷,看看怎樣打斷 Arduino loop() 的循環,去執行其他任務。有任何疑問請在評論區提出,我會逐一回答。
日常生活中,中斷是一個很容易理解的概念。比如,正在寫這篇教程稿,突然間手機響了,我去接電話,通話完畢,繼續寫。這個過程就是「中斷」和「中斷處理」。鈴聲讓我中斷當前的工作,去處理更緊急的事情,處理完後,再回頭原來的工作。
電話鈴響叫做「中斷請求」,暫停寫稿稱為「中斷響應」,接電話過程就是「中斷處理」。Arduino 執行任務過程中,出現某個事件,轉而執行這一事件的程序,執行完後,再回到中斷點繼續原來的任務,就是中斷程序。
為什麼要使用中斷呢?再舉個例子,你來拜訪我,但我不知道你何時到達,你到達門口就只能在外面等著。如果門口裝個門鈴,你按一下門鈴,我就會中斷當下的工作(比如準備晚餐)去開門,這就避免了等待和浪費時間,提高處理器的執行效率。
產生中斷請求的方式,一般有三類:
- 程序或硬體出現異常或故障,稱為「異常中斷」;
- 程序執行了設定好的中斷指令(即定時器),稱為「內部中斷」;
- 感測器、按鈕等外部設備提出中斷請求,稱為「外部中斷」;(沒錯!開發板上 Reset 按鈕就是其一)
這三類中斷裡面,外部中斷最常用也最好理解,內部中斷講起來有點複雜,處理異常中斷則是一個嚴肅的難題。所以遵從從易到難的原則,我們先從外部中斷開始介紹。
對大部分 Arduino 來說,要促發外部中斷,就要用特定的引腳,不同版本 Arduino 的中斷埠的位置、編號也不同。我們一直使用的 Uno ,規定 D2、D3 是中斷觸發埠,在中斷函數的參數裡面,編號分別為 0、1。而 Due、101 等版本最厲害,所有埠都可以能觸發中斷:
更多 Arduino 版本可以參考官方文檔。
要使用中斷程序,可以直接調用 :
attachInterrupt(interrupt, ISR, mode)
參數含義如下:
interrupt:中斷埠編號,Uno 只有0、1(即D2、D3)兩個埠
ISR:中斷服務程序,即中斷後要執行的程序mode:中斷請求的方式,可以設置成下面4種:LOW 當引腳為低電平時,觸發中斷
CHANGE 當引腳電平發生改變時,觸發中斷RISING 當引腳由低電平變為高電平時,觸發中斷
FALLING 當引腳由高電平變為低電平時,觸發中斷使用 attachInterrupt() 時要注意以下幾點:
1、中斷函數不能帶參數,也沒有返回值;2、中斷函數中,delay函數不能使用;
3、讀取串口數據的話,可能會丟失(原因後面的課程講);4、中斷函數裡面,使用的變數需要定義為 volatile 型。這是官方給出的例子:
const byte ledPin = 13;const byte interruptPin = 2;volatile byte state = LOW; void setup() { pinMode(ledPin, OUTPUT); pinMode(interruptPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);//設置觸發中斷的埠,中斷後運行的程序和觸發模式} void loop() { digitalWrite(ledPin, state);} void blink()//改變LED的狀態,如果是LOW,則改為HIGH,反之亦然{ state = !state;}
根據官方文檔建議,採用 digitalPinToInterrupt(pin) 可以自動識別不同版本的 Arduino,自動映射中斷埠。比如,interruptPin 設置為 D2,在 Uno 上自動映射為中斷埠 0,在 Leonardo 上自動映射為1,非常方便,且提高了程序兼容性。
在下一節課,我們將以實際例子來介紹外部中斷的應用。
推薦閱讀: