1、Click to edit Master title style,Click to edit Master text styles,Second level,Third level,*,第,4,章,Keil C51,程序设计,2,主要内容,:,C51,语言程序设计基础,2,C51,语言的编程技巧,4,1,Keil C51,编程语言,1,C51,语言程序设计方法,3,4.1 Keil C51,编程语言,Keil C51(,由美国,Keil Software,公司推出,),是目前最流行的,51,系列单片机,C,语言软件开发平台,具有程序的编辑、编译、连接、目标文件格式转换、调试和模拟仿真等功能。,
2、C51,是其中的一个编译器,它具有,ANSIC,标准,C,所有的功能,并针对,51,系列单片机的硬件特点做了扩展。本章首先介绍了,Keil,Vision4,的使用方法,随后对标准,C,的基本语法做了概括性的介绍,重点阐述了,C51,的扩展功能,使具有,C,语言基础的读者能尽快掌握,C51,程序的编写方法。,3,4.1.1 Keil C51,的简介,Keil C51,语言是在,ANSI C,的基础上针对,51,单片机的硬件特点进行的扩展,并向,51,单片机上移植,经过多年努力,,C51,语言已经成为公认的高效、简洁而又贴近,5 1,单片机硬件的实用高级编程语言。,目前大多数的,51,单片机用户都
3、在使用,C51,语言来进行程序设计。用,C51,进行单片机软件开发,有如下优点:,4,4.1.1 Keil C51,的简介,(1),可读性好。,(2),模块化开发与资源共享。,(3),可移植性好。,(4),代码效率高。,5,4.1.2 Keil C51,的开发环境,Keil,公司目前已推出,V7.0,以上版本的,C51,编译器,为,5 1,单片机软件开发提供了全新的,C,语言环境,同时保留了汇编代码高效、快速的特点。现在,,Keil C51,已被完全集成到一个功能强大的全新集成开发环境,(IDE),Vision4,中,该环境下集成了文件编辑处理、编译链接、项目管理、窗口、工具引用和仿真软件模拟
4、器以及,Monitor51,硬件目标调试器等多种功能,这些功能均可在,Keil,Vision4,环境中极为简便地进行操作。,本章用到,Keil C51,和,Keil,Vision4,两个术语。分别是,51,单片机编程所用的,C,语言和,51,单片机的,C51,程序编写、调试的集成开发环境。,6,4.1.3 Keil,Vision4,初步应用方法,使用汇编语言或,C,语言要用到编译器,以便把写好的程序编译为机器码,随后才能把,HEX,可执行文件写入单片机内。,Keil uVision4,是众多单片机应用开发软件中最新、最优秀的软件之一,它支持众多不同公司的,MCS51,架构的芯片,甚至,ARM,
5、系统,它集编辑,编译,仿真等多种功能于一体,它的界面和常用的微软,VC+,的操作界面相似,人机交互友好,易学易用,在调试程序,软件仿真方面也有很强大的功能。,7,建立第一个,Keil,Vision4 C,语言项目,运行,Keil,Vision4,的首个画面:,8,(,1,)在,Project,菜单,选择弹出的下拉式菜单中的,New Project,,创建新的,Vision,项目。注意,这里的项目文件扩展名是,uvproj,。,(,2,)选择所要的单片机,这里我们选择常用的,MCU,单片机芯片是,Ateml,公司的,AT89C51,。,(,3,)创建新的程序文件,如,例,4-1,的串口输出字符串
6、Hello World,!,”,程序,。,9,10,【,例,4-1,】串口输出字符串,“Hello World,!,”,#include,#include,void main(void),SCON=0 x50;/,串口方式,1,允许接收,TMOD=0 x20;/,定时器,1,定时方式,2,TCON=0 x40;/,设定时器,1,开始计数,TH1=0 xE8;/11.0592MHz 1200,波特率,TL1=0 xE8;,TI=1;,TR1=1;/,启动定时器,while(1),printf(Hello World!n);/,显示,Hello World,!,11,(,4,)保存新建的,C,
7、语言程序,可以用,File,菜单的,Save,或快捷键,Ctrl+S,进行保存。如图,4-3,所示,我们把第一个程序命名为,example801.c,,保存在项目所在的目录中。如图,4-3,鼠标在屏幕左边,project,项目区域中的,Target 1,,点击其左侧的,+,号;然后,在,Source Group1,文件夹图标上右击弹出菜单,在这里可以实现在项目中增加减少文件等操作。我们点击,Add File to Group Source Group 1,弹出文件窗口,选择刚刚保存的,example801.c,文件,按,ADD,按钮,实现添加,example801.c,文件到项目工程,如图,4
8、4,所示;然后,点击,CLOSE,按钮,实现关闭文件窗口并退出。这时在,Target 1,项目文件夹下的,Source Group1,文件夹图标左边出现了一个小,+,号说明,文件组中有了文件,点击它可以展开查看。,12,13,(,5,)设置,Options for Target Target1,在,Project,下拉菜单中或者在,Target 1,图标上点击右键,打开,Options for Target Target1,,弹出项目选项设置窗口。如图,4-5,所示,,Output,选项页中,1,是选择编译输出的路径,,2,是设置编译输出生成的文件名,,3,则是决定是否要创建,HEX,文件,
9、选中它就可以输出,HEX,文件到指定的路径中。,Debug,选项页如图,4-6,所示,由于本章内容不涉及到,Proteus,仿真和单片机开发板烧录,,Debug,选项页中均保持如图显示的默认值即可。,14,15,(,6,)项目的编译运行,(7),进入调试模式,在下拉菜单,Debug,中,StartStop Debug Session,,或者,快捷键为,Ctrl+F5,。点击下拉菜单,Debug,中的,Run,,或者,快捷键,F5,,程序连续运行。显示内容见图,4-8,,在此画面中同时打开了了,Serial Windows,,以观察字符串的输出情况。图中,1,为运行按钮,当程序处于停止状态时才有
10、效,图中,2,为停止按钮,程序处于运行状态时才有效。图中,3,是复位按钮,模拟芯片的复位,程序回到最开头处执行。按图中的,Peripherals,下拉菜单中我们可以打开串行调试窗口,如图,4,所示。这个窗口我们可以看到从,51,芯片的串行口输入输出的字符,,“Hello World,!,”,。最后我们要停止程序运行回到文件编辑模式中,就要先按停止按钮再按,StartStop Debug Session,开启,关闭调试模式按钮。,16,17,4.2 MCS-51,单片机,C51,语言程序设计基础,在单片机应用系统开发过程中,应用程序设计是整个应用系统开发的重要组成部分,它直接决定着应用系统开发周
11、期的长短、性能。尽管采用汇编语言编写的应用程序可直接操纵系统的硬件资源,能编写出较高运行效率的程序代码,程序运行速度快。但因汇编语言学习困难、可读性差、修改调试困难,且编写比较复杂的数值计算程序非常复杂。因此,为了提高编制单片机系统和其应用程序的效率,改善程序的可读性和可移植性,最好采用高级语言编程,及类似于,C,语言的单片机开发语言。,18,4.2.1 C51,与,MCS-51,汇编语言的比较,C51,语言能直接对计算机的硬件进行操作,与汇编语言相比它具有如下优点:,(1)C51,要比,MCS-51,汇编语言的可读性好。,(2),程序由若干函数组成,为模块化结构。,(3),使用,C51,编写
12、的程序可移植性好。,(4),编程及程序调试的时间短。,(5)C51,中的库函数包含了许多标准的子程序,(6),对单片机中的寄存器分配、不同存储器的寻址以及数据类型等细节可由编译器来管理。,汇编语言的特点如下:,(1),代码执行效率高。,(2),占用存储空间少。,(3),可读性和可移植性差。,19,4.2.2 C51,与标准,C,的主要区别,(1),头文件的差异。,Keil C51,系列的头文件集中体现了各系列芯片的不同资源及功能。,(2),数据类型的不同。,51,系列单片机包含位操作空间和丰富的位操作指令。,(3),数据存储类型的不同。,51,系列单片机有片内、外程序存储器,还有片内、外数据存
13、储器。,(4),标准,C,语言没有处理单片机中断的定义。,(5)Keil C51,与标准,C,的库函数有较大的不同。,(6),程序结构的差异。,20,因此,,C51,语言。它与传统的、通用的像,K&R,(,Kernighan,和,Ritchie,)所著的,C,语言是有所区别的。,Thompson,(左)和,Ritchie,(中)于,1999,年接受当时美国总统克林顿授予的国家技术勋章。,21,4.2.3,C51,数据类型与,MCS 51,的存贮方式,1,C51,的字符集、标示符与关键字,(,1,)字符集和词汇,(,2,)标识符,(,3,)关键字,以下是标准,C,规定的关键字:,auto bre
14、ak case char const ontinue default do double else enum extern float for goto if int long register return short signed static struct switch typedef union unsigned void volatile while,以下是,C51,扩展的关键字:,_at_ alien bdata bit code compact data idata interrupt large pdata _priority_ reentrant sbit sfr sfr16
15、 small _task_ using xdata,22,2,C51,常量与变量的数据类型,23,数据类型,长度(,bit,),长度(,byte,),数据表示域,bit,1,1/8,0,,,1,unsigned char,8,1,0255,signed char,8,1,128127,unsigned int,16,2,065535,signed int,16,2,3276832767,unsigned long,32,4,04294967295,signed long,32,4,21474836482147483647,float,32,4,1.176E,383.40E+38,(,6,位数字
16、double,64,8,1.176E,383.40E+38,(,10,位数字),指针类型,24,3,存贮空间,065536,表,4-1 C51,编译器的数据类型,(,1,)常量,整型常量,整型常量即整常数又称为标量,有,3,种表示形式:,八进制整数,,,十六进制整数,,,十进制整数。,字符型常量,普通字符,和,转义字符,。,常用转义字符及其含义,见后页表:,字符串常量,实型常量,24,转义字符,含义,ASCII,码(,16/10,进制数),0,空字符,(NULL),00H/0,n,换行符,(LF),0AH/10,r,回车符,(CR),0DH/13,t,水平制表符,(HT),09H/9,b,
17、退格符,(BS),08H/8,f,换页符,(FF),0CH/12,单引号,27H/39,双引号,22H/34,反斜杠,5CH/92,25,(,2,)变量,变量定义格式,51,系列单片机有内部,RAM,、,SFR,、外部,RAM/IO,、程序存贮器等存贮区域,为了能访问不同存贮区域的变量,,C51,对变量的定义增加了存贮器类型说明。变量定义的一般格式为:,存贮种类,数据类型,存贮器类型,变量名(或变量名表);,定义格式中的方括号部分,是可选项,可有可无。,26,整型变量:整型变量的类型符为,int,,有以下,4,种:,有符号基本整型,signed int,无符号基本整型,unsigned int
18、有符号长整型,long int,无符号长整型,unsigned long int,字符型变量,有符号字符型,signed char,无符号字符型,unsigned char,实型变量,C51,支持单精度实型变量,长度为,4,字节,类型符为关键字,float,,又称为浮点型。,27,3,C51,数据变量在,MCS,51,中的存贮方式,C51,语言运行的平台是,MCS-51,单片机。所以,,C51,编译器要用一系列机器指令对其进行复杂的数据类型处理。在实际编程时最好采用无符号型数据和尽量少的数据变量类型,这样将明显提高代码的运行效率。,位型变量,字符型变量,整型变量,长整型变量,28,浮点数量,
19、数的表示方法可分为定点表示和浮点表示。,浮点数则是小数点的位置是浮动的。通常,对于任意一个二进制数,X,,都可表示成:,X,=2,E,M,式中:,M,表示全部有效数字,称之为数,X,的尾数;,E,为数,X,的阶码,它指明了小数点的位置;,2,是阶码的底。,M,和,E,均为用二进制表示的数,它们可正可负。阶码常用补码表示法,尾数常为原码表示的纯小数。当,E,值可变时,表示是浮点数。,29,(,1,),C51,数据的存贮类型,C51,存贮类型与,MCS,51,实际存贮空间的对应关系,30,4,C51,数据的存贮类型与,MCS,51,单片机的存贮关系,存贮类型,与,MCS,51,系列单片机存贮,空间
20、的对应,关系,备,注,data,直接寻址片内数据存贮区,访问速度快,片内,RAM,的,00H7FH,区域,bdata,位寻址片内数据存贮区,允许位与字节混合访问,片内,RAM,的,20H2FH,区域,idata,间接寻址片内数据存贮区,可访问片内全部,RAM,,用,R0,,,R1,间接访问,片内全部,RAM,,即,00H0FFH,区域,pdata,由,MOVX R0,,,R1,间接访问,分页寻址片外数据存贮区,每页,256,字节,即,00H0FFH,区域,xdata,由,MOVX DPTR,访问的片外数据存贮区,,64KB,空间,外部,64K RAM 0000H0FFFFH,区域,code,程
21、序存贮区,,64KB,空间,由,MOVC DPTR,访问,外部,64K ROM 0000H0FFFFH,区域,(,2,),C51,存储模式,存贮模式决定了变量的默认存贮器类型、参数传递区和无明确存贮区类型的说明,等,,存贮器模式说明如表,31,存贮器模式,说,明,SMALL,默认的存贮类型为,data,,参数及局部变量放入可直接寻址的片内,RAM,中。另外,所有对象(包括堆栈),都必须嵌入片内,RAM,中。,COMPACT,默认的存贮类型为,pdata,,参数及局部变量放入分页的外部,RAM,,通过,R0,或,R1,间接访问,堆栈空间位于片内,RAM,中。,LARGE,默认的存贮类型为,xda
22、ta,,参数及局部变量放入外部,RAM,,使用数据指针,DPTR,来进行寻址,用此指针访问效率较低。堆栈空间也位于外部,RAM,中。,C51,允许在变量类型定义之前指定存贮模式。书写格式上,定义,data char x,与定义,char data x,是等价的,但应尽量使用后一种方法。,在,C51,中有两种方法来指定存贮模式,例如,以下为两种方法来指定,COMPACT,模式:,方法,1,:在编译时指定。如使用命令,C51 PROC.C COMPACT,方法,2,:在程序的第一句加预处理命令,#pragma compact,32,5,MCS,51,特殊功能寄存器(,SFR,)及其,C51,定义方
23、法,(,1,),MCS,51,系列单片机中,除了程序计数器,PC,,片内,RAM,低,128,个字节空间和,4,组工作寄存器组外。其它所有的寄存器均为特殊功能寄存器(,SFR,),离散地分布在片内,RAM,高,128,个字节中,地址范围为,80H0FFH,。,SFR,中地址为,8,的倍数的寄存器具有位寻址能力。为了能直接访问,SFR,,,C51,编译器提供了一种与标准,C,语言不兼容,而只适用于对,MCS,51,系列单片机进行,C,语言编程的,SFR,定义方法,其定义,8,位,SFR,语句的一般格式为:,sfr sfr-name=int constant,;,33,(,2,)由于,SFR,中地
24、址为,8,的倍数的寄存器具有位寻址能力,在,C51,中规定了支持,SFR,位操作的定义,当然这也是与标准,C,语言不兼容的,使用,“sbit”,来定义,SFR,的位寻址单元。定义,SFR,的位寻址单元的语法格式有,3,种:,第,1,种格式:,sbit bit-name=sfr-name int constant,第,2,种格式:,sbit bit-name=int constant int constant,第,3,种格式:,sbit bit-name=int constant,34,(,3,),MCS,51,位变量及其,C51,定义方法,位变量的,C51,定义的方法,C51,通过,“bit”
25、关键字来定义位变量,一般格式为:,bit bit-name,;,C51,程序函数的参数及返回值,C51,程序函数可包含类型为,“bit”,的参数,也可以将其作为返回值。例如:,bit func,(,bit b0,,,bit b1,),/*,位变量,b0,、,b1,作为函数的参数,*/,return,(,b1,);,/*,变量,b1,作为函数的返回值,*/,35,对位变量的限制,位变量不能说明为指针和数组。例如:,bit*ptr,;,/*,用位变量定义指针,错误,*/,bit b-array,;,/*,用位变量定义数组,错误,*/,在定义位变量时,允许定义存贮类型,位变量都被放入一个位段,此段
26、总位于,MCS,51,系列单片机片内,RAM,中,因此其存贮类型限制为,data,或,idata,,如果将其定义成其它类型都将在编译时出错。,36,4.2.4 MCS,51,并行接口及其,C51,定义方法,MCS,51,系列单片机片内有,4,个并行,I/O,口(,P0P3,),因这,4,个并行,I/O,口都是,SFR,,故这,4,个并行,I/O,口的定义采用定义,SFR,的方法。另外,,MCS,51,系列单片机在片外可扩展并行,I/O,口,因其外部,I/O,口与外部,RAM,是统一编址的,即把一个外部,I/O,口当作外部,RAM,的一个单元来看待。,利用绝对地址访问的头文件,absacc.h,
27、可对不同的存贮区进行访问。该头文件的函数有:,CBYTE,(访问,code,区字符型),DBYTE,(访问,data,区字符型),PBYTE,(访问,pdata,区或,I/O,口字符型),XBYTE,(访问,xdata,区或,I/O,口字符型),37,对于片外扩展的,I/O,口,根据硬件译码地址,将其看作片外,RAM,的一个单元,使用语句,#define,进行定义。例如:,#include /*,必须要,不能少,*/,#define PORTA XBYTE0 xFFC0/*,定义外部,I/O,口,PORTA,的地址为外部,RAM,的,0FFC0H*/,当然也可把对外部,I/O,口的定义放在一个
28、头文件中,然后在程序中通过,#include,语句调用,一旦在头文件或程序中通过使用,#define,语句对片外,I/O,口进行了定义,在程序中就可以自由使用变量名(如,PORTA,)来访问这些外部,I/O,口了。,38,C,语言的运算符有以下几类:算术运算符、逻辑运算符、位操作运算符、赋值运算符、条件运算符、逗号运算符、求字节数运算符和一些特殊运算符。用运算符和括号将运算对象(也称为操作数)连接起来并符合,C,语法规则的式子称为表达式;,C,语言有算术表达式、赋值表达式、逗号表达式、关系表达式、逻辑表达式等。,C,运算符的优先级有,15,级(具体内容见相关通用,C,语言书籍),在表达式求值时
29、按运算的优先级由高至低的次序运算(例如先乘除后加减),若在一个运算分量的两侧出现两个相同优先级的运算待时,则按运算符的结合性处理。有的运算符具有左结合特性,按自左至右的次序计算;有的运算符具有右结合特性,按自右至左的次序运算。,39,4.2.5 C51,的,运算符和表达式,1,算术运算符和算术表达式,(,1,)算术运算符,+,(加)、,-,(减)、,*,(乘)、(除)都是双目运算符;,%,(求余数运算符,也称模运算)为双目运算符;,+,(取正)、,-,(取负)都是单目运算符,具有右结合特性;,+,(自增,1,)、,-,(自减,1,)运算符。自增,1,和自减,1,运算符都是单目运算符,都具有右
30、结合特性,它们只能用于变量的加,1,或减,1,:,+i,;,-j,;,*,先自加,后引用,*,i+,;,j-,;,*,先引用,后自加,*,40,(,2,)算术表达式,由算术运算符、括号将运算对象连接起来的式子称为算术表达式。,例如:,a,、,b,、,x,、,y,都是整型变量,则下式,a+b,、,a*2/x,、,(x+y)*8,都是算术表达式,41,位运算符的功能是对数据进行按位运算,使之能对单片机的硬件直接进行位操作,位运算符只能用于字符型和整型数据,不能用于浮点数。,C51,共有以下,6,种位运算符。,(,1,)按位与运算符,&,(,2,)按位或运算符,|,(,3,)按位异或,(,4,)按位
31、取反,(,5,)左移运算符,42,2.,位运算符和位运算,3.,赋值运算符和赋值表达式,(,1,)赋值运算符和赋值表达式,赋值运算符的符号为,“=”,,其优先级别很低,仅仅高于最低优先级别的,“,,,”,逗号运算符。由赋值运算符将一个变量和一个表达式连起来称为赋值表达式,其一般形式为:,变量,=,表达式;,(,2,)复合赋值运算符及表达式,在赋值运算符,“=”,的前面加上其他双目运算符,就构成复合赋值运算符。,c,的复合赋值运算符有如下十种:,+=,、,-=,、,*=,、,=,、,%=,、,=,、,&=,、,=,、,|=,由复合运算符将一个变量和表达式连起来也构成赋值表达式。一般形式为:,变量
32、双目运算符,=,表达式;,43,“,,,”,逗号是,C,的一种特殊运算符,其功能是把几个表达式连接起来,组成(逗)号表达式,一般形式为:,表达式,1,,表达式,2,,,,表达式,n,;,逗号表达式的功能是依次计算表达式,1,,表达式,2,,,,表达式,n,的值,整个逗号表达式的值为表达式,n,的值。,逗号表达式在,for,(;)循环控制语句中用于对循环变量的初始化,。,44,4.,逗号运算符和逗号表达式,1.C51,语句和程序结构,C51,语句是计算机执行的操作命令,一条语句以分号结尾(注意,:,程序中的变量、函数声明部分尽管不是语句,但也以分号结尾)。从程序流程分析,程序主要有顺序结构、选
33、择结构和循环结构这样三种最基本的结构。而,C,语句有表达式语句、复合语句、控制语句、空语句和函数调用语句等。,45,4.2.6 C51,语句和结构化程序设计,表达式语旬的一般形式为如下:,例如:,x=y+z,;,*,赋值语句,*,i+,;,*,自增,1,语句,*,顺序结构程序由按先后顺序执行的多个语句组成,在,C,语言中,将按顺序执行的多条语句用花括号,括起来构成复合语句,复合语句中每个语句以分号结尾,复合语句花括号后不再加分号。而没有内容,只有分号,不执行任意操作的语句称为空语句。像赋值语句那种不包含其他语句的语句,称为简单语句。,46,2,表达式语句、复合语句和顺序结构程序,(1),关系运
34、算符和关系表达式,比较两个量的大小关系的运算符称为关系运算符,关系运算符有以下,6,种:,(小于)、,(大于)、,.=,(大于等于)、,=,(等于)、!,=,(不等于),关系运算符都是双目运算符,都具有左结合特性。,关系表达式的一般形式为:,表达式,1,关系运算符 表达式,2,(,2,)逻辑运算符和逻辑表达式,逻辑运算符有,&,(逻辑与)、,|,(逻辑或)、!(逻辑非)这样三种。,47,3.,选择语句和选择结构程序,if,语句用来判定所给的条件是否满足来决定执行的两种可能操作之一。,if,话句有,3,种形式。,if(,表达式,),语句;,括号中的表达式一般为关系表达式或逻辑表达式。当表达式的值
35、为非零时,则执行语句;否则,不执行语句。语句可以是简单语句或复合语句。,if(,表达式,),语句,1,;,else,语句,2,;,当括号中的表达式值为非零时执行语句,1,;否则,执行语句,2,。其中的语句,1,和语句,2,可以是简单语句或复合语句。,if,(表达式,1,),语句,1,;,else if(,表达式,2),语句,2,;,:,else if(,表达式,n),语句,n,;,else,语句,n+l,;这种形式的,if,语句可以实现多种条件的选择。,48,(,3,),if,语句,在,if,(表达式)语句,1,;,else,语句,2,;这种形式中,若语句,1,、语句,2,都是给同一个变量赋值
36、则可以用更加简洁的条件表达式来实现。条件表达式的一般形式为:,表达式,1,?表达式,2,:表达式,3,条件表达式求解时,先求表达式,1,的值,若非零(即表达式,1,为真),则求解表达式,2,的值,并作为整个条件表达式的值;如果表达式,1,的值为零(即表达式,1,为假),则求解表达式,3,的值,并作为整个条件表达式的值。,49,(,4,)条件表达式,switch,语句是直接处理多分支的选择语句,其功能类似于,51,的散转指令,JMP A+DPTR,。一般形式为:,switch,(表达式),case,常量表达式,1,:,语句,1,;,case,常量表达式,2,:,语句,2,;,:,case,常量
37、表达式,n,:,语句,n,;,default:,语句,n+l,;,50,(,5,),switch,语句,【,例,4-2,】若在一个应用系统中设置,5,个单字符命令:,A,、,F,、,G,、,W,、,Z,。变量,SIO_IN,为串行口输入的字符。要求设计一个程序,若,SIO_IN,为合法的命令字符求出其命令号,(0,4),,非法字符则置为,0FFH,。设,SIO_IN,、,CMD_N,为已定义的无符号字符型变量,则程序如下:,switch(SIO_IN),*SIO,一,IN,为输入字符变量,*,case A:CMD_N=0;break,;,*CMD N,为命令号,*,case F:CMD_N=l
38、break;,case G:CMD_N=2;break;,case W:CMD_N=3;break;,case Z:CMD_N=4;break;,default:CMD_N=0 xff;,51,(,1,),while,语句,while,语句的一般形式为:,while,(表达式)语句;,52,4,循环语句和循环结构程序,【,例,4-3,】求,S=1+2+3+100,和的程序,请用,while,循环来实现:,#include,void main(),unsigned int s=0,;,*,定义变量并初始化,*,unsigned char i=l,;,while(i=100),s+=i,;,*,
39、循环体为复合语句,*,i+,;,*,修改循环变量,x,printf(s=%dn,s);,53,Do ,语句;,*,循环体,可以是简单语句或复合语句,*,while,(表达式);,*,其后分号不可少,表达式为关系表达式或逻辑表达式,*,【,例,4-4,】求,S=1+2+3+100,和的程序,请用,do-while,循环来实现:,#include,void main(),int i,s;,i=1;s=0;,do,s=s+i;,i=i+1;while(i=100);,printf(s=%dn,s);,54,(,2,),do-while,语句,【,例,4-5,】,P1.1,输出,16,次跳变,产生,8
40、个脉冲,,P1.1,初态为,0,,则程序如下:,unsigned char i=0,;,*,定义循环控制变量,i*,do P1=P10 x02,;,*P1.1,求反,,Pl,口其他位不变,*,i+;,*,修改循环控制变量,*,while(116);,*,;号不可省,*,55,for,语句的一般形式为:,for(,表达式,1,;表达式,2,;表达式,3),语句;,for(,循环变量赋初值;循环条件;循环控制变量修改,),语句,*,循环体,可以是简单语句、复合语句或空语句,*,56,(,3,),for,语句,【,例,4-6,】用,for,语句实现,S=1+2+3+100,的程序。,unsigne
41、d int s,;,*,标准形式,*,unsigned char i,;,for,(,i=1,,,s=0,;,i=100,;,i+,),s+=i,;,unsigned int s=0,;,*,省表达式,l*,unsigned char i=l,;,for,(;,i=100,;,i+,),s+=i,;,unsigned int s,;,*,缺省表达式,3*,unsigned char i,;,for,(,i=l,,,s=0;i=100;,),s+=i;i+;,*,循环体中修改变量,i*,57,goto,话句为无条件跳转语句,一般形式为:,goto,语句标号;,*goto,语句尽量少用,*,bre
42、ak,语句用来从循环体中跳出循环体,终止整个循环。一般形式为:,Break,;,continue,语句用于循环体中,其功能为跳过本次循环中尚未执行的语句,继续下次循环,而不终止整个循环,一般形式为:,Continue,;,58,(,4,),goto,语句、,break,语句和,continue,语句,C51,编译器支持的基本数据类型有:位型(,bit,)、无符号字符(,unsigned char,)、有符号字符(,signed char,)、无符号整型(,unsigned int,)、有符号整型(,signed int,)、无符号长整型(,unsigned long,)、有符号长整型(,sig
43、ned long,)、浮点(,float,)、双精度浮点(,double,),另外,C51,还提供了一些扩展的数据类型,它们是由,C51,支持的基本数据类型按一定的规则组合成的数据类型,称之为构造数据类型。,C51,支持的构造数据类型有:数组、结构、指针、共同体(或者,也称为联合)、枚举等。其实,C51,支持的构造数据类型与标准,C,语言是一样的,对构造数据类型的定义、引用以及运算的规则也与标准的,C,语言相同。,59,4.2.7 C51,构造数据类型,1.,数组,2.,结构体,3.,联合(共用)体,4.,指针,60,数组是相关的同类对象的集合,是一种构造类型的变量。数组中各元素的数据类型必须
44、相同,元素的个数必须固定,数组中的元素按顺序存放,每个元素对应于一个序号(称为下标),各元素按下标存取。数组元素下标的个数由数组的维数确定,一维数组有一个下标,二维数组有两个下标。,(,1,)一维数组的定义,(2),一维数组的引用,(3),一维数组的初始化,61,1.,数组,【,例,4-7,】统计某班学生成绩中,80,分以上,,60,分,80,分,,60,分以下人数的程序。,unsigned char i=0,score_A=0,score_B=0,scroe _F=0;,for,(,;i80)score_A+;,*score_A,统计,80,分以上学生人数,*,else if(student
45、scorei=60)score_B+;,*score_B,统计,60,80,分之间学生人数,*,else score_F+,;,*score_F,统计,60,分以下学生人数,*,62,结构是另一种构造类型数据。通过使用结构可以把一些数据类型可能不同的相关变量结合在一起,给它们一个共同的名称,以方便编程。,(,1,)定义结构类型,定义结构类型的一般形式为:,struct,结构类型名,*struct,为结构类型关键字,*,成员表列,*,对各个成员数据类型声明,*,;,*,分号不能省略,*,例如:定义包含年、月、日的结构类型:,struct date,unsigned int year,;,*3,
46、个成员的数据类型声明,*,unsigned char month,;,unsigned char day,;,;,*,;号不可省略,*,63,2.,结构体的定义与引用,(,2,)定义结构类型变量,定义结构类型以后,再定义这种结构类型的变量。一般形式为:,结构类型名,存贮器类型说明,结构变量名表;,在定义结构类型时同时定义结构变量,一般形式为:,struct,结构类型名,成员表列,变量名表列;,直接定义结构类型变量,64,(,3,)结构变量的引用,对结构变量的成员只能一个一个引用。引用结构变量成员的方法有两种:,用结构变量名引用结构成员,其形式为:,结构变量名,.,成员名,例如:,birth_d
47、ay.year=1960,;,用指向结构的指针引用成员,其形式为:,指针变量名,-,成员名,例如:,birth_day-year=1960,;,65,联合也称为共用体,联合中的成员是几种不同类型变量,它们共用一个存贮区域,任意瞬间只能存取其中的一个变量,即一个变量被修改了,其他变量原来的值也就消失了。,(,1,)定义联合类型和联合类型变量,,,定义形式为:,union,联合类型名,成员表列,变量名表;,(,2,)联合类型变量成员引用,联合类型变量成员的引用方法类似于结构类型变量成员的引用:变量名,.,成员名,66,3.,联合的定义与引用,在,C,语言中,把存放数据的地址称为指针,把存放数据地址
48、的变量称为指针变量。一般的数据变量表示存贮单元内容,而指针变量表示存贮单元的地址。利用指针变量访问数据对象类似于用,DPTR,间接寻址一样地方便。,(,1,)定义指针变量,指针变量也必须先定义后使用,,C51,指针变量定义的一般形式为:,基类型,存贮器类型,*,指针变量名表;,67,4.,指针,C51,支持,“,基于存贮器,”,的指针和,“,通用指针,”,两种指针类型。,基于存贮器的指针,基于存贮器的指针以存贮类型为参量,在编译时确定。用这种指针可以高效地访问指针指向单元的内容。这类指针的长度为,1,个字节(,idata*,,,data*,,,pdata*,)或,2,个字节(,code*,,,
49、xdata*,)。,通用指针,凡是在指针定义时未对指针指向的对象存贮空间进行修饰说明的,编译器都使用,3,个字节的通用指针。一个通用指针可以访问任何变量而不管它在,MCS,51,哪个存贮空间的什么位置。通用指针只在编译和连接,/,定位时才把存贮空间代码和地址填入预留的,3,个字节中。,68,通用指针包括,3,个字节,其中,1,个字节为存贮类型,另,2,个字节为偏移地址。存贮类型决定了对象所占用的,MCS,51,存贮空间,偏移地址指向实际地址。有关通用指针的字节分配、存贮类型编码以及通用指针到具体存贮空间的定位如,“字节分配表”和“存储器类型编码表”,所示。,69,地,址,+0,+1,+2,地址
50、保存内容,存贮器类型,偏移地址高位字节,偏移地址低位字节,存贮器类型,idata,xdata,pdata,data,code,编码值,1,2,3,4,5,(,2,)指针变量的引用,取变量的地址赋给指针变量,C51,中的单目运算符,&,,是取变量地址的运算符,用可以将变量的地址赋给一个指针变量。,引用指针变量间接访问所指向的变量,C51,中指针运算符,*,,为单目运算符,也称间接访问运算符,它可以用指针变量间接访问所指向的变量。,指针变量的加减,1,指针变量的加减,1,是使指针变量指向下一个或上一个变量。所以,指针变量加减,1,,其步进是加减数据类型的长度。,70,C,语言是函数式语言,,C,源






