以前一起修 C 語言的好友,最近正在上 8051 單晶片的課程,他問我何謂中斷?這真的難倒我了。難的不是中斷的概念,而是如何在大半夜地透過網路解釋?沒辦法當面畫圖比手畫腳地說,實在很難讓人懂。
一般我們初學在 8051 中所寫的 C 語言都是長這樣:
1 | main() |
沒意外的話,整個程式就會 123, 123, 123,… 無限循環的執行,因為結束之後系統會自動 Reset,程式重新來過。每個地方停留的時間完全取決於 CPU 全速衝刺的速度有多快。
有可能今天的程式是這樣:
1 | main() |
那CPU每次都要去查看手機是否有新訊息?,有才執行 statement_1,這種方式叫做輪詢(Polling)。因為每次都要問,很沒有效率,如果你每毫秒都拿手機起來看,看有沒有簡訊?有沒有未接來電?有沒有 FB 訊息?這樣不是很沒效率嗎?你也不用上班、不用睡覺了,一直看手機就好了,這樣是多浪費生命,多沒意義的事啊。
通常 8051 的入門課程會教大家這樣做:
1 | main() |
在delay1ms( );的過程中,CPU 還是全速的在衝刺,只是一些無意義的運算去消耗 CPU 時間而已。這樣雖然你就不用持續盯著手機,一秒鐘才看一次,但還是會衍生其他問題
-
statement_2 與 3 可能是很忙碌的運算,雖然沒有即時處理的需求,但最好能全速衝刺,例如浮點運算
或是和女朋友XX。可是這種寫法,後面的程式全部都會被延遲1秒才執行(此處是自動 Reset 的無限迴圈,所以不管寫在前面或後面,所有的程式都會被延遲 1 秒才執行)。如果你一秒鐘才X一次,每次X一下之前還要檢查手機有沒有新訊息(輪詢的行為),你能不被踢下床嗎? -
你的大腦在 delay1ms(1000)的過程中,並不是真的 delay,還是一樣全速運轉,但想的都是些沒營養的事情
像是 SOD,這樣不是太浪費人生了嗎?
這時候如果把程式改成這樣:
1 | //宣告:當鈴聲響起時,執行 interrupt 0 函式 |
這樣的話,我們就可以不斷地在 main() 全速衝刺!當鈴聲響起時,main() 會暫停,CPU 就不會照著原先的順序執行,先跑去執行 ISR_int0(),做完之後再從 main()暫停的地方繼續往下執行,這種機制就叫做「中斷」,因為 main() 被中斷了。雖然必須把大部分的時間放在和女朋友XX,但是有些事情…
- 外部觸發(INT):更重要,不馬上處理不行,否則後果可能很嚴重(例如她老爸敲門)
- 定時要做(Timer):交作業 deadline 到了,不交會被當
- 溢位(Overflow):
滿出來了要趕快清理(8051 好像只有 Timer 暫存器會因溢位而中斷)
以上這幾件事情都有時效性,很緊急,要趕快處理!
但是中斷的同時可能又有中斷!你能想像她老爸敲門的同時,助教又打電話來催交作業嗎?這時候就是蠟燭兩頭燒!所以中斷函式要盡量減短,盡早結束。
中斷的觀念解釋完了,至於中斷正確的設定方式,隨每家MCU的不同而不同,8051 based 的基本上都差不多,AT89S5x 則與標準型 8051 完全相同,這部分就請看自己的課本吧!