新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 如何寫出高效的單片機(jī)C語言程序代碼

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

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

結(jié)果:數(shù)組a存儲(chǔ)的內(nèi)容是1、2、3、4、5。
例子4:在大端模式下(8051系列單片機(jī)是大端模式)將含有位域的結(jié)構(gòu)體賦給無符號字節(jié)整型值
方法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;
結(jié)果:a=0x3C
方法2:強(qiáng)制轉(zhuǎn)換。
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
結(jié)果:a=0x3C
例子5:在大端模式下(8051系列單片機(jī)是大端模式)將無符號字節(jié)整型值賦給含有位域的結(jié)構(gòu)體。
方法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:強(qiáng)制轉(zhuǎn)換。
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.減少函數(shù)調(diào)用參數(shù)
使用全局變量比函數(shù)傳遞參數(shù)更加有效率。這樣做去除了函數(shù)調(diào)用參數(shù)入棧和函數(shù)完成后參數(shù)出棧所
需要的時(shí)間。然而決定使用全局變量會(huì)影響程序的模塊化和重入,故要慎重使用。

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

14.將大的switch語句轉(zhuǎn)為嵌套switch語句
當(dāng)switch語句中的case標(biāo)號很多時(shí),為了減少比較的次數(shù),明智的做法是把大switch語句轉(zhuǎn)為嵌
套switch語句。把發(fā)生頻率高的case標(biāo)號放在一個(gè)switch語句中,并且是嵌套switch語句的最外
層,發(fā)生相對頻率相對低的case標(biāo)號放在另一個(gè)switch語句中。比如,下面的程序段把相對發(fā)生頻率
低的情況放在缺省的case標(biāo)號內(nèi)。
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語句同樣要轉(zhuǎn)換為嵌套的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.函數(shù)指針妙用
當(dāng)switch語句中的case標(biāo)號很多時(shí),或者if語句的比較次數(shù)過多時(shí),為了提高程序執(zhí)行速度,
可以運(yùn)用函數(shù)指針來取代switch或if語句的用法,這些用法可以參考電子菜單實(shí)驗(yàn)代碼、USB實(shí)驗(yàn)代碼
和網(wǎng)絡(luò)實(shí)驗(yàn)代碼。
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};
調(diào)用方法1:(*szTaskTbl[ucCurTask])();
調(diào)用方法2:szTaskTbl[ucCurTask]();

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

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

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

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

上一頁 1 2 下一頁

關(guān)鍵詞: 單片機(jī)C語言程序代

評論


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

關(guān)閉