微控制器C程式優化

2022-12-04 02:33:02 字數 4237 閱讀 3812

對程式進行優化,通常是指優化程式**或程式執行速度。優化**和優化速度實際上是乙個予盾的統一。一般是優化了**的尺寸,就會帶來執行時間的增加;如果優化了程式的執行速度,通常會帶來**增加的***。

很難魚與熊掌兼得,只能在設計時掌握乙個平衡點。

一、程式結構的優化

1、程式的書寫結構

雖然書寫格式並不會影響生成的**質量,但是在實際編寫程式時還是應該尊循一定的書寫規則,乙個書寫清晰、明了的程式,有利於以後的維護。在書寫程式時,特別是對於while、for、do…while、if…else、switch…case 等語句或這些語句巢狀組合時,應採用「縮格」的書寫形式。

2、識別符號

程式中使用的使用者識別符號除要遵循識別符號的命名規則以外,一般不要用代數符號(如a、b、x1、y1)作為變數名,應選取具有相關含義的英文單詞(或縮寫)或漢語拼音作為識別符號,以增加程式的可讀性,如:count、number1、red、work 等。

3、程式結構

c 語言是一種高階程式語言,提供了十分完備的規範化流程控制結構。因此在採用c 語言設計微控制器應用系統程式時,首先要注意盡可能採用結構化的程式設計方法,這樣可使整個應用系統程式結構清晰,便於除錯和維護。

對於乙個較大的應用程式,通常將整個程式按功能分成若干個模組,不同模組完成不同的功能。各個模組可以分別編寫,甚至還可以由不同的程式設計師編寫,一般單個模組完成的功能較為簡單,設計和除錯也相對容易一些。在c 語言中,乙個函式就可以認為是乙個模組。

所謂程式模組化,不僅是要將整個程式劃分成若干個功能模組,更重要的是,還應該注意保持各個模組之間變數的相對獨立性,即保持模組的獨立性,盡量少使用全域性變數等。對於一些常用的功能模組,還可以封裝為乙個應用程式庫,以

便需要時可以直接呼叫。但是在使用模組化時,如果將模組分成太細太小,又會導致程式的執行效率變低(進入和退出乙個函式時保護和恢復暫存器占用了一些

時間)。

4、定義常數

在程式化設計過程中,對於經常使用的一些常數,如果將它直接寫到程式中去,一旦常數的數值發生變化,就必須逐個找出程式中所有的常數,並逐一進行修改,這樣必然會降低程式的可維護性。因此,應盡量當採用預處理命令方式來定義常數,而且還可以避免輸入錯誤。

5、減少判斷語句

能夠使用條件編譯(ifdef)的地方就使用條件編譯而不使用if 語句,有利於減少編譯生成的**的長度。

6、表示式

對於乙個表示式中各種運算執行的優先順序不太明確或容易混淆的地方,應當採用圓括號明確指定它們的優先順序。乙個表示式通常不能寫得太複雜,如果表示式太複雜,時間久了以後,自己也不容易看得懂,不利於以後的維護。

7、函式

對於程式中的函式,在使用之前,應對函式的型別進行說明,對函式型別的說明必須保證它與原來定義的函式型別一致,對於沒有引數和沒有返回值型別的函式應加上「void」說明。如果果需要縮短**的長度,可以將程式中一些公共的程式段定義為函式。如果需要縮短程式的執行時間,在程式除錯結束後,將部分函式用巨集定義來代替。

注意,應該在程式除錯結束後再定義巨集,因為大多數編譯系統在巨集展開之後才會報錯,這樣會增加排錯的難度。

8、盡量少用全域性變數,多用區域性變數

因為全域性變數是放在資料儲存器中,定義乙個全域性變數,mcu 就少乙個可以利用的資料儲存器空間,如果定義了太多的全域性變數,會導致編譯器無足夠的記憶體可以分配;而區域性變數大多定位於mcu 內部的暫存器中,在絕大多數mcu 中,使用暫存器操作速度比資料儲存器快,指令也更多更靈活,有利於生成質量更高的**,而且區域性變數所的占用的暫存器和資料儲存器在不同的模組中可以重複利用。

9、設定合適的編譯程式選項

許多編譯程式有幾種不同的優化選項,在使用前應理解各優化選項的含義,然後選用最合適的一種優化方式。通常情況下一旦選用最高端優化,編譯程式會近乎病態地追求**優化,可能會影響程式的正確性,導致程式執行出錯。因此應熟悉所使用的編譯器,應知道哪些引數在優化時會受到影響,哪些引數不會受到影響。

二、**的優化

1、選擇合適的演算法和資料結構

應熟悉演算法語言。將比較慢的順序查詢法用較快的二分查詢法或亂序查詢法代替,插入排序或氣泡排序法用快速排序、合併排序或根排序代替,這樣可以大大提高程式執行的效率。

選擇一種合適的資料結構也很重要,比如在一堆隨機存放的資料中使用了大量的插入和刪除指令,比使用鍊錶要快得多。陣列與指標具有十分密切的關係,一般來說指標比較靈活簡潔,而陣列則比較直觀,容易理解。對於大部分分的編譯器,使用指標比使用陣列生成的**更短,執行效率更高。

但是在keil 中則相反,使用陣列比使用的指標生成的**更短。

2、使用盡量小的資料型別

