實驗目的
練習使用 attachInterrupt() 函式與外部中斷。在這個實驗中,你將利用 attachInterrupt() 函式設定中斷處理函式(Interrupt Service Routine, ISR),讓程式在 pin 2 產生外部中斷時自動執行 ISR。
材料
- Arduino 主板 x 1
- LED x 1
- Pushbutton x 1
- 10K 歐姆電阻 x 1
- 麵包板 x 1
- 單心線 x N
接線
- 把 LED 接到 pin13,長腳(陽極)接到 pin13,短腳(陰極)接到 GND
- 把 pushbutton 一支腳接到 +5V,另一支腳接到 pin 2 同時接一顆 10K 電阻連到 GND
電路圖
程式
先來看非中斷版本的程式(button.pde):
這支是 Arduino 的初級程式,我們在「Lab2 - 使用按鍵 (PushButton)控制 LED 燈號」中看過,程式邏輯很簡單,當按鍵被按下時打開 LED 燈號,在按鍵放開時關閉 LED 燈號。
底下的程式(attachInterrupt.pde)則是使用 attachInterrupt() 版與外部中斷的版本,程式作用是一樣的,當按鍵被按下時打開 LED 燈號,在按鍵放開時關閉 LED 燈號:
要特別注意是,程式裏的 buttonState 變數是宣告成 volatile,這樣做的目的是告訴 Compiler 不要做最佳化,避免變數狀態不同步。給你一個建議,程式主體跟 ISR 都會用到的變數,盡可能把它宣告成 volatile。
attachInterrupt() 函式
attachInterrupt() 函式的用途是用來指定外部中斷的處理函式(Interrupt Service Routine, ISR),就像範例程式所示範的指定 buttonStateChanged() 當作 Interrupt 0 外部中斷的處理函式。
attachInterrupt() 函式有三個參數:
- interrupt: 外部中斷的編號。大部份 Arduino 板子都有兩個外部中斷,編號 0 (Interrupt 0)是在 pin 2 上,而編號 1 (Interrupt 1)是在 pin 3 上。
- function: 中斷處理函式(Interrupt Service Routine, ISR)。中斷處理函式必須是不接受參數而且不回傳任何東西。
- mode: 定義什麼狀況下該觸發中斷,有四個可以設定的常數值:
- LOW: 當 pin 為 LOW 時觸發中斷
- CHANGE: 當 pin 狀態改變時觸發中斷,不管是從 HIGH 到 LOW 或從 LOW 到 HIGH
- RISING: 當 pin 狀態從 LOW 到 HIGH 時觸發中斷,RISING 又稱正緣觸發
- FALLING: 當 pin 狀態從 HIGH 到 LOW 時觸發中斷,FALLING 又稱負緣觸發
如果要移除外部中斷服務函式,就使用 detachInterrupt() 函式。
啟用與停止中斷
如果要停止 Arduino 所有中斷,可以呼叫 noInterrupt() 函式,要重新啟用中斷,只要呼叫一次 interrupts() 函式即可。
作者已經移除這則留言。
回覆刪除哈囉Cooper~~
回覆刪除我希望在中斷發生後能夠閃爍LED燈三次
所以把interrupt 0 中斷處裡函式改寫為下
但執行的時候卻不會閃三次,反倒有點不受控
請問Cooper是哪邊發生問題呢?
我有查詢一下似乎是中斷內不能加delay()??
那該如何解決呢??
void buttonStateChanged() {
for(int i=0;i<3:i++)
{
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
}
}
對,ISR 通常都只是做很簡單的事,不可以花太多時間
回覆刪除你應該在 ISR 裏設一個旗號,然後在 Loop() 裏不斷檢查旗號決定要不要讓 LED 閃爍
FALLING: 當 pin 狀態從 LOW 到 HIGH 時觸發中斷,FALLING 又稱負緣觸發
回覆刪除這邊是不是沒改道@@?
真的,這篇沒改到
回覆刪除哇,你是我的忠實讀者?