關於C51的中斷函數要注意的幾個問題

關於C51的中斷函數要注意的幾個問題(高手繞行)

    最近在蝦潭逛,發現一些小蝦米對C51中斷函數有些不瞭解,今天週末,抽空發個技術帖子,希望對小蝦米有所幫助,如

有錯誤之處,還請指正,就當拋磚引玉吧!

    C51的中斷函數的格式爲:

    void FuncIr(void) interrupt x [using y]

    以下是夢遊的一些分析:

    一、中斷函數是一個特殊的函數,沒有參數,也沒有返回值;但是程序中允不允許使用return呢?答案是允許的,不過

只能用"return;",不能用"return(z);";用在一些需要快速返回的地方,對應的彙編會有多個ret語句,相對效率會高一

些。

    二、using的用法,using可以修飾任何函數,不過個人建議只用來修飾中斷函數;簡單的說,“using”會指定工作寄存

器組,由於中斷函數一般都是比較緊急的事情,有時一條語句都會斤斤計較,所以使用using切換寄存器組可以省去一些壓棧

的動作,由於51只有兩級中斷,同級中斷不能被打斷,因此,我們可以同級中斷設成同樣的寄存器組,從某種意義上來說,

有一組寄存器是多餘的。同時個人建議中斷函數應該使用using這個關鍵字。

    三、中斷中調用函數,首先要討論中斷函數中調用函數的必要性,前天在論壇上我和別人爭論過這個問題,現在我還是

這個觀點:有些情況中斷中調用函數還是必要的,這個時候是不是該調用函數,其實和普通函數差不多,首先是這個函數如

果調用多次,或者要帶一些參數什麼的就更加必要的;前天有人跟我叫勁,說假如只調用一次且無參數無返回的函數要直接

寫,因爲如果用函數,至少會增加CALL和RET兩條語句,我不敢苟同,我是實際調試發現的,當你程序比較複雜時,你將那部

分單獨拉出來做成函數,可能代碼和時間都會更好

    四、中斷中調用的函數最好不要被中斷外的其它函數調用,因爲會出現“重複調用”的警告,有時這種調用是很致命

的,有人說這個函數可以用reentrant來修飾,是的,的確可以這樣解決,不過個人不建議這麼做,也許這樣會跟你減少很多

堆棧空間,並且整個程序的優化要差很多,個人建議出現這種情況就把這個函數寫兩遍,分成兩個函數分別調用。

    五,中斷調用了函數,會出現一些莫名其妙的問題,一些數據不對。其實一般是因爲彙編中使用了絕對寄存器引起的,有人說中斷函數使用那個寄存器組,被中斷調用的

函數就使用哪個寄存器組,我認爲這樣不好:

    這樣會增加額外的消耗,使用using會增加一下語句:

    PUSH PSW

    MOV PSW, #XX

    ....

    POP PSW

   更重要的是,使用using的函數不能有返回值,這是致命傷

   個人推薦的方法有兩種:

   1、使用“#pragma NOAREGS”禁止使用絕對寄存器

   2、使用“#pragme RB(x)”來指定本文件的工作寄存器組

   六、一般說來,要求中斷函數儘可能的短,但也有特殊情況,有些前/後臺的系統中,就會把很多相對重要的事情放到定

時中斷(這個定時中斷類似實時操作系統中的時鐘節拍)去做,而且程序很長。我單獨提出來這點是想告訴大家,中斷函數

也是一個函數而已,只要系統有必要,可以做一些看似不合理的事情,該出手時就出手,就像goto語句一樣。

51單片機的中斷函數

中斷使用interrupt 關鍵字和中斷編號0-4來實現:

返回值 函數名 interrupt n

n對應中斷源的編號,中斷編號告訴中斷器中斷程序的入口地址,它對應着IE寄存器中的使能位,即IE寄存器中的0位對應着外部中斷0。

8051單片機的中斷源以及終端編號如下:

中斷編號   中斷源                             入口地址

 0            外部中斷0                          0003H 

1             定時器/計數器0 溢出         000BH 

2             外部中斷1                           0013H 

3             定時器/計數器1 溢出         001BH 

4              串行口中斷                  0023H

在51系列單片機中,有的單片機多達32箇中斷源,所以中斷編號是0-31.

當正在執行一個特定的任務時,可能有更緊急的事情需要CPU處理,這就涉及到了中斷優先級。高優先級中斷可以中斷正在處理的低優先級中斷程序,因而最好給每種優先級程序分配不同的寄存器組。在C51中可使用using指定寄存器組,using後的變量爲0-3的常整數,分別表示51單片機內的4哥寄存器組。中斷函數的完整語法如下:

返回值 函數名([參數])[模式][重入]interrupt n[usingn]

unsigned int interruptcnt;

unsigned char second;

void timer0(void) interrupt 1 using 2

if(++interruptcnt==4000) // 計數到4000

second++; //另一個計數器

interruptcnt=0; //計數器清零

發佈了7 篇原創文章 · 獲贊 10 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章