C语言程序的基本结构.doc_第1页
C语言程序的基本结构.doc_第2页
C语言程序的基本结构.doc_第3页
C语言程序的基本结构.doc_第4页
C语言程序的基本结构.doc_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第5章 C语言程序的基本结构C语言程序是由若干个函数单元组成的,每个函数都是完成某个特殊任务的子程序段。组成一个程序的若干个函数可以保存在一个源程序文件中,也可以保存在几个源程序文件中,最后再将它们连接在一起。C语言程序的扩展名为“.c” ,如“test.c” 等。为了使初学者能彻底弄明白,我们通过实例进行引导,由浅入深。5.1 用函数调用方式完成LED1LED8这8个二极管实现D0、D2、D4、D6及D1、D3、D5、D7的交替点亮的实验,周期约1秒5.1.1 源程序文件在D盘建立一个文件目录(CS5-1),然后建立CS5-1.uv2的工程项目,最后建立源程序文件(CS5-1.c)。输入下面的程序:#include /1/*=2=*/void delay(void)/3/4unsigned int i,j;/5for(i=0;i500;i+)/6/7for(j=0;j121;j+)/8;/9/10/11/=12=void light1(void)/13/14P1=0xaa;/15/16/=17=void light2(void)/18/19P1=0x55;/20/21/*=22=*/void main(void)/23/24while(1)/25/26light1();/27delay();/28light2();/29delay();/30/31/32编译通过后,试验板接通5V稳压电源,将生成的CS5-1.hex文件下载到51 MCU DEMO试验板上的单片机89S51中,注意,标示“LED”的双排针应插上8个短路块。我们看到D0D7这8个二极管中的D0、D2、D4、D6及D1、D3、D5、D7的交替点亮,周期差不多为1S。图5-1为keil C51软件进行仿真时的界面。图5-1 keil c51软件进行仿真时的界面5.1.2 程序分析解释序号1:包含头文件REG51.H。序号2:程序分隔或注释,在“/*”及“*/”之间的内容,程序不会去处理,因此通常可进行文字注释,能增加程序的可读性,当然也可作为程序语句模块之间的分隔。序号3:定义函数名为delay的延时子函数。序号4:delay延时子函数开始。序号5:定义两个无符号整形变量i,j。序号610:两个for语句循环体,作用是延时,由于我们还未学习for语句,因此这里可暂不理会。序号11:delay的延时子函数结束。序号12:程序分隔或注释,在“/”之后的内容,程序也不会去处理,因此也可进行文字注释,能增加程序的可读性,当然也能作为程序模块之间的分隔。但应注意,这种风格的注释,只对本行有效,所以在只需要一行注释的时候,往往采用“/”这种格式。而“/*/”风格的注释,既可用于一行,也可用于多行。序号13:定义函数名为light1 的子函数,该子函数用于点亮D0、D2、D4、D6四个LED。序号14:light1 子函数开始。序号15:向P1口送数0xaa(0xaa为16进制数,相当于汇编语言中的AAH,前缀加0x为C51的风格),这条语句的目的是点亮D0、D2、D4、D6四个LED。序号16:light1 子函数结束。序号17:程序分隔。序号18:定义函数名为light2 的子函数,该子函数用于点亮D1、D3、D5、D7四个LED。序号19:light2子函数开始。序号20:向P1口送数0x55,目的是点亮D1、D3、D5、D7四个LED。序号21:light2子函数结束。序号22:程序分隔。序号23:定义函数名为main的主函数。序号24:main的主函数开始。序号25:while循环语句,这里进行无限循环。序号26:while循环语句开始。序号27:调用light1子函数模块。序号28:调用延时子函数模块。序号29:调用light2子函数模块。序号30:调用延时子函数模块。序号31:while循环语句结束。序号32:main的主函数结束。5.2 C语言程序的组成结构从上面的程序我们可以看出,C语言程序的组成结构如下:预处理命令include功能子函数1delay()函数体功能子函数2light1()函数体功能子函数nlight2()函数体主函数main()主函数体结论:C语言程序是由函数构成的,一个C源程序至少包括一个函数(主函数),一个C源程序有且只有一个名为main()的函数,也可能包含其它函数,因此,函数是C程序的基本单位。函数后面一定有一对大括号“”,在大括号里书写程序。C语言程序总是从main主函数开始执行的,而不管物理位置上这个main()放在什么地方。主函数通过直接书写语句和调用其它功能子函数来实现有关功能,这些功能子函数可以是由C语言本身提供给我们的库函数,也可以是用户自己编写的函数。那么库函数和用户自定义子函数有什么区别呢?简单地说,库函数就是针对一些经常使用的算法,经前人开发、归纳、整理形成的通用功能子函数集供大家使用。而自己编写的功能子函数则称用户自定义功能子函数,显然,用户自定义功能子函数是用户根据自己需要而编写的。可以看出,使用C语言开发产品,可以大量使用库函数而减少用户自己编写程序的工作量,这样,产品开发的速度和质量是汇编语言绝对不能相比的。KeilC51内部有数百个库函数可供我们使用。调用KeilC51的库函数时只需要包含具有该函数说明的相应的头文件即可。5.3 只用主函数完成LED1LED8这8个二极管实现D0、D2、D4、D6及D1、D3、D5、D7的交替点亮的实验,周期约1秒5.3.1 源程序文件在D盘中建立一个文件目录(CS5-2),然后建立CS5-2.uv2的工程项目,最后建立源程序文件(CS5-2.c)。输入下面的程序:#include /1/*=2=*/void main(void)/3unsigned int i,j;/4while(1)/5/6P1=0xaa;/7/=8for(i=0;i500;i+)/9/10for(j=0;j121;j+)/11;/12/13/=14P1=0x55;/15/=16for(i=0;i500;i+)/17/18for(j=0;j120;j+)/19;/20/21/=22/23/24编译通过后,试验板接通5V稳压电源,将生成的CS5-2.hex文件下载到51 MCU DEMO试验板上的单片机AT89S51中,注意,标示“LED”的双排针应插上8个短路块,发现实验效果与CS5-1完全相同。但是我们能看出,此程序的结构条理没有CS5-1的程序来得清晰,一大堆实现各种功能的语句全部放在主函数内,显得有点乱。因此一个设计合理的C语言程序,不仅语句要流畅,而且结构也要简洁明了。5.3.2 程序分析解释序号1:包含头文件REG51.H。序号2:程序分隔。序号3:定义函数名为main的主函数。序号4:主函数开始。定义两个无符号整形变量i,j。序号5:while循环语句,进行无限循环。序号6:while循环语句开始。序号7:向P0口送数0xaa,目的是点亮D0、D2、D4、D6四个LED。序号8:程序语句分隔。序号913:两个for语句循环体,作用是延时。序号14:程序语句分隔。序号15:向P0口送数0x55,目的是点亮D1、D3、D5、D7四个LED。序号16:程序语句分隔。序号1721:两个for语句循环体,作用是延时。序号22:程序语句分隔。序号23:while循环语句结束。序号24:main的主函数结束。5.4 文件包含处理我们还没有解释过预处理命令中的包含头文件REG51.H(即include )。包含头文件即为文件包含处理。所谓“文件包含”是指一个文件将另外一个文件的内容全部复制并包含进来,所以这里的预处理命令虽然只有一行,但C编译器在处理的时候却要处理几十乃至几百行。包含头文件REG51.H的目的是为了要使用P1这个符号,即通知C编译器,程序中所写的P1是指80C51单片机的P1端口而不是其它变量。用记事本打开C:/Keil/C51/Inc/Reg51.h(打开时的文件类型改为所有文件)可以看到这样的一些内容:/*-REG51.HHeader file for generic 80C51 and 80C31 microcontroller.Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.All rights reserved.-*/#ifndef _REG51_H_#define _REG51_H_/* BYTE Register */sfr P0 = 0x80;sfr P1 = 0x90;sfr P2 = 0xA0;sfr P3 = 0xB0;sfr PSW = 0xD0;sfr ACC = 0xE0;sfr B = 0xF0;sfr SP = 0x81;sfr DPL = 0x82;sfr DPH = 0x83;sfr PCON = 0x87;sfr TCON = 0x88;sfr TMOD = 0x89;sfr TL0 = 0x8A;sfr TL1 = 0x8B;sfr TH0 = 0x8C;sfr TH1 = 0x8D;sfr IE = 0xA8;sfr IP = 0xB8;sfr SCON = 0x98;sfr SBUF = 0x99;/* BIT Register */* PSW */sbit CY = 0xD7;sbit AC = 0xD6;sbit F0 = 0xD5;sbit RS1 = 0xD4;sbit RS0 = 0xD3;sbit OV = 0xD2;sbit P = 0xD0;/* TCON */sbit TF1 = 0x8F;sbit TR1 = 0x8E;sbit TF0 = 0x8D;sbit TR0 = 0x8C;sbit IE1 = 0x8B;sbit IT1 = 0x8A;sbit IE0 = 0x89;sbit IT0 = 0x88;/* IE */sbit EA = 0xAF;sbit ES = 0xAC;sbit ET1 = 0xAB;sbit EX1 = 0xAA;sbit ET0 = 0xA9;sbit EX0 = 0xA8;/* IP */ sbit PS = 0xBC;sbit PT1 = 0xBB;sbit PX1 = 0xBA;sbit PT0 = 0xB9;sbit PX0 = 0xB8;/* P3 */sbit RD = 0xB7;sbit WR = 0xB6;sbit T1 = 0xB5;sbit T0 = 0xB4;sbit INT1 = 0xB3;sbit INT0 = 0xB2;sbit TXD = 0xB1;sbit RXD = 0xB0;/* SCON */sbit SM0 = 0x9F;sbit SM1 = 0x9E;sbit SM2 = 0x9D;sbit REN = 0x9C;sbit TB8 = 0x9B;sbit RB8 = 0x9A;sbit TI = 0x99;sbit RI = 0x98;#endif在第4章,我们已经介绍了MCS-51单片机的基本结构,对80C51内部结构应该比较熟悉,因此从中可看出,这里都是一些符号的定义,即规定符号名与地址的对应关系。其中有“sfrP1=0x90; ”一行,即定义P1口与地址0x90对应(0x90是C语言中十六进制数的写法,相当于汇编语言中的90H)。5.5 通用的C语言程序组成结构美国国家标准化协会(ANSI)制订的C语言标准(ANSI C)中规定,函数必须要“先声明,后调用” ,我们在“5.1 用函数调用方式完成LED1LED8这8个二极管实现D0、D2、D4、D6及D1、D3、D5、D7的交替点亮的实验,周期约1秒” 的实验中,是先定义(声明)了几个功能子函数,然后在主函数中进行调用,这样当然没问题。如果将顺序倒一下,将几个功能子函数放在主函数的后面,那么编译时就会出错。这时我们需要进行“先声明,后调用”。下面就是“先声明,后调用”的例子。#include /1/=2void delay(void);,/3void light1(void);/4void light2(void);/5/=6void main(void)/7/8while(1)/9/10light1();/11delay();/12light2();/13delay();/14/15/16/*=17=*/void delay(void)/18/19unsigned int i,j;/20for(i=0;i500;i+)/21/22for(j=0;j121;j+)/23;/24/25/26/=27=void light1(void)/28/29P1=0xaa;/30/31/=32=void light2(void)/33/34P1=0x55;/35/36以上的程序中,序号35为自定义功能子函数的声明,其它可参考“5.1 用函数调用方式完成LED1LED8这8个二极管实现D0、D2、D4、D6及D1、D3、D5、D7的交替点亮的实验,周期约1秒”的程序解释,由于符合ANSI C规定的“先声明,后调用” 原则,因此编译时通过。所以,一个好的习惯是,不管自定义的功能子函数放在什么位置,在程序的开始处总是先进行声明。下面是通用的C语言程序组成结构(主函数可放在功能子函数声明之后的任意位置):预处理命令include功能子函数1声明功能子函数2声明功能子函数n声明功能子函数1delay()函数体主函数main()主函数体功能子函数2ji_light()函数体功能子函数nou_light()函数体5.6 将程序的若干个函数保存在几个源程序文件中,最后再将它们连接在一起,实现D0、D2、D4、D6及D1、D3、D5、D7这8个二极管的交替点亮的实验,周期约1秒5.6.1 实现方法第5章的一开始提到过,组成一个程序的若干个函数可以保存在一个源程序文件中,也可以保存在几个源程序文件中,最后再将它们连接在一起。现在我们具体做一下实验,看看实现的方法。首先我们需建立2个源程序文件CS5-3a.c及CS5-3b.c。CS5-3a.c中输入的是main主函数(若有需要也可输入自定义功能子函数),CS5-3b.c中输入delay、light1、light2这3个自定义功能子函数,将它们分别添加到当前项目组中。为了能在CS5-3a.c文件中使用在CS5-3b.c文件里定义的delay、light1、light2这3个子函数,在程序的开始处(第2、3、4行),我们将这3个子函数声明为外部函数,说明它们已在其它文件中定义。这种做法可将一个大型、冗长的程序文件化解成若干个较小的文件,不仅可读性强,而且将任务分解开来,可同时分配给多个程序员开发,便于装配,大大提高了大型复杂软件的开发速度与质量。5.6.2 源程序文件在D盘建立一个文件目录(CS5-3),然后建立CS5-3.uv2的工程项目,选择芯片并确定选项。单击“文件”菜单,在下拉菜单中选择“新建”,在编辑窗口中输入以下的源程序:#include /1extern void light1(void);/2,声明该函数已在其它文件中定义。extern void light2(void);/3,声明该函数已在其它文件中定义。extern void delay(void);/4,声明该函数已在其它文件中定义。/=5void main(void)/6/7while(1)/8/9light1();/10delay();/11light2();/12delay();/13/14/15将上述源程序保存为CS5-3a.c。再单击“文件”菜单,在下拉菜单中选择“新建”,在编辑窗口中输入以下的源程序:#include /1void delay(void)/2/3unsigned int i,j;/4for(i=0;i500;i+)/5/6for(j=0;j121;j+)/7;/8/9/10/=11=void light1(void)/12/13P1=0xaa;/14/15/=16=void light2(void)/17/18P1=0x55;/19/20将上述源程序保存为CS5-3b.c。单击工程管理器中“Target 1”前的“+”号,出现“Source Group1”后再单击,加亮后右击。在出现的下拉窗口中选择“Add Files to GroupSource Group 1”,在增加文件窗口中选择CS5-3a.c文件,鼠标单击“Add”按钮,这时CS5-3a.c文件加入到Source Group 1这个组;同理,再选择CS5-3b.c文件,鼠标单击“Add”按钮,这时CS5-3b.c文件也加入到Source Group 1这个组,见图5-2。随后关闭此对话窗口。图5-2 添加2个文件到当前项目组下来进行编译,编译通过后,试验板接通5V稳压电源,将生成的CS5-3.hex文件下载到51 MCU DEMO试验板上的单片机89S51中,注意,标示“LED”的双排针应插上8个短路块。我们看到D0D7这8个二极管开始闪亮,其效果与“5.1 用函数调用方式完成LED1LED8这8个二极管实现D0、D2、D4、D6及D1、D3、D5、D7的交替点亮的实验,周期约1秒”完全相同。5.6.3 程序分析解释源程序文件CS5-3a.c的2、3、4行已特别作了注释,其它分析可参考“5.1.2 程序分析解释”。5.7 将程序的若干个函数保存在几个源程序文件中,最后用文件包含的方法将它们连接在一起,实现D0、D2、D4、D6及D1、D3、D5、D7这8个二极管的交替点亮的实验,周期约1秒5.7.1 实现方法我们建立起2个源程序文件CS5-4a.c及CS5-4b.c。CS5-4a.c中输入的是main主函数(若有需要也可输入自定义功能子函数),CS5-4b.c中输入delay、light1、light2这3个自定义功能子函数。为了能在CS5-4a.c文件中使用CS5-4b.c文件,在程序开始的第2行,我们使用了文件包含处理#include CS5-4b.c,将CS5-4b.c包含到CS5-4a.c文件中,在添加文件时只需将CS5-4a.c添加到当前项目组中,CS5-4b.c自然也一起包含到当前项目组中了(见图5-3)。该做法同5.6的做法如出一撤,可方便地将一个大型、冗长的程序文件化解成若干个较小的文件,具有可读性强、开发速度快、开发质量高、装配容易等特点,是开发大型复杂软件的常用方法。5.7.2 源程序文件在D盘建立一个文件目录(CS5-4),然后建立CS5-4.uv2的工程项目,选择芯片并确定选项。单击“文件”菜单,在下拉菜单中选择“新建”,在编辑窗口中输入以下的源程序:#include /1,包含头文件REG51.H,C51库函数/使用尖括号给出路径。#include CS5-4b.c/2,包含文件CS5-4b.c,一般自己编写的文件/都在当前目录(文件夹)下,用双引号给出路径。/=3void main(void)/4/5while(1)/6/7light1();/8delay();/9light

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论