單片機中斷應用的C語言編程
C51編譯器支持在C源程序中直接開發中斷程序,從而減輕了采用匯編語言編寫中斷服務程序的繁瑣程度。為了滿足在C語言源程序中直接編寫中斷服務程序的需要,C51編譯器對函數的定義進行了擴展,增加了一個擴展關鍵詞interrupt。他是函數定義式的一個選項,加上這個選項即可以將一個函數定義成中斷服務函數。定義中斷服務函數的語法格式如下:
返回值類型 函數名( )interrupt m [using n]<?XML:NAMESPACE PREFIX = O />
{
函數體
}
關鍵詞interrupt后面的m是中斷號,m的取值為0~31的正整數,編譯器從8m+3處產生中斷向量,具體的中斷號m和中斷向量取決于80C51,80C51中斷源編號見表。80C51單片機可以在片內RAM中使用4個不同的工作寄存器組,每個寄存器組中包含8個寄存器(R0~R7)。C51編譯器擴展了一個關鍵字using,專門用來選擇不同的工作寄存器組。using
表 80C51單片機中斷源編號
編號 | 中斷源 | 入口地址 | 編號 | 中斷源 | 入口地址 |
0 | 外部中斷0 | 0003H | 3 | 定時/計數器1 | 001BH |
1 | 定時/計數器0 | 000BH | 4 | 串行口中斷 | 0023H |
2 | 外部中斷1 | 0013H | | | |
后面的n是一個0~3的常整數,分別選中4個不同的工作寄存器組。在定義一個函數時,using是一個選項,如果不用該選項,則由編譯器自動選擇一個寄存器組訪問。需要注意的是,關鍵字using和interrupt的后面都不允許跟帶運算符的表達式。
關鍵字using對函數目標代碼的影響如下:
在函數的入口處將當前工作寄存器組保護到堆棧中,指定的工作寄存器內容不會改變;函數退出之前將被保護的工作寄存器組從堆棧中恢復。
使用關鍵字using在函數中確定一個工作寄存器組時必須小心,要保證任何寄存器組的切換都在控制之下,否則將產生不確定的函數結果。另外還要注意,帶using屬性的函數原則上不能返回bit類型的值,并且關鍵字using不允許用于外部函數。
關鍵字interrupt也不允許用于外部函數,它對中斷函數目標代碼的影響如下:
在進入中斷函數時,特殊功能寄存器ACC、B、DPH、DPL、PSW將被保存入棧,如果不使用using進行工作寄存器組的切換,則將中斷函數中所用到的全部工作寄存器都入棧保護,在函數退出之前恢復,中斷函數由RETI指令結束。
編寫80C51單片機中斷函數時應遵循以下原則:
①中斷函數不能進行參數傳遞,如果中斷函數中包含任何參數聲明,都將導致編譯出錯。
②中斷函數沒有返回值,如果企圖定義一個返回值,將得到不正確的結果。因此建議在定義中斷函數時將其定義為void類型,以明確說明沒有返回值。
③在任何情況下,都不能直接調用中斷函數,否則會產生編譯錯誤。因為中斷函數的退出是由80C51單片機指令RETI完成的,RETI指令影響80C51單片機硬件中斷系統。如果在沒有實際中斷請求的情況下直接調用中斷函數,則RETI指令的操作結果會產生一個致命的錯誤。
④如果在中斷函數中調用了其他函數,則被調用函數所使用的寄存器組必須與中斷函數相同。用戶必須保證按要求使用相同的寄存器組,否則會產生不正確的結果,這一點必須注意。如果定義中斷函數時沒有使用using選項,則由編譯器自動選擇一個寄存器組。另外,由于中斷的產生不可預測,中斷函數對其他函數的調用可能形成遞歸調用,需要時可將被中斷函數所調用的其他函數定義成再入函數。
⑤C51編譯器從絕對地址8m+3處產生一個中斷向量,其中m為中斷號。該向量包含一個到中斷函數入口地址的絕對跳轉。
下面給出一個中斷編程實例。
例 用C語言編寫例6-4的程序
分析:假設中斷源A、B、C、D都沒有中斷,皆為高電平;若有一個產生中斷,通過四或門在INT1引腳產生低電平,因為在主程序中已開放了中斷,所以就會執行中斷服務程序把flag設置為1,主程序判斷flag=1,就會根據P1的低位來判斷哪一位為低,即哪一個中斷源產生中斷。
C51參考程序如下:


編輯:admin 最后修改時間:2018-05-08


