LKY 只有原創內容的 Blog

今之能者,謂能轉貼,至於魯蛇,皆能轉貼。不原創,何以別乎?

以前一起修 C 語言的好友,最近正在上 8051 單晶片的課程,他問我何謂中斷?這真的難倒我了。難的不是中斷的概念,而是如何在大半夜地透過網路解釋?沒辦法當面畫圖比手畫腳地說,實在很難讓人懂。

一般我們初學在 8051 中所寫的 C 語言都是長這樣:

1
2
3
4
5
6
main()
{
statement_1;
statement_2;
statement_3;
}

沒意外的話,整個程式就會 123, 123, 123,… 無限循環的執行,因為結束之後系統會自動 Reset,程式重新來過。每個地方停留的時間完全取決於 CPU 全速衝刺的速度有多快。

有可能今天的程式是這樣:

1
2
3
4
5
6
7
8
9
main()
{
if(看看手機,是否有新訊息)
{
statement_1; //手機解鎖
}
statement_2;
statement_3;
}

那CPU每次都要去查看手機是否有新訊息?,有才執行 statement_1,這種方式叫做輪詢(Polling)。因為每次都要問,很沒有效率,如果你每毫秒都拿手機起來看,看有沒有簡訊?有沒有未接來電?有沒有 FB 訊息?這樣不是很沒效率嗎?你也不用上班、不用睡覺了,一直看手機就好了,這樣是多浪費生命,多沒意義的事啊。

通常 8051 的入門課程會教大家這樣做:

1
2
3
4
5
6
7
8
9
10
main()
{
delay1ms(1000); //先延遲一秒
if(看看手機,是否有新訊息)
{
statement_1; //手機解鎖
}
statement_2;
statement_3;
}

在delay1ms( );的過程中,CPU 還是全速的在衝刺,只是一些無意義的運算去消耗 CPU 時間而已。這樣雖然你就不用持續盯著手機,一秒鐘才看一次,但還是會衍生其他問題

  1. statement_2 與 3 可能是很忙碌的運算,雖然沒有即時處理的需求,但最好能全速衝刺,例如浮點運算或是和女朋友XX。可是這種寫法,後面的程式全部都會被延遲1秒才執行(此處是自動 Reset 的無限迴圈,所以不管寫在前面或後面,所有的程式都會被延遲 1 秒才執行)。如果你一秒鐘才X一次,每次X一下之前還要檢查手機有沒有新訊息(輪詢的行為),你能不被踢下床嗎?

  2. 你的大腦在 delay1ms(1000)的過程中,並不是真的 delay,還是一樣全速運轉,但想的都是些沒營養的事情像是 SOD,這樣不是太浪費人生了嗎?

這時候如果把程式改成這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
//宣告:當鈴聲響起時,執行 interrupt 0 函式
//同時凍結 main() 的狀態

main()
{
statement_2;
statement_3;
}

void ISR_int0(void) interrupt 0
{
statement_1; //手機解鎖
}

這樣的話,我們就可以不斷地在 main() 全速衝刺!當鈴聲響起時,main() 會暫停,CPU 就不會照著原先的順序執行,先跑去執行 ISR_int0(),做完之後再從 main()暫停的地方繼續往下執行,這種機制就叫做「中斷」,因為 main() 被中斷了。雖然必須把大部分的時間放在和女朋友XX,但是有些事情…

  • 外部觸發(INT):更重要,不馬上處理不行,否則後果可能很嚴重(例如她老爸敲門)
  • 定時要做(Timer):交作業 deadline 到了,不交會被當
  • 溢位(Overflow):滿出來了要趕快清理(8051 好像只有 Timer 暫存器會因溢位而中斷)

以上這幾件事情都有時效性,很緊急,要趕快處理!
但是中斷的同時可能又有中斷!你能想像她老爸敲門的同時,助教又打電話來催交作業嗎?這時候就是蠟燭兩頭燒!所以中斷函式要盡量減短,盡早結束

中斷的觀念解釋完了,至於中斷正確的設定方式,隨每家MCU的不同而不同,8051 based 的基本上都差不多,AT89S5x 則與標準型 8051 完全相同,這部分就請看自己的課本吧!

本文最后更新于 天前,文中所描述的信息可能已发生改变