什麼是 Interrupts?
當你在工作的時候,突然電話鈴聲響起,於是你把手邊工作停下來、接電話、講電話,然後回來繼續剛剛工作 -- 這就是所謂的中斷 (Interrupt),而電話便是中斷源。在微控制器中,中斷的來源有很多,諸如 Reset, 外部中斷, Timer, USART, EEPROM, ADC 等。比如,當 Timer Overflow 時可以引發中斷,當 USART 收到資料或資料傳輸完畢時可以引發中斷…
跟人一樣,在遇到中斷的時候,微控制器的 CPU 也會把手邊的工作停下來,然後跳到預設的位址 (接電話),接著執行一段程式 (講電話),執行完後回來繼續進行剛剛的工作。
在發生中斷的時候,CPU 會老老實實的做這幾個動作:
- 執行當前的指令
- 把下一個指令的位址 push 到 stack 上,停止程式的正常流程,然後
- 跳到預設的位址,這個位址稱為中斷向量表,是由 MCU 製造商預先定義好的。 在中斷向量表中,每個中斷都有一個 entry,就看發生什麼中斷,CPU 就跳到哪個 entry。通常每個 entry 裏只是一條 JMP xxxx 的指令,會讓 CPU 輾轉跳到一段稱為中斷服務函式 (Interrupt Service Routine, ISR) 的副程式。
- 接著執行中斷服務函式
- 當執行完中斷服務函式後,再從 stack 上 pop 出指令的位址,並從它離開的地方繼續執行程式
Interrupt vectors
底下這張是 ATmega328 的中斷向量表:當中斷觸發時,CPU 會跳到預設的位址,例如當 ADC 轉換完成時會引發 ADC 中斷,CPU 這時就會跳到 0x002A 這個位址 (vector 22 所在的位址) 去執行指令。如前面說的,通常中斷向量表的每個 entry 裏只是一條 JMP xxxx 的指令,會讓 CPU 輾轉跳到中斷服務函式 (ISR)。
底下是中斷向量表典型的設定:
以上面的程式為例,當發生 reset 中斷時,MCU 執行的第一條指令是 jmp RESET,因此會跳到 0x0033 的位址,亦即主程式的起始位置。假如是 ADC 中斷,MCU 會先跳到中斷向量表 0x002A 的位址,之後輾轉跳到 ADC 這個中斷服務函式。
Interrupt Service Routine (ISR)
在 Arduino 的程式中,要寫 ISR 是很簡單的一件事。你不需要自己設定中斷向量表,只要會使用 ISR() 這個巨集指令就可以了,例如:這表示這個是處理 ADC 轉換的中斷服務函式,將來當 ADC 轉換完成時會引發中斷,CPU 就會來執行這個中斷服務函式。
底下這張表列出了 ATmega328 的所有中斷向量:
Vector | 說明 |
---|---|
INT0_vect | External Interrupt Request 0 |
INT1_vect | External Interrupt Request 1 |
PCINT0_vect | Pin Change Interrupt Request 0 |
PCINT1_vect | Pin Change Interrupt Request 1 |
PCINT2_vect | Pin Change Interrupt Request 2 |
WDT_vect | Watchdog Time-out Interrupt |
TIMER2_COMPA_vect | Timer/Counter2 Compare Match A |
TIMER2_COMPB_vect | Timer/Counter2 Compare Match B |
TIMER2_OVF_vect | Timer/Counter2 Overflow |
TIMER1_CAPT_vect | Timer/Counter1 Capture Event |
TIMER1_COMPA_vect | Timer/Counter1 Compare Match A |
TIMER1_COMPB_vect | Timer/Counter1 Compare Match B |
TIMER1_OVF_vect | Timer/Counter1 Overflow |
TIMER0_COMPA_vect | TimerCounter0 Compare Match A |
TIMER0_COMPB_vect | TimerCounter0 Compare Match B |
TIMER0_OVF_vect | Timer/Couner0 Overflow |
SPI_STC_vect | SPI Serial Transfer Complete |
USART_RX_vect | USART Rx Complete |
USART_UDRE_vect | USART, Data Register Empty |
USART_TX_vect | USART Tx Complete |
ADC_vect | ADC Conversion Complete |
EE_READY_vect | EEPROM Ready |
ANALOG_COMP_vect | Analog Comparator |
TWI_vect | Two-wire Serial Interface |
SPM_READY_vect | Store Program Memory Read |
Cooper好,
回覆刪除非常抱歉...因為短時間閱讀你大量文章
有些文章有印象...但忘記在哪了><
請問我記得有一篇寫到用單張板做到"簡易多工"的效果
請問Cooper您知道是哪一篇有寫到嗎?
我翻遍interupt還有timer都沒找到...
繼續尋找ing~~~
補充說明, 我記得那一篇有強調不使用delay....
回覆刪除然後到底是用什麼達到多工...我實在是忘了@@
我超想看那篇文章阿阿阿~~~~~><
你是說這篇嗎?
回覆刪除不使用延遲的燈號閃爍程式 (Blink without delay)
這兩篇文章你可能有興趣:
回覆刪除同時執行多個活動與 TimedAction 函式庫簡介
http://yehnan.blogspot.tw/2012/03/arduino.html
對對對!!!就是這篇~~~哈哈~~
回覆刪除因為沒有放在首頁的上欄裡面~~
我還在想我是在哪看到的哩~~~~
原來是之前從你網誌翻箱倒櫃找出來的XDDD
Ask, and it shall be given! haha~
回覆刪除