




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、下面让我们揭开模块化神秘面纱,一窥其真面目。C语言源文件*.c提到C语言源文件,大家都不会陌生。因为我们平常写的程序代码几乎都在这个XX.C文件里面。编译器也是以此文件来进行编译并生成相应的目标文件。作为模块化编程的组成基础,我们所要实现的所有功能的源代码均在这个文件里。理想的模块化应该可以看成是一个黑盒子。即我们只关心模块提供的功能,而不管模块内部的实现细节。好比我们买了一部手机,我们只需要会用手机提供的功能即可,不需要知晓它是如何把短信发出去的,如何响应我们按键的输入,这些过程对我们用户而言,就是是一个黑盒子。在大规模程序开发中,一个程序由很多个模块组成,很可能,这些模块的编写任务被分配到
2、不同的人。而你在编写这个模块的时候很可能就需要利用到别人写好的模块的借口,这个时候我们关心的是,它的模块实现了什么样的接口,我该如何去调用,至于模块内部是如何组织的,对于我而言,无需过多关注。而追求接口的单一性,把不需要的细节尽可能对外部屏蔽起来,正是我们所需要注意的地方。C语言头文件*.h谈及到模块化编程,必然会涉及到多文件编译,也就是工程编译。在这样的一个系统中,往往会有多个C文件,而且每个C文件的作用不尽相同。在我们的C文件中,由于需要对外提供接口,因此必须有一些函数或者是变量提供给外部其它文件进行调用。假设我们有一个LCD.C文件,其提供最基本的LCD的驱动函数LcdPutChar(c
3、harcNewValue);/在当前位置输出一个字符而在我们的另外一个文件中需要调用此函数,那么我们该如何做呢?头文件的作用正是在此。可以称其为一份接口描述文件。其文件内部不应该包含任何实质性的函数代码。我们可以把这个头文件理解成为一份说明书,说明的内容就是我们的模块对外提供的接口函数或者是接口变量。同时该文件也包含了一些很重要的宏定义以及一些结构体的信息,离开了这些信息,很可能就无法正常使用接口函数或者是接口变量。但是总的原则是:不该让外界知道的信息就不应该出现在头文件里,而外界调用模块内接口函数或者是接口变量所必须的信息就一定要出现在头文件里,否则,外界就无法正确的调用我们提供的接口功能因
4、而为了让外部函数或者文件调用我们提供的接口功能,就必须包含我们提供的这个接口描述文件-即头文件。同时,我们自身模块也需要包含这份模块头文件(因为其包含了模块源文件中所需要的宏定义或者是结构体),好比我们平常所用的文件都是一式三份一样,模块本身也需要包含这个头文件。下面我们来定义这个头文件,一般来说,头文件的名字应该与源文件的名字保持一致,这样我们便可以清晰的知道哪个头文件是哪个源文件的描述。于是便得到了LCD.C的头文件LCD.h其内容如下。#ifndef_LCD_H_#define_LCD_H_externLcdPutChar(charcNewValue);#endif这与我们在源文件中定义
5、函数时有点类似。不同的是,在其前面添加了extern修饰符表明其是一个外部函数,可以被外部其它模块进行调用。#ifndef_LCD_H_#define_LCD_H_#endif这个几条条件编译和宏定义是为了防止重复包含。假如有两个不同源文件需要调用LcdPutChar(charcNewValue)这个函数,他们分别都通过#include"Lcd.h”把这个头文件包含了进去&第一个源文件进行编译时候,由于没有定义过_LCD_H_因此#ifndef_LCD_H_条件成立,于是定义_LCD_H_并将下面的声明包含进去。在第二个文件编译时候,由于第一个文件包含时候,已经将_LCD_H
6、_定义过了。因此#ifndef_LCD_H_不成立,整个头文件内容就没有被包含。假设没有这样的条件编译语句,那么两个文件都包含了externLcdPutChar(charcNewValue);就会引起重复包含的错误。不得不说的typedef很多朋友似乎了习惯程序中利用如下语句来对数据类型进行定义#defineuintunsignedint#defineucharunsignedchar然后在定义变量的时候直接这样使用uintg_nTimeCounter=0;不可否认,这样确实很方便,而且对于移植起来也有一定的方便性。但是考虑下面这种情况你还会这么认为吗?#definePINTunsignedi
7、nt*/定义unsignedint指针类型PINTg_npTimeCounter,g_npTimeState;那么你到底是定义了两个unsignedint型的指针变量,还是一个指针变量,一个整形变量呢?而你的初衷又是什么呢,想定义两个unsignedint型的指针变量吗?如果是这样,那么估计过不久就会到处抓狂找错误庆幸的是C语言已经为我们考虑到了这一点。typedef正是为此而生。为了给变量起一个别名我们可以用如下的语句typedefunsignedintuint16;/给指向无符号整形变量起一个别名uint16typedefunsignedint*puint16;/给指向无符号整形变量指针起
8、一个别名puint16在我们定义变量时候便可以这样定义了:uint16g_nTimeCounter=0;/定义一个无符号的整形变量puint16g_npTimeCounter;/定义一个无符号的整形变量的指针在我们使用51单片机的C语言编程的时候,整形变量的范围是16位,而在基于32的微处理下的整形变量是32位。倘若我们在8位单片机下编写的一些代码想要移植到32位的处理器上,那么很可能我们就需要在源文件中到处修改变量的类型定义。这是一件庞大的工作,为了考虑程序的可移植性,在一开始,我们就应该养成良好的习惯,用变量的别名进行定义。如在8位单片机的平台下,有如下一个变量定义uint16g_nTim
9、eCounter=0;如果移植32单片机的平台下,想要其的范围依旧为16位。可以直接修改uint16的定义,即typedefunsignedshortintuint16;这样就可以了,而不需要到源文件处处寻找并修改。将常用的数据类型全部采用此种方法定义,形成一个头文件,便于我们以后编程直接调用。文件名MacroAndConst.h其内容如下:#ifndef_MACRO_AND_CONST_H_#define_MACRO_AND_CONST_H_typedefunsignedintuint16;typedefunsignedintUINT;typedefunsignedintuint;typed
10、efunsignedintUINT16;typedefunsignedintWORD;typedefunsignedintword;typedefintint16;typedefintINT16;typedefunsignedlonguint32;typedefunsignedlongUINT32;typedefunsignedlongDWORD;typedefunsignedlongdword;typedeflongint32;typedeflongINT32;typedefsignedcharint8;typedefsignedcharINT8;typedefunsignedcharbyt
11、e;typedefunsignedcharBYTE;typedefunsignedcharuchar;typedefunsignedcharUINT8;typedefunsignedcharuint8;typedefunsignedcharBOOL;#endif至此,似乎我们对于源文件和头文件的分工以及模块化编程有那么一点概念了。那么让我们趁热打铁,将上一章的我们编写的LED闪烁函数进行模块划分并重新组织进行编译。在上一章中我们主要完成的功能是P0所驱动的LED以1Hz的频率闪烁。其中用到了定时器,以及LED驱动模块。因而我们可以简单的将整个工程分成三个模块,定时器模块,LED模块,以及主函数
12、对应的文件关系如下main.cTimer.c-?Timer.h先给大家讲一下如何在KEIL中建立工程模板吧,这个模板是我一直沿用至今。Led.c-?Led.h在开始重新编写我们的程序之前,希望能够给大家一点启发。卜面的内容就主要以图片为主了。同时辅以少量文字说明。我们以芯片AT89S52为例。工ditJTittw|EXojact|Fl华h.hfiph睚slLm工qoIeJVCS£indQ,"IpSI史雷艮¥isioilFrojact.-.新建一个工程留言X电的trojectoLfkiiiacre.ImportPVisiarilFroject.OpenFrojtct
13、.project选择NewProjectWot单击uVisionProject(enome.fiFileZlitVievPi-oiectPlisk?tr:tk<i'AlsTools£VZS%md>vHelp自卢。电喇三I画苑dejectWorkspace口*昌|巽京pargetIVorh5pocc*®-I二ACoccLKer(1X511rdeadcfEL5AT&LV55ATF?051ATCSS4051AT跌4也A陵53A【W*82b278958253AT6M75122T9X31T3X31X2T3T32TcolstC51DatabaceVendor
14、Oevhe在子项中选中AT89s52厂8Aitcrrocr仲51)iniheco»a51De*crptcrc然后单击OK按钮SC61oo:odFullStotcCMOScontolterwihThooLevelProjonMcravLxk,K"ncz,?ligi/CouHr:,。nterWvScuccs.V/dchdooliiet2DPIRs伙FleJiPcnuiv.2E£D/zOrrchbHANeehoriferGH三|上塔需在弹出来的对话框中,选择是,将启动代码添加到工程中eehomexn:eISlORn:£ilej£ditViewproj
15、ectDebugFlash.PetipheralsJoolsSVCSWindowHelpNew.Ctrl+NCtrliO序SaveAllDeviceDatabase.LicenseMan&gemcat.PrintSetup,.+P昌土小位PrirttPreview=jFi1e|JditVievrProjectfiebugFlashPeripheralsToolsgWCSWindowHelp窗New.Ctrl+K百OpeaCtrl+OCloseQCtrl+Sz4%选聃二&蹇LicenseManagement.CtrH-P文件新建之后,再次点击Fi加菜单并选择SaveAs菜单Pri
16、ntSetup.PrintPrintPreview二丛玲需乐Target1我的电脑在弹出的保存文件对话框中,单击新建文件夹按钮,新建一个空的文件夹网上邻居文件名QI):保存类型:|mFiles(*.*)打开(Q)三取消保存在(I):9我最近的文档3STARTUP.A51曷皿33test桌面r,新建文传人选定(L)我最智打开Q)资源管理器也)搜索在OneNote中作为第记本打开千千播敢(1)千千播放列表&)在新建文件夹上右键单击,选择重命-名文件夹网上邻居我E文件名QI):保存类型a共享和安全HSntgltI递添加到压缩文件3./费添加到"新建文件夹.r打“Ql)/3压缩并./
17、涝压缩到“新建文件夹.2“并£-21一:GroovePolderSynchroniza打开取消ScwivithNortonInt«rn4tcurity发送到如剪切(T)复制C)indinFilec/创建快捷方式)mJ册瞬也)重命名幽eetiornecns|7ileEditViewProjectDebugFlashPeripheralsToolsSVCSWinAowHelpProjectWorkspaceSTARTUPons在SourceGroupl上单击鼠标右键,在弹出的菜单中选择AddFilestoGroupSourceGroup1'RebuildallBuild
18、LtargetgetfilesdLdFilestoGroup,SourceGroup1,RemoveGroup/SourceGroupVanditsTiLess%IncludeX|DependencieseehomeYiT1FileEditViFrojectDbugFl&shFriyheriLsToolsSVCSWindowKelp国国暨爹曷,XS|Target1ProjectWorkspace-玲Target1一-、SourceGroup1A51include<reg52h>voidmain(void)while(1)01D3040506D708在main,c文件中编写我
19、们的主函数代码FileEdiiVievProjectFlashPeripheralsToolsSVCSWindowHelp阈意IH解X电增£5Target1二昆皂m*lrfion;Fa:FaSelectFolderforListings.TargetOutput(ListingserVCCompilerListing:.V.lst,ConditionalSymbolsCPreprocessorListing:AxiC51A51IBL51LocateBI51MiseIDebugUtilities,PageWidth:|120-PageLength:|65切换到Listing选项卡,并单
20、击5d产喋岛由田forWWcodevAssemblerListing:Ax.l$t>Conditional3SymbolsMacros:|FinalexpansiononlyCrossReferencebLirkerLining:Atest.m51VMemoryMap3PublicSymbols3LocalSymbols卜LineNumbersVCommentRecords厂CrossReferencegGeneratedSymbolsMLibrarySymbolsOKCancelDefaultsHelpa&txome因cj-舒Folder:IOtesterK:Docum
21、1;nt«tnd八A赤桌面'Path:srcSTARTUP,test双击选中output文件夹,然后单击OK按钮OKLaneelJJetaultsHelp威|Target1DeviceTargetOutputListingJUserC51A51;BL51LocateBL51MiseDebugUtilitiesSelectFcJdecforListings.*一»*«*«»*«*PageWidth:|120FageLength:1653PCCompilerListing:.V.lstVConditional-Symbolsinc
22、ludeFilesAssemblyCodePCPrepfocessorListing:,V.i最后单击OK按钮VAssemblerLining:xl$tConditional3LinkerListingMe$tm51卜MemoryMap3PublicVL3SymbolsMacros:|Finalexpansiononly!CrossReferenceVLineNumbersPCommentReccxcsCrossReferenceTvGeneratedSymbols2LibrarySymbfilsOKCancelDefaults|=|FileEditYiprojectDebigFlash,re
23、ripheralstoolsSVCSYindowHelp窗kpo电鱼q。:4飞飞题聃I三(胸Xcl1SBuildtarget'Target1'assemblingSTARTUP.Apilingmam.c.linking.PcogcamSize:data=9.0code=17rr.outputtestrr-0Error(s)f0Warnings).山1£"BuildXCommandFindinFiles/ILUa&tWtfWGrGRt£t转到一广t«tjdGlBIHTMLDocument1K0打开整ttetUv2.EQBK文件0KB
24、STARTUP.ASIA51文件7KB谑is:ionPr<»jeat自泰看看我们的HOpton文忤组家形式output文件夹里面保存的是编译过程中的输出文件以及列表和目标文件.而S代文件夹里则是我们的源代码文件(*.c及工h文能home.srcOK,到此一个简单的工程模板就建立起来了,以后我们再新建源文件和头文件的时候,就可以直接保存到文件目录下面了。下面我们开始编写各个模块文件。首先编写Timer.c这个文件主要内容就是定时器初始化,以及定时器中断服务函数。其内容如下。#include<reg52.h>bitg_bSystemTime1Ms=0;/IMS系统时标v
25、oidTimer0Init(void)TMOD&=0xf0;TMOD|=0x01;/定时器0工作方式1TH0=0xfc;/定时器初始值TL0=0x66;TR0=1;ET0=1;voidTime0Isr(void)interrupt1TL0/定时器重新赋初值TH0=0xfc;0x66;g_bSystemTime1Ms=1;/IMS时标标志位置位由于在Led.c文件中需要调用我们的g_bSystemTime1Ms变量。同时主函数需要调用Timer0Init()初始化函数,所以应该对这个变量和函数在头文件里作外部声明。以方便其它函数调用。Timer.h内容如下。#ifndef_TIMER_H
26、_#define_TIMER_H_externvoidTimer0Init(void);externbitg_bSystemTime1Ms;#endif完成了定时器模块后,我们开始编写LED驱动模块。Led.c内容如下:#include<reg52.h>#include"MacroAndConst.h"#include"Led.h"#include"Timer.h"staticuint16g_u16LedTimeCount=0;/LED计数器staticuint8g_u8LedState=0;/LED状态标志,0表示亮,1表示熄灭# defineLEDP0/定义LED接口# defineLED_ON()LED=0x00;/所有LED亮# defineLED_OFF()LED=0xff;/所有LED熄灭voidLedProcess(void)if(0=g
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 理赔业务风险培训效果评估灵活性风险基础知识点归纳
- 构建思政课程教学评价体系的现状及总体形势
- 色彩氛围营造基础知识点归纳
- 构建出版业融合发展的现状及总体形势
- 跨界合作在健美操创新中的应用
- 抽水蓄能产业创新驱动的核心路径
- 2025不锈钢型材采购协议合同
- 智联车市场策略
- 答辩成功实战手册
- 研究生之路全攻略
- 扬尘污染控制工作台帐(扬尘防治全套资料)
- 2021年英语专业四级TEM4考试真题和答案
- 各科室临床路径(卫生部)2022
- 学习宣传贯彻反有组织犯罪法工作经验材料
- 大学生德育论文范文3000字
- 美术作品使用授权书.docx
- 金属轧制工艺学1轧制过程基本参数
- 低压电缆头制作安装施工工艺标准
- 初中英语语法讲解PPT课件(共210页)
- 排骨架检验标准_图文
- 工程变更申请表(ECR)
评论
0/150
提交评论