<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 關(guān)于單片機的using使用

關(guān)于單片機的using使用

作者: 時(shí)間:2016-11-09 來(lái)源:網(wǎng)絡(luò ) 收藏
C51的中斷函數的格式為:void FuncIr(void) interrupt x [using y]
以下是夢(mèng)游的一些分析:
一、中斷函數是一個(gè)特殊的函數,沒(méi)有參數,也沒(méi)有返回值;但是程序中允不允許使用return呢?答案是允許的,不過(guò)只能用"return;",不能用"return(z);";用在一些需要快速返回的地方,對應的匯編會(huì )有多個(gè)ret語(yǔ)句,相對效率會(huì )高一些。
二、using的用法,using可以修飾任何函數,不過(guò)個(gè)人建議只用來(lái)修飾中斷函數;簡(jiǎn)單的說(shuō),“using”會(huì )指定工作寄存器組,由于中斷函數一般都是比較緊急的事情,有時(shí)一條語(yǔ)句都會(huì )斤斤計較,所以使用using切換寄存器組可以省去一些壓棧的動(dòng)作,由于51只有兩級中斷,同級中斷不能被打斷,因此,我們可以同級中斷設成同樣的寄存器組,從某種意義上來(lái)說(shuō),有一組寄存器是多余的。同時(shí)個(gè)人建議中斷函數應該使用using這個(gè)關(guān)鍵字。
三、中斷中調用函數,首先要討論中斷函數中調用函數的必要性,前天在論壇上我和別人爭論過(guò)這個(gè)問(wèn)題,現在我還是這個(gè)觀(guān)點(diǎn):有些情況中斷中調用函數還是必要的,這個(gè)時(shí)候是不是該調用函數,其實(shí)和普通函數差不多,首先是這個(gè)函數如果調用多次,或者要帶一些參數什么的就更加必要的;前天有人跟我叫勁,說(shuō)假如只調用一次且無(wú)參數無(wú)返回的函數要直接寫(xiě),因為如果用函數,至少會(huì )增加CALL和RET兩條語(yǔ)句,我不敢茍同,我是實(shí)際調試發(fā)現的,當你程序比較復雜時(shí),你將那部單獨拉出來(lái)做成函數,可能代碼和時(shí)間都會(huì )更好。
四、中斷中調用的函數最好不要被中斷外的其它函數調用,因為會(huì )出現“重復調用”的警告,有時(shí)這種調用是很致命的,有人說(shuō)這個(gè)函數可以用reentrant來(lái)修飾,是的,的確可以這樣解決,不過(guò)個(gè)人不建議這么做,也許這樣會(huì )跟你減少很多堆??臻g,并且整個(gè)程序的優(yōu)化要差很多,個(gè)人建議出現這種情況就把這個(gè)函數寫(xiě)兩遍,分成兩個(gè)函數分別調用。
五、中斷調用了函數,會(huì )出現一些莫名其妙的問(wèn)題,一些數據不對(我現在遇到這個(gè)問(wèn)題)其實(shí)一般是因為匯編中使用了絕對寄存器引起的,有人說(shuō)中斷函數使用那個(gè)寄存器組,被中斷調用的函數就使用哪個(gè)寄存器組(我認為好參考C51.PDF:Functions called from an interrupt procedure must function with the same register bank as the interrupt procedure. When the NOAREGS directive is not explicitly specified, the compiler may generate absolute register accesses using the register bank selected (by the using attribute or by the REGISTERBANK control) for that function. Unpredictable results may occur when a function assumes a register bank other than the one currently selected. Refer to “Register Bank Access” on page 124 for more information.),我認為這樣不好:
這樣會(huì )增加額外的消耗,使用using會(huì )增加一下語(yǔ)句:
PUSH PSW
MOV PSW, #XX
....
POP PSW
更重要的是,使用using的函數不能有返回值(這個(gè)地方有問(wèn)題,應該可以有返回值,下文說(shuō)是不能不能返回bit類(lèi)型的值),這是致命傷(所以這不是致命傷,可以使用using解決這個(gè)問(wèn)題)
個(gè)人推薦的方法有兩種:
1、使用“#pragma NOAREGS”禁止使用絕對寄存器
2、使用“#pragme RB(x)”來(lái)指定本文件的工作寄存器組
六、一般說(shuō)來(lái),要求中斷函數盡可能的短,但也有特殊情況,有些前/后臺的系統中,就會(huì )把很多相對重要的事情放到定時(shí)中斷(這個(gè)定時(shí)中斷類(lèi)似實(shí)時(shí)操作系統中的時(shí)鐘節拍)去做,而且程序很長(cháng)。我單獨提出來(lái)這點(diǎn)是想告訴大家,中斷函數也是一個(gè)函數而已,只要系統有必要,可以做一些看似不合理的事情,該出手時(shí)就出手,就像goto語(yǔ)句一樣。

