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