說明:本文中所說的編程規範只是我個人的一些想法和實踐,有些經驗可能並不能適合所有場合,當然也不可避免的有比較偏頗的看法,請大家多多批評指正。
之前我們已經學習了如何把複雜的單片機程序按照模塊功能分為多個程序模塊,然後使用頭文件包含的方式將不同的程序模塊有機的聯繫起來。經過模塊化編寫的程序,閱讀、查詢起來會很清晰。
本例中,我們進一步對單片機程序的編程規範做一些簡單說明,目的是讓我們編寫的程序看起來不會那麼亂,並且讓看我們程序的人都能看懂。
本實例我們從變量的命名規範、程序注釋、程序體結構劃分幾方面來簡單了解如何使程序看起來乾淨、不雜亂、變量一看就知道含義,程序中每一段都是獨立的,但是又能有機的結合起來。
我們從變量的命名規範、變量的初始化、函數體的結構化、注釋的方法這幾方面來了解一下。至於其它的編程規範和方法,我們在隨後的實例中逐步了解。
變量名應使用帶有具體含義的英文單詞組合或者簡寫,避免使用i,j,k這種無任何含義的變量名。
但是i,j,k這類變量並不是完全就不能用,在一定場合下,還是建議使用i,j,k這類變量的。什麼場合下可以使用這種無含義的變量呢?在循環語句中是可以使用的,例如for循環、while循環、do...while循環,循環次數可以使用i,j,k這些變量表示。循環次數等一些很簡單的,目的很明確的場合,使用這些變量不但不會引起歧義,還可以使程序更加簡潔。
而在大部分情況下,還是建議使用有具體含義的變量名稱。我個人習慣於使用動詞+名稱的方式,其中每一個檔次的頭一個字母大寫。例如定義一個向DS1302寫數據的變量,可以定義為WriteData,當程序裡包含多個外設模塊,這些模塊都有相似的操作時,最好再把外設模塊名字加上,與具體操作的變量名之間用下劃線「_」將二者組合在一起,用以區別是對那個模塊的操作。例如程序中有LCD1602和DS1302兩個外設模塊,都有寫數據的操作,分別命名為:LCD1602_WriteData,DS1302_WriteData。也可以定義為WriteData_LCD1602,WriteData_DS1302。模塊名稱可以在前面,也可以在後面,根據自己的習慣就行。
對於英文名字比較長的單詞,可以使用簡寫,但是簡寫的名字要讓人看了容易理解,或者使用約定俗成的簡寫。例如對於串口數據收發的變量,一般約定用Rev表示接收數據變量、用Trn表示發送數據變量,對於數組變量,一般使用Buff命名。
還有一種命名習慣是命名時帶上變量的數據類型,例如定義一個無符號整型數據,可以這樣定義 unsigned int uiCounter。這樣的話,一看到這個變量名字前面的「ui」,就知道該變量是無符號整型數據。
變量在定義的時候可以直接初始化,例如unsigned int uiCounter=0;也可以只定義變量但不初始化變量的值。
如果變量在定義時沒有初始化其數值,則程序中使用該變量時應對其設置明確的數值,不能直接使用,否則容易出錯。例如先定義了變量unsigned int uiCounter;未對其值初始化,這時如果直接作如下操作P0=uiCounter,則P0埠8個位的狀態是隨機的,並且每調用一次這個語句,P0口8個位的狀態是不一樣的。
一般情況下,函數體的內容包括:局部變量定義及初始化,具體函數語句、函數返回值語句。
其中局部變量定義及初始化以及函數返回值語句可以沒有。另外函數返回值語句可能在函數體的任何位置,不一定局限於函數的最後。
函數內的局部變量初始化、執行語句、返回值這三部分之間最好用一個空行隔開。例如下面的代碼。
bit BusyTest(void) { bit result; RS=0; //根據規定,RS為低電平,RW為高電平時,可以讀狀態 RW=1; E=1; //E=1,才允許讀寫 _nop_(); //空操作 _nop_(); _nop_(); _nop_(); //空操作四個機器周期,給硬體反應時間 result=BF; //將忙碌標誌電平賦給result E=0; //將E恢復低電平 return result; }
這樣做的好處是,可以使函數結構清晰。
並且建議函數體內根據不同功能,內容,適當在語句中添加空行,這樣的程序看起來不會讓人感覺到累。
程序的注釋分為兩大部分:函數功能的注釋和程序語句的注釋。
函數語句的注釋一般包括函數功能,入口參數、出口參數等。對於較為複雜的函數,有些還建議添加函數建立時間,更改時間,更改內容等。
如下面代碼所示。
/*****************************************************函數功能:將模式設置指令或顯示地址寫入液晶模塊入口參數:dictate***************************************************/void WriteInstruction (unsigned char dictate){ }
程序語句的注釋一般放在語句後面,應當於與語句保持適當的空格,這樣不至於把程序語句和注釋看成一體。
對於比較長的語句,或者這個語句的注釋比較長,一般把注釋放在該語句的上方。如下所示。
/*****************************************************函數功能:指定字符顯示的實際地址入口參數:x***************************************************/ void WriteAddress(unsigned char x) { //顯示位置的確定方法規定為&34; WriteInstruction(x|0x80); }
本實例沒有電路。
本實例沒有具體的程序代碼。
本實例沒有仿真。
單片機項目設計不單單是把功能實現了,還要把程序設計得更合理、更清晰、易移植,因為多數情況下,在公司裡面的單片機項目不會只是設計者一個人看的,更不會一直是同一個人在管理、修改這個項目。所以要養成良好的編程習慣。