《模块化编程基础.doc》由会员分享,可在线阅读,更多相关《模块化编程基础.doc(6页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、【精品文档】如有侵权,请联系网站删除,仅供学习与交流模块化编程基础.精品文档.模块化编程基础田欣兴当你在一个项目小组中与人共同开发一个相对较复杂的项目时,意味着你不再单干,你需要与项目小组中的其他成员分工合作,一起完成这个项目。这就要求小组成员各自负责一部分项目。比如:你在项目小组中负责通信模块,其他人负责其他模块,这就需要你将通信这一模块写成一个模块,单独调试,留出接口供其他模块的调用。最后由项目组长整合所有模块。像这些场合就要求将程序模块化。模块化的好处有很多,不仅仅是便于分工,它还有助于程序的调试,有利于程序结构的划分,还增加了程序的可读性和可移植性。程序模块即一个“.c”文件和一个“.
2、h”文件的结合,头文件(.h)中对于该模块接口进行声明。举例说明:假如你用的液晶显示,那么你可能写一个液晶驱动模块,用来实现字符、汉字或者图像的显示,命名为lcd12864.c,该模块的.c文件大体可以写成:/ 模块名称(Module Name):LCD12864驱动模块/ 创建日期(Create Date):2012年12月23日/ 模块功能(Function ):驱动LCD12864进行显示/ 修改日期(Modify Date):/ 其他说明(Others ):#includelcd12864.h/定义变量unsigned char busy;/定义函数/ 函数名称(Function Na
3、me):Lcd_delay_ms/ 创建日期(Create Date ):2012年12月/ 函数功能(Function ):毫秒级延时/ 输入参数(Input ):uint t(065535)/ 输出参数(Output ):无/ 返回信息(Return ):无Static void Lcd_delay_ms(uint t)/程序部分/ 函数名称(Function Name):Lcd_Write/ 创建日期(Create Date ):2012年12月/ 函数功能(Function ):向12864模块写入指令或数据/ 输入参数(Input ):uchar type;0:数据,1:命令ucha
4、r data;发送的数据/ 输出参数(Output ):无/ 返回信息(Return ):无Void Lcd_Write(uchar type; uchar dara)/程序部分/结束注:此处只写出两个函数,一个只在模块内部调用,一个在外部调用。.h文件中给出模块的接口。在.c文件中,第二个函数就是一个接口函数,因为其他的模块会调用它,那么在.h文件中必须将这个函数声明成外部函数(使用extrun关键字修饰),而第一个函数只在本模块中使用(本地函数,用static关键字修饰),因此它是不需要放到.h文件中的。Lcd12864.h文件大体可以写成:/ 模块名称(Module Name):LCD1
5、2864驱动模块/ 创建日期(Create Date):2012年12月23日/ 模块功能(Function ):驱动LCD12864进行显示/ 修改日期(Modify Date):/ 其他说明(Others ):#ifndef _LCD12864_H_#define _LCD12864_H_/声明全局变量/声明接口函数#endif/结束注:1、在keil中即使不使用extern关键字,软件也不会报错,并且程序运行良好,但其他编译器不能保证。 2、.c中的函数只有在其他模块中使用时,才会出现在.h文件中。 3、注意在声明函数时在最后要添加分号。当在main.c文件中使用lcd12864.c中的
6、函数时,只需在main.c中添加一条“#includelcd12864.h/包含液晶驱动程序头文件”即可使用lcd12864.h中声明的所有函数和变量。(二)、某模块提供给其他模块调用的外部函数及其数据需在.h文件中冠以extern关键字声明。全局变量的使用:常规的做法是在.h文件中外部数据冠以extern关键字声明。比如:全局变量year,若某个模块也使用这个变量,只需在使用的.c文件中包含该变量的头文件即可。另一种做法:这个方法只需在头文件中定义一次。方法为:在定义所有全局变量的.h文件中做如下定义:#ifndef xxx_GLOBALS#define xxx_EXT#else#defin
7、e xxx_EXT extern#endif.h文件中每个全局变量都加了xxx_EXT的前缀。Xxx代表模块的名字。该模块的.c文件中有以下定义:#define xxx_GLOBALS#includeincludes.h当编译器处理.c文件时,它强制xxx_EXT为空,(因为xxx_GLOBALS已经定义)。所以编译器会给每个全局变量分配内存空间,而当编译器处理其他.c文件时,xxx_GLOBALS没有定义,xxx_EXT被定义为extern,这样用户就可以调用外部全局变量举例说明:参考uC/OS_II.H#ifndef OS_GLOBALS#define OS_EXT#else#define
8、 OS_EXT extern#endifOS_EXT INT32U OSIdleCtr;OS_EXT INT32U OSIdleCtrRun;OS_EXT INT32U OSIdleCtrMax;同时在uCOS_II.H中有以下定义:#define OS_GLOBALS#includeincludes.h当编译器在处理uCOS_II.C时,它就会使得头文件变成如下所示:INT32U OSIdleCtr;INT32U OSIdleCtrRun;INT32U OSIdleCtrMax;这样编译器就会将这些全局变量分配在内存中。当编译器处理其他.c文件时,由于没有定义OS_GLOBALS,所以OS_
9、EXT被定义为extern。extern INT32U OSIdleCtr;extern INT32U OSIdleCtrRun;extern INT32U OSIdleCtrMax; 在这种情况下,不产生内存分配,而任何.c文件都可以使用这些变量。这样的就只需在.h文件中定义一次就可以了。(三)、模块内部的函数和全局变量需在.c文件开头冠以static关键字声明;Static 是一个相当重要的关键字,他能对函数和变量做一些约束,而且可以传递一些信息。其约束为:被static声明的函数只用于本模块,其信息为:其他模块无法调用static声明的函数Static的作用:1、在函数体,一个被声明为静
10、态的变量在这一函数被调用的过程中维持其值不变;2、在模块内,但在函数体外,一个被声明为静态的变量可以被模块内的任意函数调用,但不能被其他模块调用,它是一个本地的全局变量。3、在模块内,一个被声明为静态的函数,只可被这一模块内的其他函数调用。永远不要在.h文件中定义变量。/*Module1.h*/Int a=5;/*Module2.c*/#includemodule1.h/*Module3.c*/#includemodule1.h以上程序的运行结果是:在模块1.模块2和模块3中,都定义了,整形变量a,a在不同的模块中对应不同的地址单元。正确做法是:/*Module1.h*/Extern int
11、a=5;/*Module1.c*/Int a=5;/*Module2.c*/#includemodule1.h/*Module3.c*/#includemodule1.h这样在模块1、2、3中操作A的话,对应的是同一内存单元。一个嵌入式系统通常包括2类模块:1、硬件驱动模块,一种特定硬件对应一个模块;2、软件功能模块,其模块划分应满足低耦合,高内聚的要求。参考文献:1、 E.W.Dijkstra.Go To Statement Consider Harmful2、 D.L.Parnas.Information Distribution Aspects of Design Merhodology
12、3、 O-J.Dahl and C.A.R hoar.Hierarchical Program Structures4、 J.H.Morris.Protection in Programming Languages5、 N.Wirth.Program Development by Stepwise Refinement6、 B.Liskov.A Design Methodology for Reliable Software Systems7、 W.Wulf and M.Shaw. Global Variable Considered Harmful8、 B.Liskov and S.Zilles.Programming with Abstract Data Types