嵌入式模塊化編程、驅(qū)動分離的重要性
來源:zhzht19861011
引言
最后,小組成員都將自己負(fù)責(zé)的模塊寫完并調(diào)試無誤后,由項(xiàng)目組長進(jìn)行組合調(diào)試。
要說的話
模塊即是一個(gè).c 文件和一個(gè).h 文件的結(jié)合,頭文件(.h)中是對于該模塊接口的聲明;
#include …
…
//定義變量
unsigned char value;//全局變量
…
//定義函數(shù)
//這是本模塊第一個(gè)函數(shù),起到延時(shí)作用,只供本模塊的函數(shù)調(diào)用,所以用到static關(guān)鍵字修飾
/********************延時(shí)子程序************************/
static void delay (uint us) //delay time
{}
//這是本模塊的第二個(gè)函數(shù),要在其他模塊中調(diào)用
/*********************寫字符程序**************************
** 功能:向LCD寫入字符
** 參數(shù):dat_comm 為1寫入的是數(shù)據(jù),為0寫入的是指令
content 為寫入的數(shù)字或指令
******************************************************/
void wr_lcd (uchar dat_comm,uchar content)
{}
……
……
/***************************** END Files***********************************/
//聲明全局變量
extern unsigned char value;
//聲明接口函數(shù)
extern void wr_lcd (uchar dat_comm,uchar content); //向LCD寫入字符
……
/***************************** END Files***********************************/
在keil 編譯器中,extern這個(gè)關(guān)鍵字即使不聲明,編譯器也不會報(bào)錯(cuò),且程序運(yùn)行良好,但不保證使用其它編譯器也如此。強(qiáng)烈建議加上,養(yǎng)成良好的編程規(guī)范。
.c文件中的函數(shù)只有其它模塊使用時(shí)才會出現(xiàn)在.h文件中,像本地延時(shí)函數(shù)static void delay (uint us)即使出現(xiàn)在.h文件中也是在做無用功,因?yàn)槠渌K根本不去調(diào)用它,實(shí)際上也調(diào)用不了它(static關(guān)鍵字的限制作用)。
注意本句最后一定要加分號”;”,相信有不少同學(xué)遇到過這個(gè)奇怪的編譯器報(bào)錯(cuò): error C132: 'xxxx': not in formal parameter list,這個(gè)錯(cuò)誤其實(shí)是.h的函數(shù)聲明的最后少了分號的緣故。
#include“l(fā)cd_device.h //包含液晶驅(qū)動程序頭文件,之后就可以在該.c文件中調(diào)用//lcd_device.h中的全局函數(shù),使用液晶驅(qū)動程序里的全局//變量(如果有的話)。
…
//調(diào)用向LCD寫入字符函數(shù)
wr_lcd (0x01,0x30);
…
//對全局變量賦值
value=0xff;
…
某模塊提供給其它模塊調(diào)用的外部函數(shù)及數(shù)據(jù)需在.h 中文件中冠以extern 關(guān)鍵字聲明;
比如上例的變量value就是一個(gè)全局變量,若是某個(gè)模塊也使用這個(gè)變量,則和使用外部函數(shù)一樣,只需在使用的模塊.c文件中包含#include“l(fā)cd_device.h”即可。
#ifdef xxx_GLOBALS
#define xxx_EXT
#else
#define xxx_EXT extern
#endif
#define xxx_GLOBALS
#include "includes.h"
#ifdef OS_GLOBALS
#define OS_EXT
#else
#define OS_EXT extern
#endif
OS_EXT INT32U OSIdleCtr;
OS_EXT INT32U OSIdleCtrRun;
OS_EXT INT32U OSIdleCtrMax;
#define OS_GLOBALS
#include “includes.h”
INT32U OSIdleCtr;
INT32U OSIdleCtrRun;
INT32U OSIdleCtrMax;
extern INT32U OSIdleCtr;
extern INT32U OSIdleCtrRun;
extern INT32U OSIdleCtrMax;
模塊內(nèi)的函數(shù)和全局變量需在.c 文件開頭冠以static 關(guān)鍵字聲明;
比如上例在LCD驅(qū)動模塊.c文件中定義的延時(shí)函數(shù)static void delay (uint us),這個(gè)函數(shù)冠以static修飾,一方面是限定了函數(shù)的作用范圍只是在本模塊中起作用,另一方面也給人傳達(dá)這樣的信息:該函數(shù)不會被其他模塊調(diào)用。
在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。
在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個(gè)本地的全局變量。
在模塊內(nèi),一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。
永遠(yuǎn)不要在.h 文件中定義變量!
/*module1.h*/
int a = 5; /* 在模塊1 的.h 文件中定義int a */
/*module1 .c*/
#include "module1.h" /* 在模塊1 中包含模塊1 的.h 文件 */
/*module2 .c*/
#include "module1.h" /* 在模塊2 中包含模塊1 的.h 文件 */
/*module3 .c*/
#include "module1.h" /* 在模塊3 中包含模塊1 的.h 文件 */
/*module1.h*/
extern int a; /* 在模塊1 的.h 文件中聲明int a */
/*module1 .c*/
#include "module1.h" /* 在模塊1 中包含模塊1 的.h 文件 */
int a = 5; /* 在模塊1 的.c 文件中定義int a */
/*module2 .c*/
#include "module1.h" /* 在模塊2 中包含模塊1 的.h 文件 */
/*module3 .c*/
#include "module1.h" /* 在模塊3 中包含模塊1 的.h 文件 */
硬件驅(qū)動模塊,一種特定硬件對應(yīng)一個(gè)模塊;
軟件功能模塊,其模塊的劃分應(yīng)滿足低偶合、高內(nèi)聚的要求。
???????????????? ?END ?????????????????
關(guān)注我的微信公眾號,回復(fù)“加群”按規(guī)則加入技術(shù)交流群。
點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。
