模塊化編程
模塊化編程是開發(fā)者首先會掌握的一種編程思想,就像前面我們多次提到的把一些特定功能的代碼大打包成一個函數(shù),這么一來以后在其他項目中就可以通過復制、粘貼輕松的移植了。這就是最簡單的模塊化思想了,當然如果要規(guī)范一點的話我們需要在函數(shù)前做一些必要的注釋說明,方便自己日后重新使用這段代碼時能很快就可以知道代碼的功能。比如下面這段代碼:
/*
- 函數(shù)名:led_display
- 描 述:****
- 輸 入:****
- 輸 出:****
- 返 回:****
- 調 用:****
- 備 注:****
*/
void led_display(uint16_t duty ,uint8_t up_rate,uint8_t down_rate)
{
****
}
當然也可以不用寫這么多注釋,注釋內(nèi)容只要能保證可以看懂函數(shù)的意思就行,內(nèi)容根據(jù)自己的喜好來確定,比如你也可以這樣些:
/**
- @brief :****
- @param : ****
- @retval : ****
**/
甚至你也可以直接就用一句注釋說明,比如:
/* **** */
或者直接
// ****
只要能保證可以一眼看懂你的說明就行,當然最好是自形成一個統(tǒng)一的格式注釋格式,讓程序看起來更加美觀大方,以后別人讀你的程序心情也會好很多,畢竟項目開發(fā)不一定是你一個人完成特別是互聯(lián)網(wǎng)項目,比如一個大型項目就涉及到前端開發(fā)者,后端開發(fā)者,移動端(或桌面端)開發(fā)者,甚至還需要測試人員配合,這種情況雖然不會每個人都需要看你的代碼但至少會有人來跟你協(xié)同完成應用功能。所以很多公司都會規(guī)定注釋規(guī)范或編程規(guī)范。
平時編程時除了善于打包函數(shù)將程序模塊化,但項目中很多時候我們的程序不止是幾個函數(shù),我們項目可能使用了大量的外設,程序中需要大量的函數(shù)來完成功能,這時候如果只是打包函數(shù),我們的代碼也會變得非常龐大,如果一個文件里面有幾千甚至上萬行代碼,你日后維護起來是不是會崩潰,可能找一個bug都能找半天,這時候我們需要怎么辦呢?其實C語言庫文件就已經(jīng)告訴我們做法了,當然其他語言也是一樣。這時候我們就可以進行分文件打包程序,就是將相同功能或控制同一個外設的代碼放在同一個文件里進行模塊化,這樣做是不是比單純使用的函數(shù)會更有優(yōu)勢,以后我們?nèi)绻貜褪褂眠@些代碼都不用在代碼中查找這些函數(shù)的了,直接將整個文件拷貝就可以了,現(xiàn)在我們一起來看看這是怎么實現(xiàn)的。
以上圖片中展示的就是這種模塊化的做法,在項目中將不同作用的代碼放在不同的文件夾下,將不同模塊的代碼放在不同的***.c文件里面,這樣后續(xù)修改,調試,移植代碼的效率就會大大提高。那這種做法是怎么實現(xiàn)的呢,之前我們在介紹C語言文件時說過C語言文件主要有兩種,即.c和.h文件,.c文件我們稱它問源文件,.h文件我們稱為頭文件,在源文件中我們存放各種變量或功能函數(shù)的定義等內(nèi)容,在頭文件中聲明對應的變量、函數(shù)或宏定義等等,所以一般情況下源文件和頭文件都是成對出現(xiàn)的。若某個文件需要使用另一個文件中定義的函數(shù)時就在該文件頭部添加另一個文件對應的頭文件,這樣就可以實現(xiàn)各部模塊程序相互調用了。通過源文件和頭文件分離,當你遇到有一些代碼文件你不想給別人知道,但又要發(fā)布給別人,這種情況下也有對應的處理辦法,具體的做法我們后面再介紹。
一般情況下在不同的源文件中我們也會像之前些函數(shù)一樣對該文件做一些注釋描述,比如:
/**** (C) COPYRIGHT *********
- 文件名 :****
- 描述 :****
- 操作系統(tǒng) :****
- 軟件平臺 :****
- 硬件基礎 :****
- 庫版本 :****
- 作者 :****
- 版本編號 :****
- 修改時間 :****
- 修改說明 :****
**********************************/
當然你也可以不用寫這么多內(nèi)容,以你能看懂為準。
接下來
多任務編程
一般情況下我們在使用 51、AVR、STM32等單片機編程的時候都是在main函數(shù)里面用while(1)做一個大循環(huán)來完成所有的處理,即應用程序是一個無限的循環(huán),循環(huán)中調用相應的函數(shù)完成所需的處理。有時候我們也需要用到中斷來完成一些功能操作。相對于多任務系統(tǒng)而言,這個就是單任務系統(tǒng),也稱作前后臺系統(tǒng),中斷服務函數(shù)作為前臺程序,大循環(huán)while(1)作為后臺程序。
類似一下的做法:
void IRQHandler_fun()
{
flag1 = 1;
}
int main (void)
{
while(1)
{
if (1 = flag1)
{
func1();
flag1 = 0;
}
}
}
這種做法在一般項目中是完全沒有問題的,但是這種程序結構的一個缺陷是它的前后臺系統(tǒng)的實時性不強,前后臺系統(tǒng)各個任務(應用程序)都是排隊等著輪流執(zhí)行,不管你這個程序現(xiàn)在有多緊急,沒輪到你就只能等著!相當于所有任務(應用程序)的優(yōu)先級都是一樣的。在小項目中前后臺系統(tǒng)簡單,資源消耗也少,單片機處理起來還得心應手!但在稍微大一點的嵌入式應用中前后臺系統(tǒng)對實時性要求較高的應用中就明顯力不從心了。這時候就需要進行多任務處理了,就像一下的做法:
void first_task()
{
while (1)
{
if(has_data())
put_data();
}
}
void second_task()
{
while (1)
{
if(get_data())
do_something();
}
}
int main(void)
{
create_task(first_task);
create_task(second_task);
start_task();
}
相信細心的朋友一眼就能發(fā)現(xiàn),這種做法很明顯的不一樣就是每個任務函數(shù)中都有一個while (1)死循環(huán),是不是我們只要在程序中多使用一些while (1)死循環(huán)就OK了呢?簡單說可以這么認為吧,當然實際情況肯定不會這么簡單。
那多任務編程是怎么實現(xiàn)程序功能的呢?多任務系統(tǒng)把一個大問題“分而治之”,把大任務劃分成很多個小問題,逐步的把小任務解決掉,大任務也就隨之解決了,這些任務是并發(fā)處理的。注意,并不是說同一時刻一起執(zhí)行很多個任務,畢竟我們單片機項目都是使用單核芯片,任意時刻它也只能存在一個任務占用其內(nèi)核,它是由于每個任務執(zhí)行的時間很短,導致看起來像是同一時刻執(zhí)行了很多個任務一樣。
看了以上內(nèi)容是不是感覺多任務編程非常的難?其實難肯定是難,但也沒有那么難,因為現(xiàn)在有非常多開源多任務系統(tǒng)供我們選擇,比如freeRTOS,RT-Thread,UC/OS等等,所以就不用我們自己從零寫一個多任務系統(tǒng)了,使用時選擇一個合適的系統(tǒng)進行移植就能減少很多工作量了。
像以上這個項目,調用freeRTOS來實現(xiàn)程序功能。當然這種編程思維不是一兩天就能掌握,需要一定的項目經(jīng)驗,所以初學者理解起來困難并不要緊,要緊的是自己需要把C語言基礎掌握好,基礎牢固了編程就有感覺了。
面向對象編程
前面介紹C語言基礎時我們說過編程語言主要有面向過程和面向對象兩種,C語言是典型的面向過程的一種編程語言。你們你可能就會想為什么我們使用C語言開發(fā)單片機程序還需要面向對象的編程思維呢,是要使用面向對象的編程語言來開發(fā)了嗎?當然不是,我們還是使用C語言來編程,只是呢,在編程時我們按面向對象的方式來處理其相關功能,簡單的說就是把C語言通過一定的處理技巧封裝成像面向對象的編程語言一樣來執(zhí)行程序功能。
對于流程清晰的簡單程序,一般只有一條流程主線,很容易被劃分成順序執(zhí)行的幾個步驟,面向對象編程和面向過程編程沒有太大差別,并且面向過程編程相對比面向對象編程更加直觀高效。
當我們面對一個大型的復雜程序,由于其錯綜復雜的流程和交互關系,很難將其簡單地拆分成一條主線串成的簡單步驟,而通常表現(xiàn)為一個網(wǎng)狀關系結構。這個時候,面向過程編程的這種流程化和線性化的思維方式就會顯得比較吃力,而面向對象編程的優(yōu)勢就比較明顯了。
這也是為什么說面向對象的編程語言是更高級的語言的原因之一,面向對象編程風格的代碼更容易復用、擴展和維護、更高級、更人性化、更適合大規(guī)模復雜程序的開發(fā)。在C語言編程的一些操作系統(tǒng)(包括Unix,linux以及Windows等等)中就會用到的面向對象的編程方式,里面有很多的結構體、指針、鏈表等內(nèi)容。如果還沒有接觸到面向對象編程只能說明你做的東西還不夠復雜。當然也不是非要掌握這個技能你才能進行項目開發(fā),只是你掌握了這些技能你就能開發(fā)更復雜的工程了。你的薪酬肯定也會比其他人高。
我們想來看看一些簡單的面向對象編程代碼:
以上是STM32某系列芯片官方標準庫函數(shù)中的部分片段代碼。
這是freeRTOS中任務創(chuàng)建的函數(shù),對于初學者來說這些咋看都是很深奧的內(nèi)容,所以這里也不需要你現(xiàn)在就掌握它,以后你有機會接觸它們,現(xiàn)在知道有這么回事就好了?,F(xiàn)在總不至于哪天面試的時候被人問你一句你是否嘗試過面向對象開發(fā)單片機程序時自己啥話都說不上來。
這是微軟某個版本的某文件的某段源碼,看起來很復雜吧,說實話這段代碼我也沒細看,細看也一時不可能看明白,只是剛好看到就這個就貼上來跟大家一起分享一下。
評論