本文引用地址:http://dyxdggzs.com/article/201611/317705.htm
轉自http://www.ednchina.com/blog/hotchip/,請大家去他的博客中支持他,里面有不錯的文章。括號中是我的理解
關(guān)于using:
舉個(gè)例子來(lái)說(shuō):
定義一個(gè)函數
void func(unsigned char i) {
...
}
有如下一個(gè)中斷函數
void int_0(void) interrupt 0 using 1 {
....
}
在默認狀態(tài)下,func使用寄存器組0(BANK0),那么當int_0調用func時(shí)是否存在當傳遞參數時(shí)會(huì )造成參數傳遞錯誤?
如果在中斷服務(wù)函數ISR中使用寄存器,那么必須處理好using的使用問(wèn)題:
1、中斷服務(wù)函數使用using指定與主函數不同的寄存器組(主函數一般使用Register bank 0)。
2、中斷優(yōu)先級相同的ISR可用using指定相同的寄存器組,但優(yōu)先級不同的ISR必須使用不同的寄存器組,在ISR中被調用的函數也要使用using指定與中斷函數相同的寄存器組。(應該是這樣的)
3、如果不用using指定,在ISR的入口,C51默認選擇寄存器組0,這相當于中斷服務(wù)程序的入口首先執行指令:
MOV PSW #0
這點(diǎn)保證了,沒(méi)使用using指定的高優(yōu)先級中斷??梢灾袛嗍褂貌煌募拇嫫鹘M的低優(yōu)先級中斷。
4、使用using關(guān)鍵字給中斷指定寄存器組,這樣直接切換寄存器組而不必進(jìn)行大量的PUSH和POP操作,可以節省RAM空間,加速MCU執行時(shí)間。寄存器組的切換,總的來(lái)說(shuō)比較容易出錯,要對內存的使用情況有比較清晰的認識,其正確性要由你自己來(lái)保證。特別在程序中有直接地址訪(fǎng)問(wèn)的時(shí)候,一定要小心謹慎!至于“什么時(shí)候要用到寄存器組切換”,一種情況是:當你試圖讓兩個(gè)(或以上)作業(yè)同時(shí)運行,而且它們的現場(chǎng)需要一些隔離的時(shí)候,就會(huì )用上了。在ISR或使用實(shí)時(shí)操作系統RTOS中,寄存器非常有用。
寄存器組使用的原則:
1、8051的最低32個(gè)字節分成4組8寄存器。分別為寄存器R0到R7。寄存器組由PSW的低兩位選擇。在ISR中,MCU可以切換到一個(gè)不同的寄存器組。對寄存器組的訪(fǎng)問(wèn)不可位尋址,C51編譯器規定使用using或禁止中斷的函數(#pragma disable)均不能返回bit類(lèi)型的值。
2、主程序(main函數)使用一組,如bank 0;低中斷優(yōu)先級的所有中斷均使用第二組,如bank 1;高中斷優(yōu)先級的所有中斷均使用再另外一組,如bank 2。顯然,同級別的中斷使用同一組寄存器不會(huì )有問(wèn)題,因為不會(huì )發(fā)生中斷嵌套;而高優(yōu)先級的中斷則要使用與低優(yōu)先級中斷不同的一組,因為有可能出現在低優(yōu)先級中斷中發(fā)生高優(yōu)先級中斷的情況。編譯器會(huì )自動(dòng)判斷何時(shí)可使用絕對寄存器存取。
3、在ISR中調用其它函數,必須和中斷使用相同的寄存器組。當沒(méi)用NOAREGS命令做明確的聲明,編譯器將使用絕對寄存器尋址方式訪(fǎng)問(wèn)函數選定(即用using或REGISTERBANK指定)的寄存器組,當函數假定的和實(shí)際所選的寄存器組不同時(shí),將產(chǎn)生不可預知的結果,從而可能出現參數傳遞錯誤,返回值可能會(huì )在錯誤的寄存器組中。
舉一例子:當需要在中斷內和中斷外調用同一個(gè)函數,假定按照程序的流程控制,不會(huì )出現函數的遞歸調用現象,這樣的調用會(huì )不會(huì )出現問(wèn)題?若確定不會(huì )發(fā)生重入情況,則有以下兩種情況:
1、如果ISR和主程序使用同一寄存器組(主程序缺省使用BANK 0,若ISR沒(méi)有使用using為其指定寄存器區,則缺省也使用BANK 0),則不需其他設置。
2、如果ISR和主程序使用不同的寄存器組(主程序缺省使用BANK 0,ISR使用using指定了其他BANK),則被調用函數必須放在:
#pragma NOAREGS
#pragma AREGS
控制參數對中,指定編譯器不要對該函數使用絕對寄存器尋址方式;或者也可在Options->C51,選中“Dont use absolute register accesses”,使所有代碼均不使用絕對寄存器尋址方式(這樣,執行效率將稍有降低)。不論以上的哪一種情況,編譯器均會(huì )給出重入警告,需手工更改OVERLAY參數,做重入說(shuō)明。
3、還有一種辦法:如果被調用函數的代碼不是很長(cháng),還是將該函數復制一份,用不同的函數名代替,這種情況適合ROM有足夠多余的空間。
因此,對using關(guān)鍵字的使用,如果沒(méi)把握,寧可不用,交給編譯系統自己去處理好了。

例子

用上using可以精簡(jiǎn)代碼,節省堆棧,不過(guò)有時(shí)會(huì )出現一個(gè)問(wèn)題:
用上using ,在中斷服務(wù)程序里調用函數要小心一點(diǎn),因為keil C有時(shí)會(huì )產(chǎn)生依賴(lài)絕對地址的代碼,例如如下函數,功能是從片外的存儲設備中讀取一個(gè)字節:
uchar ReadByte(uchar address)
{
retrun PBYTE[address];
}
會(huì )被編譯成如下代碼:
MOVR0,0x07
MOVXA,@R0
MOVR7,A
這時(shí),如果在中斷服務(wù)程序里調用 ReadByte(0xAA); 就會(huì )發(fā)現讀出的數據根本不對,因為using 1使得中斷服務(wù)程序在調用函數時(shí)使用第一組寄存器傳遞參數,編譯器生成的代碼如下:
MOVR7,#0xAA
LCALLReadByte
而ReadByte這個(gè)函數的代碼是使用絕對地址為0x07的第0組寄存器的R7來(lái)傳遞參數的,所以會(huì )出問(wèn)題。
解決方法是在定義ReadByte這個(gè)函數的前面加上"#pragma noaregs",這樣編譯器就會(huì )生成不依賴(lài)于絕對地址的代碼了,函數ReadByte被編譯生成的代碼如下:
XCHA,R0
MOVA,R7
XCHA,R0
MOVXA,@R0
MOVR7,A
這樣就可以大膽的使用using了,使用using才是充分利用51架構的使用方法。



關(guān)鍵詞: 單片機usin

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>