《单片机应用技术工业和信息化高职高专十二五规划教材立项项目教学课件李海涛MCS51系单片机C语言程序设计》由会员分享,可在线阅读,更多相关《单片机应用技术工业和信息化高职高专十二五规划教材立项项目教学课件李海涛MCS51系单片机C语言程序设计(79页珍藏版)》请在金锄头文库上搜索。
1、在线教务辅导网:在线教务辅导网: :/教材其余课件及动画素材请查阅在线教务辅导网教材其余课件及动画素材请查阅在线教务辅导网QQ:349134187 或者直接输入下面地址:或者直接输入下面地址:第3章 MCS51系单片机C语言程序设计实训任务3 LED显示电路 3.1 C语言与MCS51单片机 3.2 C51的数据与运算 3.3 C51程序根本结构与控制语句 3.4 函数 3.5 C51构造数据类型 实训任务3 LED显示电路任务:将09这十个数循环送P0口七段LED上显示 C51程序: #include reg51.hsbit P20=P20;void mDelay(unsigned int
2、DelayTime) unsigned int j=0;for(;DelayTime0;DelayTime-) for(j=0;j125;j+) ; 实训任务3 LED显示电路void main() unsigned char str10=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90; unsigned char i; P20=1; while(1) for(i=0;i10;i+) P0=stri; mDelay(1000); /*延时1000毫秒*/ 3.1 C语言与MCS51单片机v在进行单片机应用系统的程序设计时,汇编语言是一种常用的
3、软件工具。它能直接操作硬件,指令的执行速度快。但其指令系统的格式受硬件结构的限制很大,程序不易理解,且难于编写与调试,可移植性也差。目前在单片机的开发应用中,已逐渐开始引入高级语言,C语言就是其中的一种。采用C语言不必对单片机的具体硬件结构和指令系统有深入的了解,也能够编出符合硬件实际的程序。 3.1.1 C语言与MCS51单片机v用C语言编写的MCS51单片机应用程序(本书后面简称为C51程序),虽然不用像汇编语言那样须具体组织、分配存储器资源和处理端口数据,但在C51语言编程中,对数据类型与变量的定义,必须要与单片机的存储结构相关联,否那么编译器不能正确地映射定位。v深入理解并应用C51对
4、标准C的扩展是学习C51的关键之一。 3.1.2 C51程序结构 用C语言编写单片机应用程序与标准的C语言程序在语法规那么、程序结构及程序设计方法等方面根本相同,但C51程序与标准的C程序在以下几个方面是不一样: 1C51中定义的库函数和标准C语言定义的库函数不同。标准的C语言定义的库函数是按通用微型计算机来定义的,而C51中的库函数是按MCS-51单片机结构来定义的; 2C51中的数据类型与标准C的数据类型也有区别,在C51中还增加了几种针对MCS-51单片机特有的数据类型;3.1.2 C51程序结构 3C51变量的存储模式与标准C中变量的存储模式不一样,C51中变量的存储模式是与MCS-5
5、1单片机的存储器结构紧密相关; 4C51与标准C的输入输出处理方式不一样,C51中的输入输出是通过MCS-51串行口来完成的,输入输出指令执行前必须要对串行口进行初始化; 5C51与标准C在函数使用方面也有一定的区别,C51中有专门的中断函数。3.2 C51的数据与运算 3.2.1 数据与数据类型 表3-1 Keil Cx51的数据类型数 据 类 型长 度值 域unsigned char1字节(Byte)0255signed char1字节-128+127unsigned int2字节065536signed int2字节-32768+32767unsigned long4字节04294967
6、295signed long4字节-2147483648+2147483647float4字节1.176E-383.40E+38*13字节对象的地址bit1位(bit)0或1sbit1位0或1sfr1字节0255sfr162字节0655363.2.1 数据与数据类型 C51扩展的数据类型(1) bit位型 bit是C51编译器的一种扩充数据类型,利用它可定义一个位变量,但不能定义位指针,也不能定义位数组。它的取值是一个二进制位,不是0就是1。(2)sbit位型 sbit是也是C51编译器的一种扩充数据类型,利用它可从字节中定义一个位寻址对象,来访问片内RAM中的可寻址位或特殊功能存放器中的可寻
7、址位。 3.2.1 数据与数据类型(3)sfr/sfr16特殊功能存放器型 MCS-51单片机内部所有8位的特殊功能存放器都可以用sfr数据类型来访问,占用一个内存单元,值域为0255。而16位的特殊功能存放器用sfr16类型来访问。对可位寻址的特殊功能存放器中的位变量用sbit来定义。3.2.2 常量与变量常量是在程序运行过程中其值不能改变的量。而变量是在程序运行过程中其值可以不断变化的量。一、常量 常量的数据类型可以有整型、浮点型、字符型、字符串型和位标量。常量可用在不必改变值的场合,如固定的数据表、字库等。1整型常量 整型常量可以表示为十进制形式、十六进制形式加上前缀0(读作零)X或0x
8、或八进制形式用数字0作前缀 。长整型常量在数字后面加字母L。2浮点型常量 浮点型常量可表示为十进制形式和指数形式。3字符型常量 字符常量是指用单引号括起来的单个字符。转义字符是一种特殊的字符常量。3.2.2 常量与变量 4字符串常量 字符串常量是由一对双引号括起来的字符序列。系统会在字符串尾部加上转义字符0作为字符串的结束标志。 5位常量 位常量是一位二进制值0或1。 6符号常量 常量也可以用一个符号来表示。符号常量在使用之前必须先作定义。定义方式如下: # define 标识符 常量 /*用预处理命令,把标识符定义为其后的常量值*/ 例 :# define PI 3.14 3.2.2 常量与
9、变量 二、变量 变量数据类型可以选用C51所有支持的数据类型。 在程序中使用变量必须定义后使用,在C51程序设计中,定义一个变量的格式如下: 存储种类 数据类型 存储器类型 变量名表;3.2.2 常量与变量1数据类型 变量的数据类型可以是C51编译器支持的各种数据类型。指定数据类型时要注意变量的数值范围。在程序中应尽可量使用无符号字符变量和位变量。2变量名 变量名即变量的标识,要使用合法的C语言标识符。合法的C标识符由字母、数字和下划线组成,且必须由字母或下划线开头,字母的大小写不等价。在C51编译器中,标识符的有效位数不能超过32位。3.2.2 常量与变量3.存储器类型 MCS-51单片机的
10、存储器结构和一般微型计算机不同,在MCS-51单片机中程序存储器和数据存储严格分开,各有片内和片外两局部,特殊功能存放器和片内数据存储器统一编址。存储器类型就是说明单片机的存储区域情况。存储器类型指定了该变量在MCS-51单片机中使用的存储区域。 Keil C51编译器能识别的存储器类型有data、bdata、idata 、pdata、xdata、code几种。3.2.2 常量与变量存储器类型说 明 data直接寻址的片内RAM低128B,访问速度最快 bdata片内RAM的可位寻址区(20H2FH),允许位和字节混合访问 idata间接寻址访问的片内RAM(256B),允许访问全部片内RAM
11、 pdata用Ri间接访问的片外RAM的低256B xdata用DPTR间接访问的片外RAM,允许访问全部64k片外RAM code程序存储器ROM(64K)空间表3-3 存储器类型3.2.2 常量与变量例: unsigned int code num10=0,1,4,9,16,25,36,49,64,81; unsigned char data x; int idata a=0; sbit flag1=status_10; unsigned char pdata y1; 3.2.2 常量与变量三、特殊功能存放器变量 在C51中,允许用户对这些特殊功能存放器进行访问,访问时必须通过sfr或sf
12、r16数据类型说明符进行定义,定义时指明它们所对应的片内RAM单元的地址,使定义后的特殊功能存放器变量与51单片机的SFR对应。特殊功能存放器变量定义格式如下:sfr 8位特殊功能存放器名=特殊功能存放器字节地址常数;sfr16 16位特殊功能存放器名=特殊功能存放器字节地址常数;例如:sfr PSW=0xd0; sfr16 DPTR=0x82;3.2.2 常量与变量四、位变量 在C51中,允许用户通过位类型符定义位变量。位类型符有两个:bit和sbit。可以定义两种位变量。 bit位类型符用于定义一般的可位处理位变量。它的定义格式如下: bit 位变量名; 位变量的存储器类型只能是bdata
13、、data、idata。即位变量的空间只能是片内RAM的可位寻址区20H2FH,严格来说只能是bdata。例如: bit data a1; /*正确*/bit bdata a2; /*正确*/bit pdata a3; /*错误*/bit xdata a4; /*错误*/3.2.2 常量与变量 sbit位类型符用于定义在可位寻址字节或特殊功能存放器中的位,定义时须指明其位地址,可以是位直接地址,可以是可位寻址变量带位号,也可以是特殊功能存放器名带位号。定义格式如下: sbit 位变量名=位地址常数;例如:sbit CY=oxd7;unsigned char bdata flag;sbit fl
14、ag0=flag0;sfr P1=0x90;sbit P1_0=P10;sbit P1_2=0x902; 3.2.3 绝对地址的访问在C51程序中可以使用存储单元的绝对地址来访问存储器。C51提供了三种访问绝对地址的方法:1使用C51中绝对宏: C51编译器提供了一组宏定义来对51系列单片机的code、data、pdata和xdata空间进行绝对寻址。在头文件absacc.h中定义了8个绝对宏 。宏名为:CBYTE、DBYTE、PBYTE、XBYTE、CWORD、DWORD、PWORD或XWORD。 3.2.3 绝对地址的访问访问形式如下: 宏名地址 其中:CBYTE以字节形式对code区寻址
15、,DBYTE以字节形式对data区寻址,PBYTE以字节形式对pdata区寻址,XBYTE以字节形式对xdata区寻址,CWORD以字形式对code区寻址,DWORD以字形式对data区寻址,PWORD以字形式对pdata区寻址,XWORD以字形式对xdata区寻址。 在程序中,使用预处理命令“include 后就可使用其中定义的宏来访问绝对地址。 3.2.3 绝对地址的访问例如:#include /*将绝对地址头文件包含在文件中*/#define uchar unsigned char #define uint unsigned int void main(void) uchar var1;
16、 uint var2; var1=XBYTE0x0005; /*利用XBYTE0x0005访问片外RAM的0005H字节单元,取单元内容赋值给变量var1*/ var2=XWORD0x0002; /*利用XWORD0x0002访问片外RAM的0004H字单元*/ . 3.2.3 绝对地址的访问2使用C51扩展关键字_at_ 使用_at_对指定的存储器空间的绝对地址进行访问,一般格式如下: 存储器类型 数据类型说明符 变量名 _at_ 地址常数;说明: (1)通过这种绝对地址定义的变量不能被初使化;(2)bit型函数及变量不能用_at_指定。(3)使用_at_定义的变量必须为全局变量。例如:da
17、ta char x1 _at_ 0x40; /*在data区中定义字符变量x1,它的地址为40H*/xdata int x2 _at_ 0x2000; /*在xdata区中定义整型变量x2,它的地址为2000H*/3.2.3 绝对地址的访问3通过指针访问 Keil C51编译器允许使用者规定指针指向的存储段,这种指针叫具体指针。使用具体指针的好处是节省了存储空间。采用具体指针的方法,可以实现在C51程序中对任意指定的存储器单元进行访问。例4-1 通过指针实现绝对地址的访问。#define uchar unsigned char /*定义符号uchar为数据类型符unsigned char*/#
18、define uint unsigned int /*定义符号uint为数据类型符unsigned int*/3.2.3 绝对地址的访问void main(void)uchar data var1;uchar pdata *p1; /*定义一个指向pdata区的指针p1*/uint xdata *p2; /*定义一个指向xdata区的指针p2*/uchar data *p3; /*定义一个指向data区的指针p3*/p1=0x30; /*p1指针赋值,使p1指向pdata区的30H单元*/p2=0x1000; /*p2指针赋值,使p2指向xdata区的1000H单元*/*p1=0xff; /*
19、将数据0xff送到片外RAM30H单元*/*p2=0x1234; /*将数据0x1234送到片外RAM1000H单元*/p3=&var1; /*p3指针指向data区的var1变量*/*p3=0x20; /*给变量var1赋值0x20*/3.2.4 根本运算符和表达式1算术运算符和表达式算术运算符用于各类数值运算。包括加+、减-、乘*、除/、求余或称模运算,%、自增+和自减-共七种。 由算术运算符将各种运算对象连接起来的符合C语言语法的式子称为算术表达式。 3.2.4 根本运算符和表达式2关系运算符和表达式 关系运算符用于比较运算。包括大于、小于=、小于等于、=、=的优先级别相同,高于=和!=
20、,=和!=优先级别相同。关系运算符的优先级低于算术运算符。关系运算符的结合性为左结合。 由关系运算符将两个表达式连接起来的式子称为关系表达式。关系表达式通常用来完成某种条件的判断。关系表达式的结果是逻辑值,即条件成立,结果为“1,不成立时结果为“0。3.2.4 根本运算符和表达式3逻辑运算符和表达式 逻辑运算符用于逻辑运算,包括逻辑与&、逻辑或|、逻辑非!三种。 逻辑与和逻辑或是双目运算符,具有左结合性,逻辑非为单目运算符,具有右结合性。 在逻辑运算符中,逻辑非的优先级最高,逻辑与次之,逻辑或最低。 用逻辑运算符将逻辑量连接起来的式子称为逻辑表达式。其逻辑量可以是任何C合法的表达式。在C语言中
21、,判断真假时,“0为假,“非0为真;计算逻辑量时,真的结果为“1,假的结果为“0。3.2.4 根本运算符和表达式4位运算符和表达式 运用位运算符可以使参与运算的量,按二进制位进行运算。包括位与&、位或|、位非、位异或、左移六种。 由位算符构成的式子为位表达式。注意位运算的对象只能是整型或字符型,不能为实型数据。3.2.4 根本运算符和表达式5赋值运算符和表达式 赋值运算符用于赋值运算,分为简单赋值=、复合算术赋值+=、-=、*=、/=、%=和复合位运算赋值&=、|=、=、=、=三类共十一种。 赋值运算符的优先级与关系运算符、逻辑运算符和位运算符比较级别最低,具有右结合性。 赋值表达式的一般形式
22、: 3.2.4 根本运算符和表达式6条件运算符和表达式 条件运算符“?:是一个三目运算符,也是C语言中的惟一的三目运算,可以把3个表达式连接成一个条件表达式,用于条件求值。一般形式: 表达式1?表达式2:表达式33.2.4 根本运算符和表达式7逗号运算符和表达式 逗号运算符“,用于把假设干表达式组合成一个表达式。一般形式: 表达式1,表达式2,表达式3 逗号运算符在所有运算符中优先级最低,具有左结合性。 用逗号运算符把两个表达式连接起来的表达式称为逗号表达式。 3.2.5 C51的表达式语句和复合语句1表达式语句表达式语句是C语言中最根本的一种语句。在表达式的后边加一个分号“;就构成了表达式语
23、句 ,如: a=b*9; x=8,y=7;2空语句在C语言中有一个特殊的表达式语句,称为空语句,它仅仅由一个分号“;组成。3.2.5 C51的表达式语句和复合语句3复合语句 C程序中经常使用一种复合语句。常用将假设干条语句组合在一起形成一种功能块,这种由假设干条语句组合而成的一种语句就称作复合语句。 复合语句的一般形式为:局部变量定义;语句l;语句2;3.3 C51程序根本结构与控制语句3.3.1 C51程序的根本结构 C语言是一种结构化程序设计语言,以函数为根本单位,每个函数的编程都由假设干根本结构组成。归纳起来C51有三种根本结构:顺序结构、选择结构和循环结构。3.3.2 选择语句 在C5
24、1中,有三种条件语句实现选择结构:if语句、if-else语句、if-else-if语句。另外在C51中还支持多分支结构,多分支结构既可以通过if和if-else语句嵌套实现,可用swith语句实现。3.3.2 选择语句一、if语句if语句是C51中的一个根本条件选择语句,它通常有三种格式:1if表达式 语句 其执行过程是:先计算表达式的值,假设表达式的值为真 (非0),执行其后的语句,假设表达式的值为假(等于0),不执行语句,直接跳过执行后面的程序。例如: if(xy) printf(“x=%dn,x);3.3.2 选择语句2if表达式 语句1 else 语句2 其执行过程是:如果表达式的值
25、为真,执行语句1,表达式的值为假,执行语句2。例如: if(xy) max=x; else max=y;3.3.2 选择语句3if表达式1 语句1else if表达式2 语句2else if表达式3 语句3 else if表达式n-1 语句n-1else 语句n其执行过程是:先判断表达式1的值,如果为真,执行语句1;如果表达式1的值为假,再判断表达式2的值,如果表达式2为真,执行语句2,否那么判断表达式3,如此依次判断下去,假设有表达式成立就执行对应的语句,如果所有表达式都为假,那么执行语句n。3.3.2 选择语句例如:if (score=90) printf(“Your result is
26、an An);else if (score=80) printf(“Your result is an Bn);else if (score=70) printf(“Your result is an Cn);else if (score=60) printf(“Your result is an Dn);else printf(“Your result is an En);3.3.2 选择语句二、switch语句if语句通过嵌套可以实现多分支结构,但结构复杂。switch是C51中提供的专门处理多分支结构的多分支选择语句。它的格式如下:switch 表达式case 常量表达式1:语句1;ca
27、se 常量表达式2:语句2; case 常量表达式n:语句n;default:语句n+1;3.3.2 选择语句例如:switch(score/10)case 10:case 9: printf(“Your result is an An);break;case 8: printf(“Your result is an Bn); break;case 7: printf(“Your result is an Cn); break;case 6: printf(“Your result is an Dn); break;default: printf(“Your result is an En);
28、3.3.3 循环语句1while语句 while语句在C51中用于实现当型循环结构,它的格式如下: while表达式 语句;/*循环体*/ while语句后面的表达式是能否循环的条件,后面的语句是循环体。当表达式为非0真时,就重复执行循环体内的语句;当表达式为0假,那么中止while循环,程序将执行循环结构之外的下一条语句。 3.3.3 循环语句2do while语句 do while语句在C51中用于实现直到型循环结构,它的格式如下: do 语句; /*循环体*/ while表达式; 它的特点是:先执行循环体中的语句,再判别表达式的值。如表达式为非0真,那么再执行循环体,然后又判断,直到有表
29、达式为0假时,退出循环,执行do while结构的下一条语句。 3.3.3 循环语句3for语句 在C51语言中,for语句是使用最灵活、用得最多的循环控制语句,同时也最为复杂。它可以用于循环次数已经确定的情况,也可以用于循环次数不确定的情况。它完全可以代替while语句,功能最强大。它的格式如下: for表达式1;表达式2;表达式3 语句; /*循环体*/for语句后面带三个表达式,它的执行过程如下:1先求解表达式1的值;3.3.3 循环语句2求解表达式2的值,如表达式2的值为真,那么执行循环休中的语句,然后执行第三步的操作,如表达式2的值为假,转到第五步;3求解表达式3;4转到第二步继续执
30、行。5退出for循环,执行下面的一条语句。 在for循环中,一般表达式1为初值表达式,用于给循环变量赋初值;表达式2为条件表达式,对循环变量进行判断;表达式3为循环变量更新表达式,用于对循环变量的值进行更新,使循环变量能不满足条件而退出循环。3.3.3 循环语句 在一个循环的循环体中允许又包含一个完整的循环结构,这种结构称为循环的嵌套。外面的循环称为外循环,里面的循环称为内循环,如果在内循环的循环体内又包含循环结构,就构成了多重循环。在C51中,允许三种循环结构相互嵌套。例4-5 用嵌套结构构造一个延时程序。void delay(unsigned int x)unsigned char j;w
31、hile(x-) for (j=0;j125;j+);3.3.4 break和continue语句1break语句一般形式:break;作用:跳出所在的多分支switch语句,while、do-while、for循环语句提前结束循环。2continue 语句一般形式:continue;作用:continue语句用在循环结构中,用于结束本次循环,跳过循环体中continue下面尚未执行的语句,直接进行下一次是否执行循环的判定。3.3.4 break和continue语句 continue语句和break语句的区别在于:continue语句只是结束本次循环而不是终止整个循环;break语句那么是结
32、束循环,不再进行条件判断。3.4 函数 C程序是由函数构成的,函数相当于其它高级语言中的过程和子程序。一个函数实现一个特定的功能,是独立的,可供主函数或其它函数调用。一个主函数和假设干其它函数的集合构成一个C语言源程序。采用函数结构的编程方法使C语言程序结构清晰,易于编写、阅读和维护。3.4.1 函数的分类 从用户使用的角度,C语言的函数分为库函数和用户自定义函数两种。C语言系统本身提供了非常丰富的库函数供程序调用。用户还可以根据需要编写自定义函数;从函数的形式,函数又分为无参函数和有参函数两种。无参函数在被调用时不需要主调函数将某些数据传递给它;有参函数在被调用时需要主调函数给它传递数据。3
33、.4.2 函数的定义函数定义的一般格式如下:函数类型 函数名形式参数表列 reentrantinterrupt musing n 声明局部 执行局部 前面局部称为函数的首部,后面称为函数体,格式说明:1函数类型 函数类型说明了函数返回值的数据类型。3.4.2 函数的定义2函数名 函数名是用户为自定义函数取的名字以便调用函数时使用。3形式参数表 形式参数表用于列出在主调函数与被调用函数之间进行数据传递的形式参数的数据类型和名称。4声明局部 声明局部主要完成变量的定义、对被调用函数的声明等。 3.4.2 函数的定义5执行局部 执行局部由一系列语句组成,完成函数的具体功能设计。6reentrant修
34、饰符 这个修饰符用于把函数定义为可重入函数。所谓可重入函数就是允许被递归调用的函数。函数的递归调用是指当一个函数正被调用尚未返回时,又直接或间接调用函数本身。一般的函数不能做到这样,只有重入函数才允许递归调用。 3.4.2 函数的定义7interrupt m修饰符 interrupt m是C51函数中非常重要的一个修饰符。在C51程序设计中,中断过程通过使用interrupt关键字和中断号m(031)来实现。中断号对应8051单片机的中断程序的入口地址。当函数定义时用了interrupt m修饰符,系统编译时把对应函数转化为中断函数,自动加上程序头段和尾段,并按MCS-51系统中断的处理方式处
35、理。 3.4.2 函数的定义表3-4 中断号与中断源的对应关系中断号m对应中断源0外部中断01定时/计数器T02外部中断13定时/计数器T14串行口中断5定时/计数器T2631预留值3.4.2 函数的定义例4-6 编写一个用于统计外中断0的中断次数的中断效劳程序extern int x=0;void int0() interrupt 0 x+;3.4.2 函数的定义8using n修饰符修饰符using n用于指定中断效劳程序使用的工作存放器组,其中n的取值为03,表示存放器组号。 对于using n修饰符的使用,注意以下几点:1参加using n后,所有被中断调用的过程都必须使用同一个存放器
36、组,否那么参数传递会发生错误。2using n修饰符不能用于有返回值的函数,因为C51函数的返回值是放在存放器中的。如存放器组改变了,返回值就会出错。3.4.2 函数的定义例4-7 利用定时器T1工作在方式1,完成定时器计算器t_count计数。#include #include extern unsigned int t_count;void timer_int(void) interrupt 1 using 0 TR0=0; TH0=0X3C; TL0=0XB0; TR0=1; t_count+;3.4.3 函数的调用 C语言程序中函数是可以互相调用的。在函数调用时,通过主调函数的实际参数
37、与被调函数的形式参数之间进行数据传递来实现函数间参数的传递。 函数调用的一般形式如下: 函数名实际参数表列; 函数调用中的实参与函数定义中的形参必须在个数、类型及顺序上严格保持一致,以便将实际参数的值正确地传递给形式参数,否那么在函数调用时会产生意想不到的错误结果。 3.4.3 函数的调用按照函数调用在主调函数中出现的位置,函数调用方式有以下三种:1函数语句。把被调用函数作为主调用函数的一个语句。2函数表达式。函数被放在一个表达式中,以一个运算对象的方式出现。这时的被调用函数要求带有返回语句,以返回一个明确的数值参加表达式的运算。3函数参数。此时被调用函数作为另一个函数的实际参数。3.4.3
38、函数的调用 函数调用的前提是被调函数必须已经存在即已定义过。如果使用库函数,需使用预处理命令“#include 将有关函数的信息包含到本文件中。当使用了用户自定义函数时,如果在函数定义之前调用,需要在主调函数中对被调函数进行声明。 在C51中,函数声明(函数原型)一般形式如下: extern 函数类型 函数名形式参数表;3.4.4 函数值 函数的值是指函数被调用之后,执行被调函数体中的程序段所取得并返回给主调函数的值。 函数的值一般通过return语句返回主调函数。return 语句的一般形式为: return 表达式; 或者为: return (表达式); 该语句的功能是计算表达式的值,并返
39、回给主调函数。在函数中允许有多个return语句,但每次调用只能有一个return 语句被执行, 因此只能返回一个函数值 如果被调函数中没有return语句,函数并不是不带回返回值,只是不带回有用的值带回一个不确定的值。为明确表示不带回值,可以用void定义为无类型空类型。3.5 C51构造数据类型3.5.1 数组v数组是一组有序数据的集合。数组中每一个元素的类型相同。数组必须先定义后使用。常用的有一维数组、二维数组和字符数组。v一维数组的定义形式为:v类型说明符 数组名常量表达式;v其中,类型说明符是数组中各元素的数据类型。数组名是用户定义的数组标识符。方括号中的常量表达式表示数据元素的个数
40、,也称为数组的长度。例如:int a10;/*定义一个数组,数组名a,有10个元素,每个元素的类型均为int*/3.5.2 指针v在C语言中把一个变量的地址称为指针。而指针变量是一个变量,其值是另一个变量的地址。v指针变量与其他变量一样,必须选定义后使用。v指针变量定义的一般形式为: 类型说明符 存储器类型 指针变量名;3.5.2 指针 其中,类型说明符定义了指针变量的基类型,说明了该指针变量可以指向的变量的类型。存储器类型是C51的扩展,是可选项。有此项,指针被定义为基于存储器的指针,无此项,被定义为一般指针。 例如:char *p; /*p为一个指向char型变量的指针,而p本身那么依存储
41、模式存放*/char data * str; /*str指向data区中char型数据*/ int xdata * pow; /*pow指向外部RAM的int型整数*/3.5.2 指针v在C语言中为使用指针变量提供了两种运算符:取地址运算符&和取内容运算符*。v取地址运算符&:是单目运算符,其结合性为自右至左,其功能是取变量的地址。v取地址的一般形式为: 指针变量 = &目标变量;v其功能是将目标变量的地址赋给左边的指针变量,使指针变量指向目标变量。例如:vint a;vint *p;vp=&a; /*表示将a的地址赋给p */3.5.2 指针v取内容运算符*是单目运算符,其结合性为自右至左,
42、用来表示指针变量所指的变量。v取内容的一般形式为:v 变量 = *指针变量;v其功能是将指针变量所指向的目标变量的值赋给左边的变量。v例如:vint a,b,*p;vp=&a;v*p=5; /*表示给a赋值5 */vb=*p; /*表示将a的值赋给b*/3.5.3 结构体和联合体一、结构体 结构体是一种构造数据类型,它是将假设干个不同类型的数据结合在一起而形成的集合体。组成该集合体的各个数据称为结构体元素或成员。整个集合体使用一个单独的结构体变量名。一般来说结构中的各个成员之间是存在某种关系的,如时间数据中的时、分、秒,日期数据中的年、月、日等。 结构体变量是取值为结构体这种构造数据类型的变量
43、,结构数据类型和结构体变量都必须选定义后使用。3.5.3 结构体和联合体 定义一个结构体类型的一般形式为: struct 结构名 成员表列 ; 其中,成员表由假设干个成员组成,各个成员可以定义成不同的数据类型,所以必须作类型说明。 3.5.3 结构体和联合体 例如:定义一个时间结构体类型time,它由三个成员hour、min、sec组成。struct timechar hour;char min;char sec;;3.5.3 结构体和联合体 定义好一个结构体类型后,就可以用这种数据类型来定义结构体变量,定义的一般形式为: struct 结构体名 结构体变量名; 例如:定义结构体time类型的
44、变量time1和指针变量pt。 struct time time1 , *pt; 3.5.3 结构体和联合体引用结构体成员的一般格式如下: 结构变量名.结构元素名 或: 结构变量名-结构元素名 其中,“.是结构体的成员运算符。符号-可实现利用指针对结构体变量的引用。如: time1.hour表示结构变量time1中的元素hour,time1.min表示结构变量time1中的元素min。 3.5.3 结构体和联合体二、联合体v在C51语言中,联合体也是一种构造数据类型。联合体与结构体有一些相似之处,它也能够把不同类型的数据组合在一起使用,但它与结构有本质上的不同。在结构中定义的各个成员在一段连续
45、的内存中占用不同的内存单元,在位置上是分开的,一个结构体变量的总长度是各成员长度之和。而联合体中定义的各个成员在内存中都是从同一个地址开始存放,共享一段内存空间,一个联合变量的长度等于各成员中最长的长度。结构体变量中的各个元素可以同时进行访问,联合体变量中的各个元素在一个时刻只能对一个进行访问。 3.5.3 结构体和联合体定义一个联合体类型的一般形式为: union 联合名 成员表列;定义联合体变量,格式如下:union 联合类型名 变量列表;例如:union datafloat i;int j;char k;;union data a,b,c;3.5.3 结构体和联合体 联合体变量中元素的引
46、用与结构体变量中元素的引用格式相同,形式如下: 联合变量名.联合元素或:联合变量名-联合元素 例如:对于前面定义的联合变量a、b、c中的元素可以通过下面形式引用。a.i;b.j;c.k; 分别引用联合变量a中的float型元素i,联合变量b中的int型元素j,联合变量c中的char型元素k. 3.5.4 枚举 如果一个变量只有几种可能的值,可以定义为枚举类型。所谓“枚举就是将变量的值一一列举出来,变量的取值只限于列出的范围。枚举类型定义的一般形式为:enum 枚举名 枚举值列表 ; 其中,枚举值列表中应罗列出所有可用值。这些值也称为枚举元素。例如: enum week Sun,Mon,Tue,Wed,Thu,Fri,Sat;枚举变量定义格式如下:enum 枚举名 枚举变量列表;例如: enum week d1;