單片機C語言優(yōu)化
雖然并不會影響生成代碼的質(zhì)量,但是在實際編寫過程中還是要遵循一定的書寫規(guī)則,一個書寫清晰明了的程序有利于以后的維護。在書寫程序時,特別是對于while、for、do while、if else、switch case等語句或這些語句嵌套組合時,應采用“縮格”的書寫形式。
本文引用地址:http://butianyuan.cn/article/201611/316913.htm二、標識符
程序種使用的用戶標識符除要遵循標識符的命名規(guī)則以外,一半不要用代數(shù)符號(如a、b、x1、x2)作為變量名,應選取具有相關(guān)含義的英文單詞(或縮寫)或拼音作為標識符,增加程序的可讀性。
三、程序結(jié)構(gòu)
C語言是一種高級程序設(shè)計語言,提供了十分完備的規(guī)范化流程控制結(jié)構(gòu)。因此在采用C語言設(shè)計單片機應用程序時,首先要注意盡可能采用結(jié)構(gòu)化的程序設(shè)計方法。這樣可以使應用系統(tǒng)程序結(jié)構(gòu)清晰便于調(diào)試和維護。對于一個較大的應用程序,通常將整個程序按功能分成若干個模塊,不同的模塊完成不同的功能。各個模塊可以分別編寫,甚至還可以由不同的程序員編寫。一半單個模塊完成的功能較為簡單,設(shè)計和調(diào)試也相對容易一些。在C語言中一個函數(shù)就可以認為是一個模塊。所謂程序模塊化。不僅是要將整個程序劃分成若干個功能模塊。更重要的是,還應該保持各個模塊之間變量的相對獨立性。盡量少使用全局變量等。對于一些常用的功能模塊還可以封裝為一個應用程序庫,以便需要時可以直接調(diào)用。但是在使用模塊化時,如果將模塊分的太細又會導致程序的執(zhí)行效率低(今天和和推出一個函數(shù)時需要保護和恢復寄存器占用的了一些時間)。
四、定義常熟
在程序化設(shè)計過程中,對于經(jīng)常使用的一些常數(shù),如果將它直接寫到程序中去,一旦常數(shù)的數(shù)值發(fā)生變化,就必須逐個找出程序中所有的常數(shù),并逐一進行修改,這樣必然會導致降低程序的可維護性。因此,應盡量當采用與處理命令的方式來定義常數(shù)。而且還可以避免輸入錯誤。
五、減少判斷語句
能夠使用條件編譯的(ifdef)的地方就使用條件編譯而不使用(if)語句有利于減少編譯生成的代碼的長度。
六、表達式
對于一個表達式中的運算執(zhí)行的優(yōu)先順序不太明確或容易混淆的地方,應當采用圓括號明確制定它們的順序。一個表達式不能寫得太復雜。如果太復雜,時間久了以后自己也不容易看的懂,不易于以后的維護。
七、函數(shù)
對于程序中的函數(shù),在使用之前,應對函數(shù)的類型進行說明,對函數(shù)類型的說明,必須保證它與原來定義的函數(shù)類型一致,對于沒有參數(shù)和沒用返回值的函數(shù)應加上void說明。如果需要縮短代碼的長度,可以將程序中一些公共的程序段定義為函數(shù)。在keil中搞級別優(yōu)化就是這樣的。如果需要縮短程序的執(zhí)行時間。在程序調(diào)試結(jié)束后,將部分函數(shù)用宏定義來代替。注意,應該在程序調(diào)試結(jié)束后再定義宏,因為大多數(shù)編譯系統(tǒng)在宏展開之后才會報錯,這樣會增加排錯的難度。
八、變量
盡量少使用全局變量多用局部變量。因為全局變量是放在數(shù)據(jù)存儲器中,定義一個全局變量,mcu就少一個可以利用的數(shù)據(jù)存儲空間。如果定義了太多的全局變量,會導致編譯器無足夠的內(nèi)存可以分配。而局部變量大多定位于mcu內(nèi)部的寄存器中。在絕大多數(shù)mcu中使用寄存器操作速度比數(shù)據(jù)寄存器塊。質(zhì)量也更多更靈活。有利于生成高質(zhì)量的代碼。而且局部變量所占用的寄存器和數(shù)據(jù)存儲器在不同模塊中可以重復使用。
九、代碼的優(yōu)化
選擇和漢斯的算法和數(shù)據(jù)結(jié)構(gòu),應該熟悉算法語言,知道各種算法的優(yōu)缺點,具體資料請參見相應的參考資料,又很多計算機書籍上都又介紹。將比較慢的順序查找法用比較快的二分查找或亂序查找法代替。插入排序或冒泡排序法用快速排序、合并排序或跟排序代替。都可以大大提高程序執(zhí)行的效率。選擇一種合適的數(shù)據(jù)結(jié)構(gòu)也很重要。必然你在一堆隨機存放的數(shù)中使用了大量的插入和排序指令,那使用鏈表要快的多。
使用盡量小的數(shù)據(jù)類型
能夠使用字符型(char)定義的變量就不要使用整形(int)變量來定義
使用自加、自減指令
減少運算強度
可以使用運算量小丹功能相同的表達式替換原來復雜的表達式:
如求余運算
a=a%8
可以改為:a=a&7
平方運算
a=pow(a,2.0);
可以改為:a=a*a;
用移位運算實現(xiàn)乘除法
a=a*4
b=b/4
可以改為:
a=a<<2
b=b>>2
a=a*9可以改為a=(a<<3)+a;
循環(huán)
對于一些不需要循環(huán)變量參加運算的任務把它們安排的循環(huán)外面。這里任務包括表達式、函數(shù)的調(diào)用、指針運算、數(shù)組訪問等,應該將沒有必要執(zhí)行多次的操作全部集合在一起,放到一個init的初始化程序中進行。
延時函數(shù):
通常使用的延時函數(shù):
void delay(void)
{
unsigned int i;
for(i=0;i<1000;i++);
}
改為
void dellay(void)
{
unsigned int i;
for(i=1000;--i)
}
兩個函數(shù)效果相似,但幾乎所有的C編譯器對后一種函數(shù)生成的代碼比前一種代碼少1-3個字節(jié)。因為幾乎所有MCU都有0轉(zhuǎn)移指令采用后一種方式能夠生成這類指令。在while循環(huán)時也一樣,使用自減指令控制循環(huán)比使用自加指令控制循環(huán)生成代碼少1-3個字節(jié)。在使用while循環(huán)中又使用循環(huán)變量讀寫數(shù)據(jù)的指令時,使用減循環(huán)時又可能是數(shù)組超界,要引起注意。
while、和do while循環(huán)
unsigned int i;
i=0;
while(i<1000)
{
i++;
}
改為
do
i--;
while(i>0);
在這兩種循環(huán)中,使用do while循環(huán)編譯后的代碼長度短于while循環(huán)。
查表
在程序中一般不進行非常復雜的運算,如浮點數(shù)的程序及開方等。以及一些復雜的數(shù)學模型的插補運算。對這些即消耗時間又消耗資源的運算。應盡量使用查表的方式,并且將數(shù)據(jù)表置于程序存儲區(qū)。如果直接生成所需的表比較困難。也盡量在啟動時先計算。然后在數(shù)據(jù)存儲器中生成所需要的表。在程序運行中直接查表就可以了。減少了程序執(zhí)行過程中重復計算的工作量。
其他
比如使用在線匯編及字符串和一些常量的保存在程序存儲器中都又利于優(yōu)化。
評論