在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > PIC 單片機(jī) C 語言編程簡介(4)

            PIC 單片機(jī) C 語言編程簡介(4)

            作者: 時間:2016-11-22 來源:網(wǎng)絡(luò) 收藏
            11.9

            C 和匯編混合編程

            本文引用地址:http://www.biyoush.com/article/201611/319598.htm

            有兩個原因決定了用 C 語言進(jìn)行單片機(jī)應(yīng)用程序開發(fā)時使用匯編語句的必要性:單片


            機(jī)的一些特殊指令操作在標(biāo)準(zhǔn)的 C 語言語法中沒有直接對應(yīng)的描述,例如 PIC 單片機(jī)的清

            看門狗指令“clrwdt”和休眠指令“sleep”;單片機(jī)系統(tǒng)強(qiáng)調(diào)的是控制的實(shí)時性,為了實(shí)現(xiàn)這

            一要求,有時必須用匯編指令實(shí)現(xiàn)部分代碼以提高程序運(yùn)行的效率。這樣,一個項(xiàng)目中就會

            出現(xiàn) C 和匯編混合編程的情形,我們在此討論一些混合編程的基本方法和技巧。

            11.9.1 嵌入行內(nèi)匯編的方法

            C 原程序中直接嵌入?yún)R編指令是最直接最容易的方法。如果只需要嵌入少量幾條的

            匯編指令,PICC 提供了一個類似于函數(shù)的語句:

            asm(“clrwdt”);

            雙引號中可以編寫任何一條 PIC 的標(biāo)準(zhǔn)匯編指令。例如:

            for (;;) {

            asm("clrwdt"); //清看門狗

            Task();

            ClockRun();


            asm("sleep");

            asm("nop");

            }


            //休眠

            //空操作延時

            例 11-8 逐行嵌入?yún)R編的方式

            如果需要編寫一段連續(xù)的匯編指令,PICC 支持另外一種語法描述:用“#asm”開始匯

            編指令段,用“#endasm”結(jié)束。例如下面的一段嵌入?yún)R編指令實(shí)現(xiàn)了將 0x20~0x7F 間的

            RAM 全部清零:

            #asm

            movlw 0x20

            movwf _FSR

            clrf _INDF

            incf _FSR,f

            btfss _FSR,7

            goto $-3

            #endasm

            例 11-9 整段嵌入?yún)R編的方式

            11.9.2 匯編指令尋址 C 語言定義的全局變量

            C 語言中定義的全局或靜態(tài)變量尋址是最容易的,因?yàn)檫@些變量的地址已知且固定。按

            C 語言的語法標(biāo)準(zhǔn),所有 C 中定義的符號在編譯后將自動在前面添加一下劃線符“_”,因

            此,若要在匯編指令中尋址 C 語言定義的各類變量,一定要在變量前加上一“_”符號,我

            們在上面例 11-9 中已經(jīng)體現(xiàn)了這一變量引用的法則,因?yàn)?FSR 和 INDF 等所有特殊寄存器

            是以 C 語言語法定義的,因此匯編中需要對其尋址時前面必須添加下劃線。

            對于 C 語言中用戶自定義的全局變量,用行內(nèi)匯編指令尋址時也同樣必須加上“_” ,

            下面的例 11-10 說明了具體的引用方法:

            volatile unsigned char tmp; //定義位于 bank0 的字符型全局變量

            void Test(void)

            {

            #asm

            clrf _STATUS

            movlw 0x10

            movwf _tmp

            #endasm

            if (tmp==0x10) {

            ;

            }

            }

            //測試程序

            //開始行內(nèi)匯編

            //選擇 bank0

            //設(shè)定初值

            //tmp=0x10

            //結(jié)束行內(nèi)匯編

            //開始 C 語言程序


            例 11-10 行內(nèi)匯編尋址 C 全局變量(位于 bank0)

            上面的例子說明了匯編指令中尋址 C 語言所定義變量的基本方法。PICC 在編譯處理嵌

            入的行內(nèi)匯編指令時將會原封不動地把這些指令復(fù)制成最后的機(jī)器碼。所有對 C 編譯器所

            作的優(yōu)化設(shè)定對這些行內(nèi)匯編指令而言將不起任何作用。編程員必須自己負(fù)責(zé)編寫最高效的

            匯編代碼,同時處理變量所在的 bank 設(shè)定。對于定義在其它 bank 中的變量,還必須在匯編

            指令中加以明確指示,見例 11-11 的代碼范例。

            volatile bank1 unsigned char tmpBank1; //定義位于 bank1 的字符型全局變量

            volatile bank2 unsigned char tmpBank2; //定義位于 bank2 的字符型全局變量

            volatile bank3 unsigned char tmpBank3; //定義位于 bank3 的字符型全局變量

            void Test(void)

            {

            #asm

            bcf _STATUS,6

            bsf _STATUS,5

            movlw 0x10

            movwf _tmpBank1^0x80

            bsf _STATUS,6

            bcf _STATUS,5

            movlw 0x20

            //測試程序

            //開始行內(nèi)匯編

            //選擇 bank1

            //設(shè)定初值

            //tmpBank1=0x10

            //選擇 bank2

            //設(shè)定初值


            movwf _tmpBank1^0x100 //tmpBank2=0x20

            bsf _STATUS,6

            bsf _STATUS,5

            movlw 0x30


            //選擇 bank3

            //設(shè)定初值


            movwf _tmpBank1^0x180 //tmpBank1=0x30


            }


            #endasm


            //結(jié)束行內(nèi)匯編

            例 11-11 行內(nèi)匯編尋址 C 全局變量(非 bank0 變量)


            通過上面的代碼實(shí)例,我們可以掌握這樣一個規(guī)律:在行內(nèi)匯編指令中尋址 C 語言定

            義的全局變量時,除了在尋址前設(shè)定正確的 bank 外,在指令描述時還必須在變量上異或

            所在 bank 的起始地址,實(shí)際上位于 bank0 的變量在匯編指令中尋址時也可以這樣理解,只

            是異或的是 0x00,可以省略。如果你了解 PIC 單片機(jī)的匯編指令編碼格式,上面異或的 bank

            起始地址是無法在真正的匯編指令中體現(xiàn)的,其目的純粹是為了告訴 PICC 連接器變量所在

            的 bank,以便連接器進(jìn)行 bank 類別檢查。

            11.9.3 匯編指令尋址 C 函數(shù)的局部變量

            前面已經(jīng)提到,PICC 對自動型局部變量(包括函數(shù)調(diào)用時的入口參數(shù))采用一種“靜

            態(tài)覆蓋”技術(shù)對每一個變量確定一個固定地址(位于 bank0),因此嵌入的匯編指令對其尋

            址時只需采用數(shù)據(jù)寄存器的直接尋址方式即可,唯一要考慮的是如何才能在編寫程序時知道

            這些局部變量的尋址符號(具體地址在最后連接后才能決定,編程時無需關(guān)心)。一個最實(shí)

            用也是最可靠的方法是先編寫一小段 C 代碼,其中有最簡單的局部變量操作指令,然后參

            考圖 11-5(B)對話框選擇“Compile to assembly only”,把此 C 原代碼編譯成對應(yīng)的 PICC 匯

            編指令;查看 C 編譯器生成的匯編指令是如何尋址這些局部變量的,你自己編寫的行內(nèi)匯

            編指令就采用同樣的尋址方式。例如,例 11-12 的一小段 C 原代碼編譯出的匯編指令

            //C 原程序代碼

            void Test(unsigned char inVar1, inVar2)

            {

            unsigned char tmp1, tmp2;

            inVar1++;

            inVar2--;

            tmp1 = 1;

            tmp2 = 2;

            }

            //編譯器生成的匯編指令

            _Test

            ; _tmp1 assigned to ?a_Test+0 //tmp1 的尋址符為 ?a_Test+0


            _Test$tmp1 set


            ?a_Test


            ; _tmp2 assigned to ?a_Test+1 //tmp2 的尋址符為 ?a_Test+1


            _Test$tmp2 set


            ?a_Test+1


            ; _inVar1 assigned to ?a_Test+2 //inVar1 的尋址符為 ?a_Test+2

            _Test$inVar1 set ?a_Test+2

            44line


            ;_inVar1 stored from w

            bcf

            bcf

            movwf ?a_Test+2


            //第一個字符型行參由 W 寄存器傳遞


            ;ht16.c: 43: unsigned char tmp1, tmp2;

            incf

            45line

            ;ht16.c: 45: inVar2--;


            decf

            46line

            ;ht16.c: 46: tmp1 = 1;

            clrf

            incf

            47line

            ;ht16.c: 47: tmp2 = 2;

            movlw 2

            movwf ?a_Test+1

            48line

            ;ht16.c: 48: }

            return


            //行參 inVar2 的尋址符為 ?_Test


            例 11-12 PICC 實(shí)現(xiàn)局部變量操作的尋址方式

            基于上面得到的 PICC 編譯后局部變量的尋址方式,我們在 C 語言程序中用嵌入?yún)R編指

            令時必須采樣同樣的尋址符以實(shí)現(xiàn)對應(yīng)變量的存取操作,見下面的例 11-13。

            //C 原程序代碼

            void Test(unsigned char inVar1, inVar2)

            {

            unsigned char tmp1, tmp2;

            #asm

            //開始嵌入?yún)R編


            incf

            decf

            movlw

            addwf

            rrf

            0x10


            ?a_Test+0,f

            ?a_Test+1,f

            ?a_Test+2,f

            ?_Test,w


            //tmp1++;

            //tmp2--;

            //inVar1 +=

            //inVar2 循環(huán)右移一位

            }


            rrf

            #endasm


            ?_Test,f

            //結(jié)束嵌入?yún)R編


            例 11-13 嵌入?yún)R編指令實(shí)現(xiàn)局部變量尋址操作

            如果局部變量為多字節(jié)形式組成,例如整型數(shù)、長整型等,必須按照 PICC 約定的存儲

            格式進(jìn)行存取。前面已經(jīng)說明了 PICC 采用“Little endian”格式,低字節(jié)放在低地址,高字

            節(jié)放在高地址。下面的例 11-14 實(shí)現(xiàn)了一個整型數(shù)的循環(huán)移位,在 C 語言中沒有直接針對循

            環(huán)移位的語法操作,用標(biāo)準(zhǔn) C 指令實(shí)現(xiàn)的效率較低。

            //16 位整型數(shù)循環(huán)右移若干位

            unsigned int RR_Shift16(unsigned int var, unsigned char count)

            {

            }


            while(count--)

            {

            #asm

            rrf ?_RR_Shift16+0,w

            rrf ?_RR_Shift16+1,f

            rrf ?_RR_Shift16+0,f

            #endasm

            }

            return(var);


            //移位次數(shù)控制

            //開始嵌入?yún)R編

            //最低位送入 C

            //var 高字節(jié)右移 1 位,C 移入最高位

            //var 低字節(jié)右移 1 位

            //結(jié)束嵌入?yún)R編

            //返回結(jié)果


            例 11-14 嵌入?yún)R編指令對多字節(jié)變量的操作

            11.9.4 混合編程的一些經(jīng)驗(yàn)

            C 和匯編語言混合編程可以使單片機(jī)應(yīng)用程序的開發(fā)效率和程序本身的運(yùn)行效率達(dá)到

            最佳的配合。筆者從實(shí)際應(yīng)用中得到一些經(jīng)驗(yàn)供讀者一起分享。

            慎用匯編指令

            相比于匯編語言,用 C 語言編程的優(yōu)勢是毋庸置疑的:開發(fā)效率大大提高、人性化的

            語句指令加上模塊化的程序易于日常管理和維護(hù)、程序在不同平臺間的移植方便。所以既然

            用了 C 語言編程,就盡量避免使用嵌入?yún)R編指令或整個地編寫匯編指令模塊文件。PICC 已

            具備高效的優(yōu)化功能,如果在寫 C 原程序時就十分注意程序的編譯和運(yùn)行效率問題,加上

            PICC 的后道編譯優(yōu)化,最后得到的代碼效率不會比全部用匯編編寫的代碼差多少,尤其是

            程序量較大時。另外,PICC 對數(shù)據(jù)存儲空間的利用率肯定比用戶人工定位變量時的利用率

            要高,同時還提供完整的庫函數(shù)支持。C 語言的語法功能強(qiáng)大,能夠高效率地實(shí)現(xiàn)絕大部分

            控制和運(yùn)算功能。因此,除了一些十分強(qiáng)調(diào)單片機(jī)運(yùn)行時間的代碼或 C 語言沒有直接對應(yīng)

            的操作可以考慮用匯編指令實(shí)現(xiàn)外,其它部分都應(yīng)該用 C 語言編寫。

            以上面的例 11-14 進(jìn)一步說明,變量的循環(huán)右移操作用 C 語言實(shí)現(xiàn)非常不方便,PIC 單

            片機(jī)已有對應(yīng)的移位操作匯編指令,因此用嵌入?yún)R編的形式實(shí)現(xiàn)效率最高。同時對移位次數(shù)

            的控制,本質(zhì)上說變量 count 的遞減判零也可以直接用匯編指令實(shí)現(xiàn),但這樣做節(jié)約不了多

            少代碼,用標(biāo)準(zhǔn)的 C 語言描述更直觀,更易于維護(hù)。

            一句話:用了 C 語言后,就不要再老想著用匯編。

            盡量使用嵌入?yún)R編

            這和上面的慎用匯編指令的說法并不矛盾。如果確實(shí)需要用匯編指令實(shí)現(xiàn)部分代碼以提

            高運(yùn)行效率,應(yīng)盡量使用行內(nèi)匯編,避免編寫純匯編文件(*.as 文件)。

            雖然 PICC 支持 C 和匯編原程序模塊存在于同一個項(xiàng)目中,但要編寫純匯編文件必須首

            先了解 PICC 特有的匯編語法結(jié)構(gòu)。Hitech 公司提供了完整的文檔介紹其匯編器的使用方法,

            有興趣者可以從其網(wǎng)站上下載 PICC 的用戶使用手冊查看。

            筆者認(rèn)為,類似于純匯編文件的代碼也可以在 C 語言框架下實(shí)現(xiàn),方法是基于 C 標(biāo)準(zhǔn)

            語法定義所有的變量和函數(shù)名,包括需要傳遞的形式參數(shù)、返回參數(shù)和局部變量,但函數(shù)內(nèi)

            部的指令基本用嵌入?yún)R編指令編寫,只有最后的返回參數(shù)用 C 語句實(shí)現(xiàn)。這樣做后函數(shù)的

            運(yùn)行效率和純匯編編寫時幾乎一模一樣,但各參數(shù)的傳遞統(tǒng)一用 C 標(biāo)準(zhǔn)實(shí)現(xiàn),這樣管理和

            維護(hù)就比較方便。例如下面的例 11-15 實(shí)現(xiàn)一個字節(jié)變量的偶校驗(yàn)位計算。

            bit EvenParity(unsigned char data)

            {

            #asm


            swapf ?a_EvenParity+0,w

            xorwf ?a_EvenParity+0,f

            rrf ?a_EvenParity+0,w

            xorwf ?a_EvenParity+0,f

            btfsc ?a_EvenParity+0,2

            incf ?a_EvenParity+0,f

            #endasm

            //至此,data 的最低位即為偶校驗(yàn)位

            if (data&0x01) return(1);

            else return(0);

            }


            //入口參數(shù) data 的尋址符為 ?a_EvenParity+0


            例 11-15 C 函數(shù)框架中使用嵌入?yún)R編指令

            盡量使用全局變量進(jìn)行參數(shù)傳遞

            使用全局變量最大的好處是尋址直觀,只需在 C 語言定義的變量名前增加一個下劃線

            符即可在匯編語句中尋址;使用全局變量進(jìn)行參數(shù)傳遞的效率也比形參高。編寫單片機(jī)的 C

            程序時不能死硬強(qiáng)求教科書上的模塊化編程而大量采用行參和局部變量的做法,在開發(fā)編程

            時應(yīng)視實(shí)際情況靈活變通,一切以最高的代碼效率為目標(biāo)。



            關(guān)鍵詞: PIC單片機(jī)C語言編

            評論


            技術(shù)專區(qū)

            關(guān)閉