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