時鐘中斷

時鐘中斷

在單片機程序設計中,設置一個好的時鐘中斷,將能使一個CPU發揮兩個CPU的功效,大大方便和簡化程序的編製,提高系統的效率與可操作性。可以把一些例行的及需要定時執行的程序放在時鐘中斷中,還可以利用時鐘中斷協助主程序完成定時、延時等操作。

電路


一種時鐘中斷檢測電路,包括:對輸入時鐘以不同分度值進行分頻並輸出多個分頻時鐘的分頻器電路;對輸入時鐘和多個分頻時鐘進行“與”操作的“與”電路;將具有最大分度值的分頻時鐘反相的反相器;對輸入時鐘中其餘分頻時鐘和反相器輸出進行“與”操作的“與”電路;第一和第二開關,具有被提供以各個“與”電路輸出的控制端,控制第一和第二電容器放電路徑的開/關;第一和第二波形形成緩衝器電路,被提供以第一和第二電容器的端電壓;根據延遲電路中使反相器輸出延遲預定時間長度所得的選擇控制信號選擇第一和第二波形形成緩衝器電路的一個輸出的選擇電路。其通過單輸入時鐘系統使時鐘中斷能被檢測,集成更容易,並使時鐘中斷時間能精確地檢測。

舉例


定時器初值與中斷周期 時鐘中斷無需過於頻繁,一般取20mS(50Hz)即可。如需要百分之一秒的時基信號,可取10mS(100Hz)。這裡取20mS,用定時器T0工作於16位定時器方式(方式1)。T0的工作方式為:每過一個機器周期自動加1,當計滿0FFFFh,要溢出時,便會產生中斷,並由硬體設置相應的標誌位供軟體查詢。即中斷時比啟動時經過了N+1個機器周期。所以,我們只要在T0中預先存入一個比滿值0FFFFh小N的數,然後啟動定時器,便會在N個機器周期后產生中斷。這個值便是所謂的“初值”。下面計算我們需要的初值:時鐘為6MHz,12個時鐘周期為一個機器周期,20mS中有10000個機器周期。(10000)10=(2710)16,則0FFFFh-2710h+1=0D8F0h。由於響應中斷、保護現場及重裝初值還需要7~8個機器周期,把這個值再加上7,即T0應裝入的初值是0D8F7h。每次中斷進入后,先把A及PSW的值壓入堆棧,然後即把0D8F7h裝入T0。
設置一個單元,每次中斷加1 我們可以取內部RAM中一個單元,取名為INCPI(Increase Per Interrupt),在中斷中,裝完T0初值后,用INC INCPI指令將其加一。從這個單元中,無論中斷程序還是主程序,都可以從中獲得20mS的1~256之間任意整數倍的信號。例如:有一段向數碼管送顯的程序,需要每0.5秒執行一次以便刷新顯示器,便可以設一單元(稱為等待單元)W_DISP,用/MOV A,INCPI/ADD A,#25/MOV W_DISP,A/語句讓其比當前的INCPI值大25,然後在每次中斷中檢查是否於INCPI值相等。若相等,說明已過了25個中斷周期,便執行送顯程序,並且讓W_DISP再加上25,等待下個0.5秒。我們可以設置多個等待單元,以便取出多個不同的時基信號。讓中斷程序在每次中斷時依次查詢各個等待單元是否與INCPI相等,若相等,則執行相應的處理,並重新設置該等待單元的值,否則跳過。例如:用0.5秒信號刷新或閃爍顯示器,用1秒信號產生實時時鐘,或輸出一定頻率的方波,以一定間隔查詢輸入設備等。
在中斷中讀鍵 通常,我們在主程序中讀鍵盤,步驟為:掃描鍵盤,若有鍵按下,則延時幾十毫秒去抖動,再次確認此鍵確實按下,然後處理該鍵對應的工作,完成後再次重上述步驟。但這有兩點不足:1.處理相應工作時無法鎖存按鍵的輸入,即可能漏鍵。2.延時去抖時CPU無法做其它事情,效率不高。如果把讀鍵放入時鐘中斷中,則可避免上述不足。方法為:如果兩次相鄰的中斷中都讀到同一個鍵按下,則這個鍵是有效的(達到了去抖目的),並將其鎖存到先入先出(隊列)的鍵盤緩衝區,等主程序來處理。這樣,主程序處理按鍵的同時,仍可響應鍵盤的輸入。緩衝區深度通常可設為8級,若鎖存的鍵數多於8個,則忽略新的按鍵,並報警提示用戶新的按鍵將無效。若鍵盤緩衝隊列停滯的時間大大長於主程序處理按鍵所需要的最大時間,說明主程序已出錯或跑飛,可以在中斷用指令將系統複位,起到了看門狗的目的。
主程序中的延時 由於有常開的時鐘中斷,所以當主程序中有需要時間較短、精度較高的延時時,應暫時把時鐘中斷關閉。而程序中需要時間較長、精度不高的延時時,便可仿照下需的寫法,避免多層嵌套的循環延時。
例:在P1.1輸出1秒的高電平脈衝
MOV A,INCPI
INC A
CJNE A,INCPI$ ;等待一次中斷處理完成
SETB P1.1 ;設P1.1為H,脈衝開始
ADD A,#50 ;50個20mS為1秒
CJNE A,INCPI,$ ;等中斷將INCPI加一50次
CLR P1.1 ;設P1.1為L,脈衝結束
下面用MCS-51為例:
MCS-51的中斷響應過程:
1、中斷響應的條件:講到這兒,我們依然對於計算機響應中斷感到神奇,我們人可以響應外界的事件,是因為我們有多種“感測器“――眼、耳可以接受不同的信息,計算機是如何做到這點的呢?其實說穿了,一點都不希奇,MCS51工作時,在每個機器周期中都會去查詢一下各個中斷標記,看他們是否是“1“,如果是1,就說明有中斷請求了,所以所謂中斷,其實也是查詢,不過是每個周期都查一下而已。這要換成人來說,就相當於你在看書的時候,每一秒鐘都會抬起頭來看一看,查問一下,是不是有人按門鈴,是否有電話。。。。很蠢,不是嗎?可計算機本來就是這樣,它根本沒人聰明。
了解了上述中斷的過程,就不難解中斷響應的條件了。在下列三種情況之一時,CPU將封鎖對中斷的響應:
CPU正在處理一個同級或更高級別的中斷請求。現行的機器周期不是當前正執行指令的最後一個周期。我們知道,單片機有單周期、雙周期、三周期指令,當前執行指令是單位元組沒有關係,如果是雙位元組或四位元組的,就要等整條指令都執行完了,才能響應中斷(因為中斷查詢是在每個機器周期都可能查到的)。
當前正執行的指令是返回批令(RETI)或訪問IP、IE寄存器的指令,則CPU至少再執行一條指令才應中斷。這些都是與中斷有關的,如果正訪問IP、IE則可能會開、關中斷或改變中斷的優先順序,而中斷返回指令則說明本次中斷還沒有處理完,所以都要等本指令處理結束,再執行一條指令才可以響應中斷。
2、中斷響應過程
CPU響應中斷時,首先把當前指令的下一條指令(就是中斷返回后將要執行的指令)的地址送入堆棧,然後根據中斷標記,將相應的中斷入口地址送入PC,PC是程序指針,CPU取指令就根據PC中的值,PC中是什麼值,就會到什麼地方去取指令,所以程序就會轉到中斷入口處繼續執行。這些工作都是由硬體來完成的,不必我們去考慮。這裡還有個問題,大家是否注意到,每個中斷向量地址只間隔了8個單元,如0003-000B,在如此少的空間中如何完成中斷程序呢?很簡單,你在中斷處安排一個LJMP指令,不就可以把中斷程序跳轉到任何地方了嗎?
一個完整的主程序看起來應該是這樣的:
ORG 0000H
LJMP START
ORG 0003H
LJMP INT0 ;轉外中斷0
ORG 000BH
RETI ;沒有用定時器0中斷,在此放一條RETI,萬一“不小心“產生了中斷,也不會有太大的後果。
中斷程序完成後,一定要執行一條RETI指令,執行這條指令后,CPU將會把堆棧中保存著的地址取出,送回PC,那麼程序就會從主程序的中斷處繼續往下執行了。注意:CPU所做的保護工作是很有限的,只保護了一個地址,而其它的所有東西都不保護,所以如果你在主程序中用到了如A、PSW等,在中斷程序中又要用它們,還要保證回到主程序后這裡面的數據還是沒執行中斷以前的數據,就得自己保護起來。

評價


從上看出,要靈活地應用時鐘中斷,將任務合理分配給中斷和主程序,並且二者要分工明確,介面簡單。這其中的技巧還需要大家在實踐中多多摸索與體會。另外要注意:應盡量縮短中斷處理程序的執行時間,更不要長於20mS。