林明祖
【摘 要】 在我們的單片機作品和單片機工程中,單片機C程序的設計和編寫工作是一項主要的任務,清晰的編寫思路,對C程序結構的熟習和了解,是我們順利完成軟件編寫的主要因素。在此,通過對單片機C程序結構的學習研究,和典型綜合類源程序的分析和總結。得出單片機C程序編寫中各程序功能模塊的實現方法,函數運行部位的合理安排布置,全局變量的初始賦值方法和傳遞方向等思路。
【關鍵詞】 單片機;C程序;編寫思路;方法
【中圖分類號】G64.23 【文獻標識碼】A 【文章編號】2095-3089(2015)25-00-02
現在,很多人都在運用單片機,單片機的運用越來越廣范,產品也起來越多,更多的人在不斷加入單片機開發的隊伍。而有部分人就會遇到這樣的問題,雖然花了很多時間進行了單片機C語言的學習,也掌握了各種變量的定義、運算符的使用、各種語句的運用、函數的編寫方法和單片機各功能模塊的運用。但在實際編寫一些綜合程序時,還是不知該如何下手編寫。其原因還是對C程序的總體結構和組成要有一個清晰的了解和認識,特別是要通過對很多典型的、綜合的源程序進行分析和總結,領會和找出綜合典型程序的結構方法和巧妙的編程思路,才能合理熟練的安排各功能函數,使整個程序按我們的思路合理的組織連接起來。
單片機的硬件結構由單片機的內部功能模塊和外部功能單元構成。在軟件編寫之前,首先確定我們的硬件方案,了解和熟習單片機的內部功能和外部方案,盡量利用單片機的內部資源來設計我們的電子作品。如:內部的I/O口、定時計數器、中斷、串口通訊、A/D轉換、CCP、看門狗等;外部的ADC0804、ADC0809、DAC0832、LED數碼管、1602LCD液晶顯示、12864LCD液晶顯示、獨立鍵盤、矩陣鍵盤、電機驅動IC、蜂鳴器等;各種單片機的內部結構、功能各不相同。單片機的硬件設計完成后,就可根據硬件方案和任務來進行軟件編寫了。
1 單片機C程序的結構特點、作用
1.1單片機軟件的結構特點:
單片機C程序與PC機C有很多共同的地方,也有一些區別。函數是C程序的基本組成單位,故C又被稱為函數式語言。C程序可由一個或多個函數構成。每個函數實現一定的功能,即功能函數。一個單片機程序軟件的總體結構包括:程序開始部分的預處理(頭文件、宏定義、全局變量定義、函數說明等);主函數;子函數;中斷函。
主函數:一個C程序必須有且只能有一個main()函數,也可以有一個main()函數和若干個其它函數。主函數的位置可在其它函數之前,也可以在之后,但程序運行時,總是首先自動從主函開始執行。
子函數:子函數可有多個,每一個子函數完成一個特定的任務和功能,也就是功能函數。子函數不會自動執行,只能被其它函數調用。
中斷函數:中斷函數是在中斷發生后被執行的函數,定時器中斷一般可用來做時間發生,脈沖產生,波形產生等,外中斷則可處理一些外部事件。
1.2單片機軟件的作用:
單片機軟件是對硬件起到設置、控制、驅動的作用,對數據則進行算術運算、邏輯運算。
(1)設置作用:單片機的狀態受特殊功能寄存器的控制,一般普通51單片機都有20多個特殊功能寄存器,所有這些寄存器以及端口的初始化等都要靠軟件來設置。
(2)控制作用:單片機有一些是開關量控制,如燈的亮滅,電動機的運轉和停止,電磁閥的開和關等,這些也是靠軟件的位操作和字節操作來進行控制。
(3)驅動作用:有些硬件單元,如:液晶的顯示、步進電機的轉動等,是需要軟件來進行設置、控制以及進行數據調用的,這時的軟件對硬件起到了驅動硬件的作用。
2 單片機功能程序、函數的實現方法
單片機需要根據硬件來決定編寫哪些功能函數、驅動程序、控制程序。功能函數軟件的功能一般都有多種實現方法,選擇采用哪種函數軟件方法來實現所需要的功能,需要根據具體情況分析、選擇、確定。單片機要實現一個功能,可以采用的方法有多種,通過分析確定一種較優的方法。如:
例1:要讓單片機輸出一定的脈沖,可采用以下方案:
用PWM內部模塊
用中斷函數
軟件語句產生,然后由主函數中的while(1)無限循環調用。
例2:要進行LED數碼管顯示,可采用以下方案:
用中斷函數不斷反復執行顯示
用主函數中的while(1)無限循環調用顯示子函數
例1中,要實現PWM輸出是用軟件語句產生還是用中斷功能產生,還是用PWM功能模塊。就要根據硬件配置,如51系列單片機就無PWM內部模塊,就只能采用中斷方法或軟件語句產生,然后由主函數無限調用。如是PIC系列單片機有此功能硬件,則可采用內部PWM模塊來實現輸出。如中斷被占用,也可以采用軟件語句來實現。除此之外,還根據其它因素來考慮采用哪一種實施方案。如要求時間精度高一些則宜運用定時計數器中斷,如要求不高則可采用軟件語句產生的方法。實現單片機功能的方案確定后,就可以開始編寫相應的功能程序、函數了。
3 單片機軟件編寫時,應注重以下幾個問題
3.1編寫單片機C程序要有清晰的結構思路
1個C程序可由1個或多個源文件組成,而1個源文件又由1個或多個函數組成,一般來說,一個函數就是一個功能模塊,就是一個小的任務,多個函數組合起來就可完成一個綜合的工程項目。1個源程序,除了預處理部分外,還有其它函數,如:主函數、子函數、中斷函數。
編寫的子函數、程序,要放到哪類函數來執行,執行部位在哪里,也需要我們有一個總體的構思和安排布置。要區分某段程序是暫時調用執行一下,還是要不斷反復運行。如果只是臨時調用執行則可設計安排到一般子函數中,如果要不斷反復執行的程序段,則要設計安排到定時計數器中斷函數中和主函數的while(1)循環中。
如果把所有的程序代碼都放在一個main()函數中,程序也可以運行。但是一些結構復雜,功能函數較多,代碼量大的程序都放在一個主函數中來執行就顯得雜亂了,程序結構會變得混亂不清晰,雖然可以運行,但是可移植性、可讀性就差了。就算是自己編寫的程序,也不容易理清、讀懂。所以要把它們分解編寫成多個功能程序、子函數,安排布置到源程序的各類函數中去完整的組織起來運行。
3.2功能程序執行的部位——主函數、子函數、中斷函數
一般我們把功能函數劃分為,無限循環執行類和臨時調用執行類。一般需要不斷無限循環執行類的功能程序、函數,如:步進電機驅動程序;舵機轉角控制脈沖驅動程序;秒基準時間產生程序;外部傳感開關查詢程序;軟件PWM輸出程序;動態LED數碼管掃描程序;掃描按鍵程序等。只是臨時調用執行類的功能程序、函數,如:延時函數;初始化函數;開關量執行函數等。
通過對很多典型、綜合運用類單片機C程序的研究分析,以極C程序結構的分析,一般把不間斷無限循環類安排在中斷函數中和主函數的while(1)無限循環中,把臨時調用類安排在子函數中。功能函數的分布安排原則一般如下:
(1)一般單片機工作,是采用時間片輪轉的方法運行,所以,可將實時性要求不高的工作放在主函數中,依次輪流執行。而實時性要求高的,則要使用中斷技術及時處理。
(2)首先把反復定時,時間長和時間基準要求較高的工作如:秒基準時間產生程序、步進電機驅動程序等,安排到中斷函數中。其它的一般無限循環執行類,如:動態LED數碼管掃描程序;按鍵掃描程序等,安排到main()函數的while(1)中。
(3)如沒有時間基準要求較高的程序、函數,則可以把一般的動態LED數碼管掃描程序;按鍵掃描程序等直接安排到中斷函數中。
(4)較長的延時函數中也可插入其它程序,如顯示程序、按鍵判斷等。
(5)其它臨時調用執行類的程序、函數,如:延時函數;初始化函數;開關量執行函數等,則安排到子函數中供其它函數調用。
例如:“可設置時間的6位LED顯示軟時鐘”程序結構如下:
main( ?)
{ ?while( 1)
{
顯示函數( ) ? ? ? ?//將6位時鐘的值實時顯示
按鍵掃描函數( ) ? ?//選擇6位時鐘的某位變量,從而增減該變量
} ?}
1ms延時函數( )
定時器初始化函數( )
定時器中斷函數1( ) ? ? ? //50ms中斷一次,20次產生一秒,然后對6位數加一賦值。
定時器中斷函數2( ) ? ? ? //對按鍵選擇的某位不斷賦二個值,新的增減值和熄滅值。
以上這個項目中共用到了6個功能函數,需要不斷反復執行的有4個:顯示函數()、按鍵掃描函數()、中斷函數1()、中斷函數2()。這4個中,中斷函數1()和中斷函數2()反復定時時間長和時間基準要求較高,所以安排到中斷函數中比較合理。顯示函數()和按鍵掃描函數()時間基準要求不太嚴格則可安排到main()的while(1)無限循環中執行。其它二個子函數則供臨時調用。這樣,我們把各個功能程序、函數安排分布到各個中斷函數、主函數、子函數中,最終形成按我們的要求和運行思路連接起來運行的完整程序。
3.3單片機程序中,要盡可能采用簡潔、高效的運算方法
算法就是用C語言編程,數據處理運算的思路方法。單片機的程序算法要盡量運算簡單,節約時間。一個算法的運行效率一般用空間復雜度與時間復雜度來衡量。算法的時間復雜度是指算法需要消耗的時間資源。算法的空間復雜度是指算法需要占用的空間資源。不同的算法占用的時間、空間都不相同。編程時應盡可能做到占用空間小,運行時間短,速度快。
例如:P1口接8個小燈,運行左移流水燈。
算法1
void lamp( ?)
{
uchar i;
P1=0xfe;
for(i=0;i<8;i++)
{
P1=_crol_(P1,1);
Delay(200);
}
}
算法2
void lamp ( ?)
{
uchar i;
uchar data=0xff;
for(i=0;i<8;i++)
{
P1=data;
delay(200);
data<<=1;
}
}
算法3
void lamp ( ?)
{
P1=0xfe; delay(200);
P1=0xfd; delay(200);
P1=0xfb; delay(200);
P1=0xf7; delay(200);
.
.
}
從上面三段代碼的運行來看,算法1和算法2要優于算法3。
4 對全局變量的起始賦值、傳遞過程思路要清楚
全局變量的起始賦值和傳遞方向、執行位置是我們程序設計的一個重要思路,全局變量從哪里賦值開始?傳遞到哪里?在哪里使用?傳遞的過程路線都必須思路清晰。如:前例中,主要的全局變量是按鍵選擇位的變量和被選擇位的加減值變量,這兩個變量都是兩個主要的全局變量。兩個全局變量的起始賦值都在鍵盤掃描函數中,由一個按鍵來決定修改哪位,另二位按鍵決定該值的加減。第一個全局變量(某位)傳遞到本函數的加減語句中和中斷函數2中;第二個全局變量(加減后的值)則傳遞到中斷函數1中去更新相應位的數值。
5 總結
在單片機C程序的設計和編寫工作中,設計和編寫的原則和思路是我們完成軟件工程的精髓。我們在編寫程序時重點要重視二點:
(1)在安排布置反復執行的功能程序、函數時,首先把定時時間長和時間基準要求較高的程序、函數安排到中斷函數中;其它的一般無限循環執行類函數則安排到主函數的while(1)中。
(2)全局變量的起始賦值和傳遞方向、位置,從哪里賦值開始?傳遞到哪里?在哪里使用?和傳遞的過程路線要思路清晰。
(3)單片機程序中,要盡可能采用簡潔、高效的運算方法。
參考文獻
[1]盧伯英譯.活學活用PIC單片機C語言編程[M].科學出版社.2012.5
[2]李光飛等.單片機C程序設計實例指導[M].北京航空航天大學出版社.2005.9
[3]劉建清.輕松玩轉51單片機語言[M].北京航空航天大學出版社.2011.3