新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 如何寫出高效的單片機C語言程序代碼

        如何寫出高效的單片機C語言程序代碼

        作者: 時間:2016-11-27 來源:網絡 收藏

        結果:數組a存儲的內容是1、2、3、4、5。
        例子4:在大端模式下(8051系列單片機是大端模式)將含有位域的結構體賦給無符號字節整型值
        方法1:逐位賦值。
        typedefstruct__BYTE2BITS
        {
        UINT8_bit7:1;
        UINT8_bit6:1;
        UINT8_bit5:1;
        UINT8_bit4:1;
        UINT8_bit3:1;
        UINT8_bit2:1;
        UINT8_bit1:1;
        UINT8_bit0:1;
        }BYTE2BITS;
        BYTE2BITSByte2Bits;
        Byte2Bits._bit7=0;
        Byte2Bits._bit6=0;
        Byte2Bits._bit5=1;
        Byte2Bits._bit4=1;
        Byte2Bits._bit3=1;
        Byte2Bits._bit2=1;
        Byte2Bits._bit1=0;
        Byte2Bits._bit0=0;
        UINT8a=0;
        a|=Byte2Bits._bit7<<7;
        a|=Byte2Bits._bit6<<6;
        a|=Byte2Bits._bit5<<5;
        a|=Byte2Bits._bit4<<4;
        a|=Byte2Bits._bit3<<3;
        a|=Byte2Bits._bit2<<2;
        a|=Byte2Bits._bit1<<1;
        a|=Byte2Bits._bit0<<0;
        結果:a=0x3C
        方法2:強制轉換。
        typedefstruct__BYTE2BITS
        {
        UINT8_bit7:1;
        UINT8_bit6:1;
        UINT8_bit5:1;
        UINT8_bit4:1;
        UINT8_bit3:1;
        UINT8_bit2:1;
        UINT8_bit1:1;
        UINT8_bit0:1;
        }BYTE2BITS;
        BYTE2BITSByte2Bits;
        Byte2Bits._bit7=0;
        Byte2Bits._bit6=0;
        Byte2Bits._bit5=1;
        Byte2Bits._bit4=1;
        Byte2Bits._bit3=1;
        Byte2Bits._bit2=1;
        Byte2Bits._bit1=0;
        Byte2Bits._bit0=0;
        UINT8a=0;
        a=*(UINT8*)&Byte2Bits
        結果:a=0x3C
        例子5:在大端模式下(8051系列單片機是大端模式)將無符號字節整型值賦給含有位域的結構體。
        方法1:逐位賦值。
        typedefstruct__BYTE2BITS
        {
        UINT8_bit7:1;
        UINT8_bit6:1;
        UINT8_bit5:1;
        UINT8_bit4:1;
        UINT8_bit3:1;
        UINT8_bit2:1;
        UINT8_bit1:1;
        UINT8_bit0:1;
        }BYTE2BITS;
        BYTE2BITSByte2Bits;
        UINT8a=0x3C;
        Byte2Bits._bit7=a&0x80;
        Byte2Bits._bit6=a&0x40;
        Byte2Bits._bit5=a&0x20;
        Byte2Bits._bit4=a&0x10;
        Byte2Bits._bit3=a&0x08;
        Byte2Bits._bit2=a&0x04;
        Byte2Bits._bit1=a&0x02;
        Byte2Bits._bit0=a&0x01;
        方法2:強制轉換。
        typedefstruct__BYTE2BITS
        {
        UINT8_bit7:1;
        UINT8_bit6:1;
        UINT8_bit5:1;
        UINT8_bit4:1;
        UINT8_bit3:1;
        UINT8_bit2:1;
        UINT8_bit1:1;
        UINT8_bit0:1;
        }BYTE2BITS;
        BYTE2BITSByte2Bits;
        UINT8a=0x3C;
        Byte2Bits=*(BYTE2BITS*)&a;

        12.減少函數調用參數
        使用全局變量比函數傳遞參數更加有效率。這樣做去除了函數調用參數入棧和函數完成后參數出棧所
        需要的時間。然而決定使用全局變量會影響程序的模塊化和重入,故要慎重使用。

        13.switch語句中根據發生頻率來進行case排序
        switch語句是一個普通的編程技術,編譯器會產生if-else-if的嵌套代碼,并按照順序進行比較,
        發現匹配時,就跳轉到滿足條件的語句執行。使用時需要注意。每一個由機器語言實現的測試和跳轉僅僅
        是為了決定下一步要做什么,就把寶貴的處理器時間耗盡。為了提高速度,沒法把具體的情況按照它們發
        生的相對頻率排序。換句話說,把最可能發生的情況放在第一位,最不可能的情況放在最后。

        14.將大的switch語句轉為嵌套switch語句
        當switch語句中的case標號很多時,為了減少比較的次數,明智的做法是把大switch語句轉為嵌
        套switch語句。把發生頻率高的case標號放在一個switch語句中,并且是嵌套switch語句的最外
        層,發生相對頻率相對低的case標號放在另一個switch語句中。比如,下面的程序段把相對發生頻率
        低的情況放在缺省的case標號內。
        UINT8ucCurTask=1;
        voidTask1(void);
        voidTask2(void);
        voidTask3(void);
        voidTask4(void);
        ……………
        voidTask16(void);
        switch(ucCurTask)
        {
        case1:Task1();break;
        case2:Task2();break;
        case3:Task3();break;
        case4:Task4();break;
        ………………………
        case16:Task16();break;
        default:break;
        }
        可以改為
        UINT8ucCurTask=1;
        voidTask1(void);
        voidTask2(void);
        voidTask3(void);
        voidTask4(void);
        ……………
        voidTask16(void);
        switch(ucCurTask)
        {
        case1:Task1();break;
        case2:Task2();break;
        default:
        switch(ucCurTask)
        {
        case3:Task3();break;
        case4:Task4();break;
        ………………………
        case16:Task16();break;
        default:break;
        }
        Break;
        }
        由于switch語句等同于if-else-if的嵌套代碼,如果大的if語句同樣要轉換為嵌套的if語句。
        UINT8ucCurTask=1;
        voidTask1(void);
        voidTask2(void);
        voidTask3(void);
        voidTask4(void);
        ……………
        voidTask16(void);
        if(ucCurTask==1)Task1();
        elseif(ucCurTask==2)Task2();
        else
        {
        if(ucCurTask==3)Task3();
        elseif(ucCurTask==4)Task4();
        ………………
        elseTask16();
        }

        15.函數指針妙用
        當switch語句中的case標號很多時,或者if語句的比較次數過多時,為了提高程序執行速度,
        可以運用函數指針來取代switch或if語句的用法,這些用法可以參考電子菜單實驗代碼、USB實驗代碼
        和網絡實驗代碼。
        UINT8ucCurTask=1;
        voidTask1(void);
        voidTask2(void);
        voidTask3(void);
        voidTask4(void);
        ……………
        voidTask16(void);
        switch(ucCurTask)
        {
        case1:Task1();break;
        case2:Task2();break;
        case3:Task3();break;
        case4:Task4();break;
        ………………………
        case16:Task16();break;
        default:break;
        }
        可以改為
        UINT8ucCurTask=1;
        voidTask1(void);
        voidTask2(void);
        voidTask3(void);
        voidTask4(void);
        ……………
        voidTask16(void);
        void(*szTaskTbl)[16])(void)={Task1,Task2,Task3,Task4,…,Task16};
        調用方法1:(*szTaskTbl[ucCurTask])();
        調用方法2:szTaskTbl[ucCurTask]();

        16.循環嵌套
        循環在編程中經常用到的,往往會出現循環嵌套。現在就已for循環為例。
        UINT8i,j;
        for(i=0;i<255;i++)
        {
        for(j=0;j<25;j++)
        {
        ………………
        }
        }
        較大的循環嵌套較小的循環編譯器會浪費更加多的時間,推薦的做法就是較小的循環嵌套較大的循環。
        UINT8i,j;
        for(j=0;j<25;j++)
        {
        for(i=0;i<255;i++)
        {
        ………………
        }
        }

        17.內聯函數
        在C++中,關鍵字inline可以被加入到任何函數的聲明中。這個關鍵字請求編譯器用函數內部的代
        碼替換所有對于指出的函數的調用。這樣做在兩個方面快于函數調用。這樣做在兩個方面快于函數調用:
        第一,省去了調用指令需要的執行時間;第二,省去了傳遞變元和傳遞過程需要的時間。但是使用這種方
        法在優化程序速度的同時,程序長度變大了,因此需要更多的ROM。使用這種優化在inline函數頻繁調
        用并且只包含幾行代碼的時候是最有效的。
        如果編譯器允許在C語言編程中能夠支持inline關鍵字,注意不是C++語言編程,而且單片機的ROM
        足夠大,就可以考慮加上inline關鍵字。支持inline關鍵字的編譯器如ADS1.2,RealViewMDK等。

        18.從編譯器著手
        很多編譯器都具有偏向于代碼執行速度上的優化、代碼占用空閑太小的優化。例如Keil開發環境編
        譯時可以選擇偏向于代碼執行速度上的優化(FavorSpeed)還是代碼占用空間太小的優化(Favor
        Size)。還有其他基于GCC的開發環境一般都會提供-O0、-O1、-O2、—O3、-Os的優化選項,而使用
        -O2的優化代碼執行速度上最理想,使用-Os優化代碼占用空間大小最小。

        19.嵌入匯編---殺手锏
        匯編語言是效率最高的計算機語言,在一般項目開發當中一般都采用C語言來開發的,因為嵌入匯編
        之后會影響平臺的移植性和可讀性,不同平臺的匯編指令是不兼容的。但是對于一些執著的程序員要求程
        序獲得極致的運行的效率,他們都在C語言中嵌入匯編,即“混合編程”。
        注意:如果想嵌入匯編,一定要對匯編有深刻的了解。不到萬不得已的情況,不要使用嵌入匯編。

        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 平泉县| 青田县| 龙陵县| 普陀区| 龙口市| 南平市| 景洪市| 麻城市| 汉沽区| 建昌县| 兴城市| 余姚市| 岱山县| 元阳县| 西乡县| 金川县| 金塔县| 易门县| 靖远县| 香河县| 玛曲县| 宜昌市| 嘉祥县| 建平县| 拜城县| 定安县| 昌图县| 贵南县| 微山县| 那曲县| 大丰市| 从江县| 靖安县| 乐都县| 山西省| 开鲁县| 祁阳县| 民乐县| 叶城县| 龙里县| 云林县|