能夠使用字元型(char)定義的變數,就不要使用整型(int)變數來定義;能夠使用整型變數定義的變數就不要用長整型(long int),能不使用浮點型(float)變數就不要使用浮點型變數。當然,在定義變數後不要超過變數的作用範圍,如果超過變數的範圍賦值,c 編譯器並不報錯,但程式執行結果卻錯了,而且這樣的錯誤很難發現。

3、使用自加、自減指令

通常使用自加、自減指令和復合賦值表示式(如a-=1 及a+=1 等)都能夠生成高質量的程式**,編譯器通常都能夠生成inc 和dec 之類的指令,而使用a=a+1 或a=a-1 之類的指令,有很多c 編譯器都會生成2~3個位元組的指令。

4、減少運算的強度

可以使用運算量小但功能相同的表示式替換原來複雜的的表示式。如下:

(1)求餘運算

a=a%8;

可以改為:

a=a&7;

說明:位操作只需乙個指令週期即可完成,而大部分的c 編譯器的「%」運算均是呼叫子程式來完成,**長、執行速度慢。通常,只要求是求2n 方的餘數,均可使用位操作的方法來代替。

(2)平方運算

a=pow(a,2.0);

可以改為:

a=a*a;

說明:在有內建硬體乘法器的微控制器中(如51 系列),乘法運算比求平方運算快得多,因為浮點數的求平方是通過呼叫子程式來實現的,在自帶硬體乘法器的**r 微控制器中,如atmega163 中,乘法運算只需2 個時鐘週期就可以完成。既使是在沒有內建硬體乘法器的**r 微控制器中,乘法運算的子程式比平方運算的子程式**短,執行速度快。

如果是求3 次方,如:

a=pow(a,3.0);

更改為:

a=a*a*a;

則效率的改善更明顯。

(3)用移位實現乘除法運算

a=a*4;

b=b/4;

可以改為:

a=a<<2;

b=b>>2;

說明:通常如果需要乘以或除以2n,都可以用移位的方法代替。在icc**r 中,如果乘以2n,都可以生成左移的**,而乘以其它的整數或除以任何數,均呼叫乘除法子程式。

用移位的方法得到**比呼叫乘除法子程式生成的**效率高。實際上,只要是乘以或除以乙個整數,均可以用移位的方法得到結果,如:

a=a*9

可以改為:

a=(a<<3)+a

5、迴圈

(1)迴圈語

對於一些不需要迴圈變數參加運算的任務可以把它們放到迴圈外面,這裡的任務包括表示式、函式的呼叫、指標運算、陣列訪問等,應該將沒有必要執行多次的操作全部集合在一起,放到乙個init 的初始化程式中進行。

(2)延時函式

通常使用的延時函式均採用自加的形式:

void delay (void)

將其改為自減延時函式:

void delay (void)

兩個函式的延時效果相似,但幾乎所有的c 編譯對後一種函式生成的**均比前一種**少1~3 個位元組,因為幾乎所有的mcu 均有為0 轉移的指令,採用後一種方式能夠生成這類指令。在使用while 迴圈時也一樣,使用自減指令控制迴圈會比使用自加指令控制迴圈生成的**更少1~3 個字母。

但是在迴圈中有通過迴圈變數「i」讀寫陣列的指令時,使用預減迴圈時有可能使陣列超界,要引起注意。

(3)while 迴圈和do…while 迴圈

用while 迴圈時有以下兩種迴圈形式:

unsigned int i;

i=0;

while (i<1000)

或:unsigned int i;

i=1000;

dowhile (i>0);

在這兩種迴圈中,使用do…while 迴圈編譯後生成的**的長度短於while

迴圈。6、查表

在程式中一般不進行非常複雜的運算,如浮點數的乘除及開方等,以及一些複雜的數學模型的插補運算,對這些即消耗時間又消費資源的運算,應盡量使用查表的方式,並且將資料表置於程式儲存區。如果直接生成所需的表比較困難,也盡量在啟動時先計算,然後在資料儲存器中生成所需的表,後以在程式執行直接查表就可以了,減少了程式執行過程中重複計算的工作量。

7、其它

比如使用**彙編及將字串和一些常量儲存在程式儲存器中,均有利於優化。

微控制器讀寫U盤C程式

這個程式用180行c 就能夠讀取fat16檔案系統u盤的根目錄,可以看到根目錄下的檔案 名,並可顯示 首檔案內容,不過,該程式很不嚴謹,也沒有任何錯誤處理,對u盤相容性較差,只是用於簡單試 驗,作為參考.這個程式可以支援windows按fat16格式化的u盤,因為程式精簡,所以只相容超過50 以上的...

微控制器程式詳解

微控制器程式詳解.txt 根網線 盡賺了多少人的青春 有時候感動的就是身邊微不足道的小事。破碎不是最殘酷的最殘酷的是踩著這些碎片卻假裝不疼痛固執的尋找 將來就算我遇見再怎麼完美的人,都有乙個缺點,他不是你,下輩子要做男生,娶乙個像我這樣的女生。程式詳解 程式清單 共陽數碼管加減顯示 sp1 bit ...

51微控制器的C語言程式結構

預處理命令 include 子函式 void delay void 主函式 void main void 2 c語言是由函式構成的,乙個c語言程式可以包含多個函式,但是有且只能有乙個主函式 函式名為main 主函式沒有返回值和引數 void main void c語言程式的執行總是從主函式main開...