PIC16F87X單片機中斷系統(tǒng)應用須關(guān)注的問題
在圖2中,第1行是系統(tǒng)時鐘脈沖信號,每4個時鐘周期對應1個指令周期。第2行就是指令周期信號。該信號只有在RC 振蕩模式下,從OSC2腳上可以向片外送出。第3行是單片機外部引腳INT送入的中斷脈沖信號。外部中斷信號INT是用邊沿觸發(fā)的。假設預先設定的是 INT中斷信號上升沿有效的話,則該信號的上升沿將會在1個時鐘周期后引發(fā)中斷標志位INTF被置位。第4行代表INTF信號。每個指令周期內(nèi)的第2個時鐘脈沖上升沿時,該信號被抽檢1次。一旦檢測到INTF信號被設置為“1”,則CPU會在接下來的1個指令周期內(nèi),將全局中斷屏蔽位GIE清零。第5行是全局中斷屏蔽位GIE。在GIE信號被清零的下一個指令周期內(nèi),程序計數(shù)器PC被置入中斷向量0004H,見圖2中第6行。同時在該指令周期內(nèi)完成到中斷服務程序的跳轉(zhuǎn),并且實現(xiàn)提取該子程序的首條指令,即指令(0004H),見圖2中第7行。在其后的1個指令周期內(nèi),正式開始執(zhí)行中斷服務程序的第1條指令,見圖2中第8行。自INT引腳輸入有效信號,到中斷服務程序的第1條指令得到執(zhí)行,大約需要3~4個指令周期的延時。更精確的延遲時間取決于中斷事件的發(fā)生時機。
以上描述的只是1次中斷從申請到得到CPU的響應的延遲時間。下面分析從CPU響應1次中斷到該中斷得到有效處理的延遲時間。由于具有中斷功能的PIC系列單片機(低檔產(chǎn)品PIC16C5X和PIC12C5X系列不具備中斷功能),采用的是“多源中斷”的設計方案(即1個中斷向量對應著多個中斷源),只有惟一的1個中斷向量,或者說只有1個中斷服務程序入口地址。這就意味著,此類單片機的中斷服務程序只能編寫1個。這類單片機的硬件結(jié)構(gòu)得到了簡化,那么,相應的軟件設計上就得多開銷一些。在1個中斷服務程序中,若想對多個中斷源作出處理,就必須在進入中斷服務程序后,首先執(zhí)行調(diào)查具體中斷源的一條或多條指令,其后才能對查到的中斷源作出有針對性的服務。如此以來,就形成了1次中斷從CPU響應到進入針對性處理的延遲時間。該時間有長有短,它會隨著被開放的中斷源的個數(shù)的增加而增加。最好情況是只有1個中斷源被開放,這時不需要檢測中斷源就可以立即進入針對性處理;最壞情況是所有中斷源全部開放,此時用在檢測中斷源上的時間會最長。
另外,PIC單片機中采用的是硬件堆棧結(jié)構(gòu)。其好處是既不占用程序存儲器空間,也不占用數(shù)據(jù)存儲器空間,同時也不需用戶去操作堆棧指針;但此時也帶來1個不可回避的弱點,即不具備像其他單片機指令系統(tǒng)中的壓棧(PUSH)和出棧(POP)指令那樣,實現(xiàn)中斷現(xiàn)場的保護會麻煩一些,并且占用的處理時間也相應多一點。
2 中斷的現(xiàn)場保護問題
中斷現(xiàn)場的保護是中斷技術(shù)中一個很重要的環(huán)節(jié)。在進入中斷服務程序期間,只有返回地址,即程序計數(shù)器PC的值被自動壓入堆棧。若需要保留其他寄存器的內(nèi)容,就得由程序員另想辦法。由于PIC單片機的指令系統(tǒng)中沒有像其他單片機那樣的PUSH(入棧)和POP(出棧)之類的指令,所以要用1段用戶程序來實現(xiàn)類似的功能。因為是用1段程序來實現(xiàn)現(xiàn)場保護,而程序的執(zhí)行有可能會影響到W寄存器和STATUS寄存器,所以,首先應該把這2個寄存器保護起來,然后再去保存其他用戶認為有必要保護的寄存器。并且在PIC單片機中,中斷現(xiàn)場數(shù)據(jù)不是保留到芯片的堆棧存儲區(qū)中,而是保留在用戶自己選擇的一些文件寄存器(即RAM數(shù)據(jù)存儲器單元)中,當然一般應該選擇通用寄存器來保護現(xiàn)場。下面給出的是1段原廠家最新提供的實現(xiàn)保護中斷現(xiàn)場的范例程序片段。
?。粚、STATUS和PCLATH寄存器的內(nèi)容保存到臨時備份寄存器中
?。?]MOVWFW_TEMP ;復制W到它的臨時備份寄存器W_TEMP中
[2]SWAPFSTATUS,W ;將STATUS寄存器高低半字節(jié)交換后放入W
[3]CLRFSTATUS ;不管當前處在哪個體,都設置體0作當前體
?。?]MOVWFSTATUS_TEMP ;保存STATUS到體0上的臨時寄存器STATUS_TEMP
[5]MOVF PCLATH, W ;把寄存器PCLATH內(nèi)容復制到W中
?。?]MOVWFPCLATH_TEMP ;經(jīng)W將PCLATH內(nèi)容轉(zhuǎn)到臨時寄存器PCLATH_TEMP
?。?]CLRFPCLATH ;不管當前處在哪頁,都把PCLATH設置成指向頁0 (中斷服務程序的核心部分)
?。?]MOVFPCLATH_TEMP, W ;經(jīng)過W轉(zhuǎn)移
?。?]MOVWFPCLATH ;恢復PCLATH內(nèi)容
?。?0]SWAPFSTATUS_TEMP,W ;將STATUS_TEMP寄存器高低半字節(jié)交換后放入W
?。?1]MOVWFSTATUS ;把W內(nèi)容移動到STATUS寄存器,(同時也把當前體恢復到原先的體上)
?。?2]SWAPFW_TEMP,F ;將W_TEMP內(nèi)容高低半字節(jié)交換后放回
?。?3]SWAPFW_TEMP,W ;再次將W_TEMP內(nèi)容高低半字節(jié)交換后放入W
這段程序適用于PIC16CXX系列中各款型號的單片機。在這段例程之前,假設預先對于待保留的各個寄存器都分別定義了相應的臨時備份寄存器。用后綴 “_TEMP”表示臨時備份寄存器,例如“W”的臨時備份寄存器記為“W_TEMP”。對于這些臨時備份寄存器究竟需要定義多少個,定義在通用寄存器區(qū)域中的哪個位置,都是值得考究的問題。并且單片機的型號不同,其內(nèi)部的通用寄存器區(qū)域的分布也不同,因此這就使得臨時備份寄存器定義的數(shù)量和位置也不能相同。
例如,對于PIC16F873/874來說,要求寄存器W_TEMP必須在文件寄存器(即RAM數(shù)據(jù)存儲器)的體0和體1上各定義1 個,并且這2個W_TEMP寄存器單元必須具有相同的體內(nèi)地址碼(比如,在體0上把W_TEMP定義在20H單元,則在體1上就把另一個W_TEMP定義在A0H單元);而其他寄存器的臨時備份寄存器(如STATUS_TEMP和PCLATH_TEMP)都僅僅需要在體0上定義1個即可。
又例如,對于PIC16F87X子系列中的其他5款型號來說,情況有所不同。其文件寄存器各個體的頂端部分有16個地址空間,都會尋址到相同的16個物理單元上。這16個單元不需要體選尋址,或者說,尋址這16個單元與體選碼無關(guān),即與當前所處的體無關(guān)。因此,將各個臨時備份寄存器都安排在這個位置(W_TEMP也只需要定義1個即可)最為合適。這樣做可以使得現(xiàn)場保護和現(xiàn)場恢復變得非常容易。中斷是一種隨機發(fā)生的事件。進入中斷服務程序后,第1個要保存的應該是工作寄存器W。原因是PIC單片機沒有在“不同寄存器”之間進行直接傳遞的指令,這樣的功能得用W作中轉(zhuǎn)(需要2條指令)才能實現(xiàn),所以應該先把W寄存器騰空(對應程序中第1條指令)。急于騰空W寄存器,又不能破壞當前狀態(tài)寄存器 STATUS中的體選碼,還不能影響當前狀態(tài)寄存器STATUS內(nèi)的標志位,可又無法確定主程序所處的RAM數(shù)據(jù)存儲器當前體是哪一個,就只好在主程序所有可能選擇到的每一個RAM數(shù)據(jù)存儲器體上的相同位置,都定義1個W_TEMP臨時備份寄存器。
一旦把工作寄存器W騰空后,緊接著就應將狀態(tài)寄存器STATUS的內(nèi)容轉(zhuǎn)移到W中。完成這一操作的指令也不能影響到STATUS寄存器內(nèi)部原有的標志位,原因是STATUS寄存器的內(nèi)容在此之前還沒有安全地保護起來。經(jīng)過仔細分析得知,PIC16系列單片機的指令系統(tǒng)中有3條“MOV”傳送指令。但是,只有1條“MOVF f,W”是以RAM單元為源寄存器,以W為目標寄存器的;而這條指令的操作過程又偏偏會影響“Z”標志位。因此,該指令就不能使用了,只好用1條既有高、低半字節(jié)交換功能又有傳遞功能的“SWAPFSTATUS,W”來勉強頂替(對應程序中第2條指令)。不過在此只利用它的傳遞功能,其交換功能帶來的多余操作還得記下來,等到工作完成之后還得把它倒換回來。
STATUS寄存器的內(nèi)容已經(jīng)保存到W中時,就可以大膽地將其清0了,以便把定義著 STATUS_TEMP和PCLATH_TEMP的體0設置為當前體(對應程序中第3條指令)。經(jīng)過以上幾步特別需要謹慎的操作過后,就可以輕而易舉地將寄存器STATUS和PCLATH的內(nèi)容保存到各自的臨時備份寄存器中了(對應程序中第4~6條指令)。
評論