《单片机原理与应用技术》课件第4章_第1页
《单片机原理与应用技术》课件第4章_第2页
《单片机原理与应用技术》课件第4章_第3页
《单片机原理与应用技术》课件第4章_第4页
《单片机原理与应用技术》课件第4章_第5页
已阅读5页,还剩136页未读 继续免费阅读

下载本文档

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

文档简介

第四章MCS-51单片机Cx51语言概述和程序设计4.1C与80C51

4.2Cx51数据与运算

4.3Cx51流程控制语句

4.4Cx51构造数据类型

4.5Cx51的函数、变量的作用域和存储类型

4.6Cx51语言程序设计

4.7程序设计举例

4.8习题实训四简单的单片机Cx51语言程序设计

4.1C与80C51

4.1.180C51的编程语言

程序设计语言经历了机器语言、汇编语言、高级语言三个阶段,机器语言和汇编语言是面向机器的语言,高级语言又分为面向过程和面向对象两种。机器语言就是计算机能识别的二进制数据码。汇编语言是用助记符号描述的指令系统。它们都属于计算机的低级语言。标准的C语言和单片机的Cx51语言都属于高级语言,它们都遵循着模块化程序设计思想进行编程。对于MCS-51系列的单片机,现有4种语言可以支持,即汇编、PL/M、C和BASIC语言。标准的C语言是一种专门用来编写计算机操作系统的语言,TurboC是标准的C语言,在微机上广泛使用的编译软件。KeilCx51是用来在MCS-51系列单片机上使用的编译程序软件。Cx51语言又可以像汇编语言那样对位、字节和地址进行操作,它把高级语言的结构化程序设计思想和编辑软件的语句与低级语言的实用性结合起来。与汇编语言相比,Cx51语言具有如下优点:

(1) Cx51语言是一种结构化的高级语言,其可读性好,可移植性强,更贴近人的思维;

(2)编程者对单片机的指令系统不要求了解,仅要求对8051的存储器有初步了解;

(3)Cx51语言有功能丰富的库函数,运算速度快、编译效率高,可以实现对单片机系统硬件的控制;

(4)Cx51语言因为具有完整的程序模块结构,可以满足较大规模的软件系统的开发,提高了开发软件的效率。

Cx51语言与汇编语言相比,缺点是占用资源较多,执行效率没有汇编语言高。同时,对于普遍采用的RISC架构的MCS-51系列单片机来说,内部的ROM、RAM、STACK等资源都有限,一条Cx51语言指令编译后,会转换为很多机器码,很容易出现ROM空间不够,堆栈溢出等问题。而一条汇编语言的指令对应一条机器码,每一步的执行动作都很清楚,并且程序大小和堆栈调用情况都容易控制,调试起来也比较方便。4.1.2Cx51程序结构

Cx51程序结构与标准C语言的语法规则基本一致,都是由函数构成的。也就是说,函数是Cx51程序的基本单位。下面从以下几个方面介绍Cx51程序的结构特点:

(1)一个Cx51源程序至少包含一个main函数,也可以包含一个main函数和若干个其它函数。

(2) main函数是每个程序执行的起始点。

(3)函数定义由类型、函数名、参数表和函数体4个部分组成。Cx51函数的定义格式如下:

类型函数名(数据类型形式参数,数据类型形式参数…)

{定义数据变量部分;可执行语句部分;}

(4)函数定义相当于汇编语言中的一般子程序。函数的调用相当于调用子程序的CALL语句。函数定义和函数调用不分先后,但是如果调用在定义之前,那么在调用前必须先进行函数说明。函数说明是一个没有函数体的函数定义,而函数调用则要求有函数名和实参数表。

(5)Cx51程序书写格式自由,一行可以写几个语句,一个语句也可以写在多行上。Cx51程序没有行号,也没有像FORTRAN、COBOL那样严格规定书写格式(语句必须从某一列开始)。每条语句的最后必须有一个分号“;”表示语句的结束。

(6)可以使用/**/对Cx51程序中的任何部分作注释。注释可以提高程序可读性,使用注释是编程人员的良好习惯。

(7)  Cx51语言本身没有输入/输出语句,输入和输出的操作是由scanf和printf等库函数来完成的,也就是说Cx51语言对输入/输出实行“函数化”。

4.1.3KeilCx51编程实例

【例4-1】

由单片机80C51的P1口控制8个发光二极管的动作,动作要求如下:

(1)开始8个发光二极管全暗;

(2)延时1 s后,按D0→D1→D2→D3→D4→D5→D6→D7的顺序依次点亮8个发光二极管;

(3)延时1 s后,按D7→D6→D5→D4→D3→D2→D1→D0的顺序依次点亮8个发光二极管;

(4)延时1 s后,按D0→D2→D4→D6→D1→D3→D5→D7的顺序依次点亮8个发光二极管;

(5)延时1s后,按D1→D3→D5→D7→D0→D2→D4→D6的顺序依次点亮8个发光二极管;

(6)重复步骤(1)~(5)。

硬件电路设计如图4-1所示。图4-180C51控制8个发光二极管的电路图

4.2Cx51数据与运算

4.2.1数据与数据类型

1.数据

具有某种特定格式的数字或数值称为数据。不同的数据之间通常还存在着某些联系。

数据的特点为:数据是计算机操作的对象,不管使用何种语言、何种算法进行程序设计,最终在计算机中运行的只有特定格式的数据流。计算机能够识别的数据流就是二进制数据。

2.Cx51的数据类型

数据的不同格式就称为数据类型。Cx51支持的数据类型如图4-2所示。图4-2Cx51的数据类型

MCS-51系列单片机是8位机,用户进行Cx51程序编写时,经常会出现数据类型不匹配的情况,当计算结果隐含着另外一种数据类型时,数据类型可以自动进行转换,也可以利用Cx51的标准指令函数进行人工转换。

例如将一个位变量赋给一个整型变量时,位型值自动会转换为整型值,有符号变量的符号也能自动进行处理。表4-1列出了所有Cx51能够识别的数据类型的长度和值域。表4-1Cx51的数据类型

3.数据结构

所谓数据结构就是指数据的组织形式。数据按照一定的数据类型进行的排列、组合及其架构称为数据结构。

4.2.2常量与变量

Cx51语言中的数据也有常量和变量之分。

1.常量

1)符号常量

符号常量就是用标识符代表的常量,即标识符形式的常量。虽然符号常量用标识符来定义,但它是不同于变量的,它的值在其作用域内不能改变,也不能再被赋值。符号常量一般用大写字母表示,其定义语句是宏定义预处理命令,不是C语句。定义格式:

#define符号常量常量

2)整型常量

整型常量分为以下三种形式:

(1)十进制整数:由数字0~9和正负号表示,例如123,-456,0。

(2)八进制整数:由数字0开头,后跟数字0~7表示,例如0123,011。

(3)十六进制整数:由0x开头,后跟0~9,a~f,A~F表示,例如0x123,0xff。

整型常量的类型是根据其值所在范围来确定的。在整型常量后面加字母L或l,表明它是longint型常量。

3)实型常量

实数又称为浮点数。实数有两种表示形式:

(1)十进制小数表示形式:如0.1234、12、789。

(2)指数形式:如12.3E3、124E5、14.3E-5。字母E(e)之前必须有数字,而且E(e)后面的指数必须是整数,否则都是不合法的。

实型常量的类型分为float浮点型和double双精度型两种,默认为double型。如果在实型常量后加字母f或F,表明它是浮点型实型常量。

4)字符常量

字符常量的长度为8位,1个字节。字符常量的值就是该字符的ASCII码值,它是用单引号括起来的单个普通字符或转义字符,如 'a'、'A'、'?'、'n'、'\101' 等。其中,反斜杠为转义字符,反斜杠后面可以跟一个字符和一个代码值。

【例4-3】

转义字符举例。4.2.3Cx51数据的存储类型与8051存储器结构

KeilCx51编译器的特点如下:

(1)完全支持8051单片机的硬件结构,可完全访问8051硬件系统的所有部分。

(2)该编译器通过将变量、常量定义成不同的存储类型(data、bdata、idata、pdata、xdata、code)的方法,将它们定位在不同的存储区域中。

Cx51存储类型与8051存储空间的对应关系如表4-2所示。表4-2Cx51存储类型与8051存储空间的对应关系带存储类型的变量定义的一般格式为

[存储种类]数据类型[存储器类型]变量名表4.2.4Cx51对8051系列特殊功能寄存器、并行接口、位变量的定义

1.特殊功能寄存器的Cx51定义

MCS-51单片机中特殊功能寄存器(SFR)分散在片内RAM区的高128字节中,地址范围为80H~0FFH。SFR中有11个寄存器,具有位寻址能力,它们的字节地址都能被8整除,即字节地址是以8或0为尾数的。

为了能直接访问这些SFR,KeilCx51提供了一种自主形式的定义方法,这种定义方法与标准C语言不兼容,只适用于对MCS-51系列单片机进行Cx51语言编程。Cx51定义特殊功能寄存器的一般语法格式如下:

sfrsfr_名称=int常量;“sfr”是定义语句的关键字,其后必须跟一个MSC-51单片机真实存在的特殊功能寄存器名,“=”后面必须是一个整型常量,不允许是带有运算符的表达式,这个常量是特殊功能寄存器“sfr_name”的字节地址,这个常量值的范围必须在SFR地址范围内,位于0x80H~0xFFH之间。

MCS-51系列单片机的特殊功能寄存器的数量与类型不尽相同,因此建议将所有特殊功能寄存器的“sfr”定义语句放入一个头文件中,该文件应包括MCS-51单片机系列机型中的所有SFR定义。C51编译器的reg51.h头文件就是这样一个文件。

在新的MCS-51系列产品中,SFR在功能上经常组合为16位值。当SFR的高字节地址直接位于低端地址之后时,对16位SFR的值可以直接进行访问。例如MCS-51单片机系列的定时器/计数器2就是这种情况。为了有效地访问这类SFR,可使用关键字“sfr16”来定义,其定义语句的语法格式与8位SFR相同,只是“=”后面的地址必须用16位SFR的低字节地址,即低字节地址作为“sfr16”的定义地址。

1)第一种格式

sbitbit_名称=sfr_名称^int常量;

“sbit”是定义语句的关键字,后跟一个寻址位符号名(该位符号名必须是MCS-51单片机中规定的位名称),“=”后的“sfr_name”必须是已定义过的SFR的名字,“^”后的整常量是寻址位在特殊功能寄存器“sfr_name”中的位号,必须是0~7范围中的数。

2)第二种格式

sbitbit_名称=int常量^int常量;

“=”后的int常量为寻址地址位所在的特殊功能寄存器的字节地址,“^”符号后的int常量为寻址位在特殊功能寄存器中的位号。

3)第三种格式:

sbitbit_名称=int_常量

这种格式将位的绝对地址赋给变量,地址必须位于0x80H~0xFFH之间。

2.8051并行接口的Cx51定义

在Cx51语言中,可以在头文件中定义8051片内外扩展的I/O口,也可以在程序设计的过程中(一般在开始的位置)进行定义。只有先定义这些I/O口,才能在Cx51程序中自由使用。

(1)对于MCS-51系列单片机,用关键字sfr来定义片内I/O口。

(2)对于片外扩展的I/O口,根据其设计的硬件译码地址,使用#define语句进行定义。

3.位变量(BIT)的Cx51定义

Cx51编译器支持以下几种方式定义bit数据类型。

(1)位变量的定义。

(2)在函数的定义过程中也可包含类型为bit的参数,也可以将其作为返回值。

(3)位变量不能定义成一个指针或数组。4.2.5Cx51运算符、表达式及其规则

运算符:表示各种运算的符号。运算符的种类有算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、条件运算符、逗号运算符、指针运算符、求字节数运算符、强制类型转换运算符、分量运算符、下标运算符、函数调用运算符等。

表达式:使用运算符将常量、变量、函数连接起来,构成的式子。

算术表达式:用算术运算符和括号将运算对象(包括常量、变量、函数、数组和结构等)连接起来的式子。

1.Cx51算术运算符及其表达式

1)算术运算符的种类

+ (加法运算符,如3+5)

- (减法运算符或负值运算符。如5-2,-3)

* (乘法运算符,如3*5)

/ (除法运算符,如5/3,5.0/3)

% (模运算符或求余运算符,%要求两侧均为整型数据,如7%4的值为3)。

除了负值运算符为单目运算符外,其它都是双目运算符。

2)算术运算符的优先级与结合性

在进行表达式求值过程中,C语言规定了各运算符的“优先级”和“结合性”。

(1)优先级——指当运算对象两侧都有运算符时,执行运算的先后次序。按运算符优先级别的高低顺序执行运算。

算术运算符的优先级规定为先乘、除、模,后加、减,括号最优先。

说明:在算术运算符中,乘、除、模运算符的优先级相同,并高于加、减运算符。在表达式中若出现括号,则括号中的内容优先级最高。

(2)结合性——指当一个运算对象两侧的运算符的优先级别相同时的运算顺序。

2.强制类型转换运算符

在Cx51语言中,整型、实型和字符型数据间与标准的C语言一样,可以混合运算(因为字符数据与整型数据可以通用)。如果一个运算符两侧的操作数的数据类型不同,则系统按“先转换,后运算”的原则,首先将数据自动转换成同一类型,然后在同一类型数据间进行运算。

数据类型转换规则如图4-3所示。

类型转换的方式有两种:

1)自动转换

(1)横向向左的箭头,表示必须的转换。char和short型必须转换成int型,float型必须转换成double型。

(2)纵向向上的箭头,表示不同类型的转换方向。图4-3数据类型自动转换规则

2)强制类型转换

除自动转换外,Cx51语言也同样允许强制转换。数据类型强制转换的一般格式为

(要转换成的数据类型)(被转换的表达式)

使用强制转换类型运算符后,运算结果被强制转换成规定的类型。转换规则为:

(1)当char和int变量同时存在时,必定将char转换成int类型;

(2)当float和double类型共存时,在运算时一律先转换成double类型,以提高运算精度。

(3)图4-3中的纵向箭头表示当运算对象为不同类型时的转换方向。例如int型和long型数据进行运算时,先将较低类型int转换成较高的类型long,然后再进行运算,结果是long类型。

3.Cx51关系运算符、表达式及优先级

所谓关系运算,实际上是比较运算。关系运算是将两个数值进行比较,并判断比较的结果是否符合规定的条件。

(1) Cx51提供了六种关系运算符:

(2)关系运算符中前四种运算符的优先级相同,后两种也相同,但前四种高于后两种。关系运算符的优先级低于算术运算符,高于赋值运算符,并采用“从左至右”的结合方向。

(3)关系表达式。用关系运算符将两个表达式(算术表达式、关系表达式、逻辑表达式及字符表达式等)连接起来的式子,称为关系表达式。其一般形式如下:

表达式1关系运算符表达式2

其中,表达式可以是算术表达式、关系表达式、逻辑表达式、赋值表达式和字符表达式。同算术表达式一样,关系表达式也是有值的,这个值反映了两个表达式比较的结果。比较的结果有两种可能:一种是判断条件正确,命名为“真”;另一种是判断条件不正确,命名为“假”。Cx51语言以“1”表示“真”;以“0”表示“假”。

4.Cx51逻辑运算符、表达式及优先级

(1) Cx51提供了三种逻辑运算符:

&& 逻辑“与”(AND);

|| 逻辑“或”(OR);

! 逻辑“非”(NOT);图4-4Cx51中的运算符的优先级

“&&”和“‖”是双目运算符,要求有两个运算对象,而“!”是单目运算符,只要求有一个运算对象。

(2)逻辑运算符的优先级(由高到低排列)是:

! (非)→&&(与)→‖(或)。

(3) Cx51中的运算符的优先级如图4-4所示。

(4)逻辑表达式就是用逻辑运算符将关系表达式或逻辑量连接起来的式子。图4-4Cx51中的运算符的优先级

5.Cx51位操作及其表达式

Cx51提供了六种位操作运算符:

(1) &:按位与(双目运算符);

(2) |:按位或(双目运算符);

(3) ^:按位异或(双目运算符);

(4) ~:按位取反(单目运算符);

(5) <<:位左移(双目运算符);

(6) >>:位右移(双目运算符)。

位操作运算符只能是整型或字符型数据,不能为实型数据。

双目运算符:要求运算符两侧各有一个运算对象。因此,如果只要求有一个运算对象的运算符称为单目运算符。

6.赋值运算符及其表达式

赋值运算符为“=”。由赋值运算符组成的表达式称为赋值表达式。赋值表达式的一般格式为

<变量><赋值符><表达式>

赋值表达式的求解过程:将赋值运算符右侧的表达式的值赋给左侧的变量。

赋值的含义:将赋值运算符右边的表达式的值存放到左边变量名标识的存储单元中。

7.自增减运算符

自增减运算符是一种单目运算符,它的作用就是使变量值自动加1或减1。自增减运算只能用于变量,而不能用于常量表达式。(++)和(--)的结合方向是“自右向左”。

自增减运算符放在变量的前面和后面是有区别的:++i和i++ 的作用都相当于i=i+1,但是两者的区别在于 ++i是先执行i=i+1,再使用i的值;而i++ 则是先使用i的值,再执行i=i+1。

8.复合运算符及其表达式

Cx51提供了十种复合赋值运算符,即

+=、-=、*=、/=、%=、<<=、>>=、&=、^=、!=。

Cx51采用这种复合运算符运算的目的是为了简化程序,提高Cx51程序编译效率。

a+=b 相当于a=a+b

a-=b 相当于a=a-b

a*=b 相当于a=a*b

a/=b 相当于a=a/b

a%=b 相当于a=a%b

a<<=7 相当于a=a<<7

a>>=7 相当于a=a>>7

9.逗号运算符及其表达式

逗号运算符为“,”。逗号表达式的一般形式:表达式1,表达式2,…,表达式n。

逗号表达式的求解过程为自左向右,求解表达式1,求解表达式2,…,求解表达式n。整个逗号表达式的值是表达式n的值。例如:逗号表达式3+5,6+8的值为14。

【例4-7】

分析程序的运行结果。

4.3Cx51流程控制语句

4.3.1Cx51语言程序的顺序结构及其流程图

在程序设计过程中,按照由低地址向高地址顺序执行指令代码的结构,我们称为顺序结构程序设计。顺序结构是一种最基本、最简单的编程结构。如图4-5所示,程序先执行A操作,再执行B操作,两者是顺序结构关系。图4-5顺序结构流程图4.3.2Cx51语言程序的选择结构及其流程图

单片机就像人类的大脑,具有一定的逻辑分析能力和选择决策能力,在很多情况下都能判断条件是否成立,然后再作出相应的操作(如图4-6所示)。图4-6选择结构流程图

1.选择语句if

Cx51语言的一个基本判定语句就是if语句。基本结构是:

if(表达式){语句};如果表达式成立(为真),则程序执行花括号中的语句,否则程序跳过花括号中的语句部分,执行下面的其他语句。Cx51语言中提供了三种形式的if语句。

形式一:

if(表达式){语句}

形式二:

if(表达式){语句1}else{语句2}

2.if语句的嵌套

在if语句中又包含有一个或多个if语句,这种情况称为if语句的嵌套。基本格式如下:4.3.3Cx51语言程序的循环结构及其流程图

在Cx51语言中用来实现循环的语句有三种:while语句、dowhile语句、for语句。

1.while语句

while语句用来实现“当型”循环结构,其一般形式为

while(表达式){语句/*循环体*/}

表达式是while循环能够继续的条件,而语句部分则是循环体,是执行重复操作的部分。只要表达式为真,就重复执行循环体内的语句;反之,则终止while循环,执行循环之外的下一行语句。具体过程(如图4-7所示)就是先判断表达式,当表达式的值为假时,退出while循环,执行循环体外的后续语句;否则,当表达式的值为真时,便执行循环体,再次执行该while语句。图4-7while循环的过程语句

2.dowhile语句

在程序设计的过程中有时需要在循环体的结尾处,而不是在循环体的开始处检测循环结束条件。dowhile循环语句可以满足这种要求。dowhile语句的格式为

do

{语句;}/*循环体*/

while(表达式);

dowhile语句用来实现“直到型”循环结构。执行过程如图4-8所示。图4-8dowhile的程序流程

3.for循环语句

在Cx51语言中,for循环语句是循环语句中最为灵活也是最为复杂的一种。它不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定但已经给出循环条件的情况。

for循环语句的一般形式为

for(表达式1;表达式2;表达式3)

{语句;}/*循环体*/

for循环的语句执行过程如下:

(1)先对表达式1赋初值,进行初始化。

(2)判断表达式2是否满足给定的循环条件,若满足循环条件,则执行循环体内的语句然后执行第(3)步;若不满足循环条件,则结束循环,转到第(5)步。

(3)若表达式2为真,则在执行指定的循环语句后,求解表达式3。

(4)回到第(2)步继续执行。

(5)退出for循环,执行下面一条语句。

4.三种循环语句的比较

在上述三种循环语句中,while循环是最基本的,凡是能用dowhile语句和for语句编写的程序,都能用while语句编写出来,但对某些应用场合来说,使用dowhile语句和for语句编写程序更简单。

一般来说,在不知道数据的数量或不知道重复计算的次数,如用迭代法对非线性方程求解时,应使用while语句和dowhile语句。与上述情况相反,如果知道数据的数量或知道重复计算的次数,例如对数组进行处理时,一般用for语句,并且用循环控制变量作为数组的下标有很强的表达能力。 4.4Cx51构造数据类型

4.4.1数组

1.一维数组

(1)一维数组的定义方式:

类型说明符数组名[整型表达式]

这条语句定义了一个一维字符型数组,有10个元素,每个元素由不同的下标表示,分别为a[0]、a[1]、a[2]、a[3]、a[4]、a[5]、a[6]、a[7]、a[8]、a[9]。

在数组定义的时候,数组的第一个元素的下标为0而不是1,即数组的第一个元素是a[0]而不是a[1],而数组的第10个元素应为a[9]。每个分量都相当于一个整型变量。一维数组的存储结构与逻辑结构如下:

(2)一维数组的引用。数组是一种构造类型,它由若干个元素组成,C语言规定只能依次引用数组的每一个元素,而不能一次引用数组这个整体的10个元素,即不能直接对数组名操作。

一维数组的元素引用形式为

数组名[整型表达式]

(3)数组的初始化。数组中的值可以在程序运行期间用循环和键盘输入语句进行赋值。但这样做将耗费许多机器运行时间。对大型数组而言,这种情况更加突出。对此可以用数组初始化的方法加以解决。

2.二维数组

(1)二维数组的定义方式:

数据类型说明符数组名[常量表达式1][常量表达式2]

二维数组的定义类似于一维数组的定义,只是多了一个下标,第一个中括号中的常量表达式1的值为数组的行数,第二个中括号中的常量表达式2的值为数组的列数。

这条语句定义了一个2行3列的二维数组,有6个元素,每个元素由不同的下标表示,分别为b[0][0]、b[0][1]、b[0][2]、b[1][0]、b[1][1]、b[1][2]。注意,在数组定义的时候,数组的行和列的第一个元素的下标都是从0而不是从1开始,即数组的第一个元素是b[0][0]而不是b[1][1],而数组的第6个元素应为b[1][2]而不是b[6]。每个分量都相当于一个整型变量。二维数组的所有元素在计算机内存中占有一片连续的存储空间。C语言中二维数组b在内存中是按行存放的,二维数组的存储结构如下:

对于一维数组来说,它的逻辑结构与存储结构是相同的,一维数组的下标值与一维数组在内存中元素排列位置的序号是一致的。而对于二维数组来说,两者却是完全不同的。数组b的逻辑结构如下:

(2)二维数组的引用。二维数组的元素引用形式为

数组名[整型表达式1][整型表达式2]

(3)二维数组的初始化。对数组的全部元素赋初值可以用下面两种方法进行:

①分行给二维数组的全部元素赋初值。

②也可以将所有数据写在一个花括号内,按数组的排列顺序对各元素赋初值。

3.字符数组

1)字符数组的定义、引用和初始化

字符数组的定义方式为

char数组名[常量表达式];

2)字符串和字符串结束标志

字符串是用一对双引号括起来的字符序列,这些字符可以是一般的可显示字符,也可以是某些特殊的控制字符。C语言不提供字符串变量,规定字符串只能用字符数组来处理。将字符串存储到内存中时,除了要将字符串中的每一个字符存入内存中,还要在字符串的最后加一个 '\0' 字符存入内存。这个 '\0' 字符就是字符串的结束标志。

3)用字符串给字符数组初始化

charst[8]="welcome";

4)字符串的长度

若有“charch[]="Good";”,则数组ch的元素个数是5,而不是4,也就是说,字符串的长度是双引号中所包括的字符个数加1。

若干个字符串可以装入一个二维字符数组中,称为字符数组。数组的第一个下标是字符串的个数,第二个下标定义每个字符串的长度。该长度应当比这批字符串中最长的串多一个字符,用于装入字符串的结束符 '\0'。比如语句charb[60][34];定义了一个二维字符数组b,可容纳60个字符串,每串最长可达34个字符。

4.数组的应用

数组是一种很重要的数据结构,应掌握一维和二维数组的应用,熟练掌握排序、查找、删除、插入等基本算法,运用二维数组完成一些基本算法和应用。

4.4.2指针

1.基本概念

(1)地址。内存中每一个字节都有一个唯一的编号,这个编号就是地址。

(2)指针。指针就是地址。

(3)指针变量。指针变量是专门用来存放地址值的一种变量。

(4)直接访问方式。先根据变量名与内存单元地址的对应关系,找到变量在内存中的位置,然后从该地址中取出变量的值,这种方式就是直接访问方式。

(5)间接访问方式。如果要存取变量的值,可以将变量的地址放在另一个内存单元中,访问时先找到存放变量的地址的内存单元地址,从中取出该变量的地址,然后从该地址的内存单元中取出变量的值,这种访问方式就是间接访问方式。在这种访问方式中就会用到指针。

2.指针与变量

(1)指针变量定义的一般形式为

类型说明符*指针变量名;

在上述语句中的*表示“指向”;指针变量名即为标识符,必须是一个合法的标识符;类型说明符表示该指针变量所能指向的对象的数据类型。

(2)指针变量的引用。弄清指针和指针变量的概念,掌握了指针变量的定义后,就可以使用指针来进行间接访问了。有关指针的运算符有两个:

&——取变量地址的运算符;

* ——指针运算符或称“间接访问”运算符。

(3)指针变量作为函数的参数。函数的形参不仅可以是整型、实型、字符型,还可以是指针类型。指针变量存放的是地址,同样可以作为函数的参数来进行“地址传送”,实际参数可以是地址常量或指针变量,形式参数则为指针变量。

3.指针变量的运算

若先使指针变量p指向数组a[](即p=a;),则变量中的运算如下:

(1) p++(或p+=1)。该操作将使指针变量p指向下一个数组元素,即a[1]。若再执行x=*p,则将取出a[1]的值,将其赋给变量x。

(2) *p++。由于++与*运算符优先级相同,而结合方向为自右向左,故 *p++ 等价于*(p++)。其作用是先得到p指向的变量的值(即 *p),然后再执行p自加运算。

(3) (*p)++。该运算表示p所指向的元素值加1。要注意的是,这里是元素值加1而不是指针变量值加1。若指针变量p指向&a[0],且a[0]=3,则(*p)++ 等价于(a[0])++,此时a[0] 值增为4。

若p当前指向数组中第i个元素,则

*(p--)与a[i--] 等价,相当于先执行*p,然后再使p自减;

*(++p)与a[++i] 等价,相当于先执行p自加,再执行 *p运算;

*(--p)与a[--i]等价,相当于先执行p自减,再执行 *p运算。

4.KeilCx51的指针类型

KeilCx51支持“基于存储器的指针”和“一般指针”两种指针类型。

1)基于存储器的指针

2)一般指针

一般指针包含3个字节,其中2个字节是偏移,1个字节为存储器类型。第一个字节代表了指针的存储器类型。存储器类型有四种:0x00代表idata、data、bdata;0x01代表xdata;0xfe代表pdata;0xff代表code。

例如:表示xdata类型的0x23fe地址作为指针可以表示成如表4-3所示的形式。表4-3一般指针的定义方法4.5Cx51的函数、变量的作用域和存储类型

在Cx51语言程序设计过程中,一般都采用模块化程序设计方法,也就是说一个比较大的程序都是由一个个函数构成的,函数就是汇编语言程序设计中所说的“子程序”或“过程”。本节要求学会设计并使用(调用)函数,同时通过程序设计的练习,要求进一步掌握“自顶向下,逐步求精”的结构化程序设计方法。在Cx51中,同样也采用函数来实现重复地去做某件事的过程。主程序(main())可以根据需要来调用其他函数。当函数执行完毕后,就可以发出返回指令,而主程序main()用后面的指令来恢复主程序流的执行。同一个函数可以在不同的地方被调用,并且函数可以重复使用。也就是说Cx51语言程序是由一个个函数构成的,在构成Cx51语言程序的若干个函数中,必有一个是主函数main()。下面所示为Cx51语言程序的一般组成结构:

1.函数的分类

Cx51语言函数分为主函数main()和普通函数两种。而从用户的角度划分,普通函数又可分为两种:一种是标准库函数;一种是用户自定义函数。

1)标准库函数

标准库函数是由Cx51编译系统的函数库提供的。Cx51语言系统一般都具有功能强大、资源丰富的标准函数库。因此,作为系统的使用者,在进行程序设计时,应该善于充分利用这些标准库函数资源,以提高效率,节省时间。

2)用户自定义函数

用户自定义函数就是用户根据自己的需要编写的函数。

从函数定义的形式上划分,用户自定义函数可以有三种形式:无参数函数、有参数函数和空函数。

2.函数的定义

函数定义是一个完整的构造。在编译时,编译程序根据函数定义为函数分配存储空间。

(1)无参数函数的定义形式:

返回值类型标识符函数名(){函数体语句}

(2)有参数函数的定义形式:

返回值类型标识符函数名{数据类型形式参数,数据类型形式参数…}

{函数体语句}

(3)空函数的定义方法:

返回值类型说明符函数名(){}

3.函数的参数和函数值

Cx51语言采用函数之间的参数传递方式,使一个函数能对不同的变量进行功能相同的处理,从而提高了函数的通用性与灵活性。

函数之间的参数传递,通过主调用函数的实际参数与被调用函数的形式参数之间进行数据传递来实现。被调用函数的最后结果由被调用函数的return语句返回给主调用函数。

1)形式参数和实际参数

(1)形式参数。在定义函数时,函数名后面括号中的变量名称为“形式参数”,简称形参。

(2)实际参数。在函数调用时,主调用函数名后面括号中的变量名称为“实际参数”,简称实参。

2)函数的返回值

主调函数用main()在调用有参数函数时,将实际参数传递给被调用函数的形式参数。然后,被调用函数使用形式参数作为输入变量进行运算,所得结果通过返回语句returnu返回给主函数,并在主函数的语句中通过等号赋值给变量。这个变量u就是被调用函数的返回值,简称函数的返回值。

4.函数的调用

函数调用的一般形式为

函数名(实际参数表列);

对于有参数型函数,若包含多个实际参数,则应将各参数之间用逗号分隔开。主调用函数的实际参数的数目与被调用函数的形式参数的数目应该相等。实际参数与形式参数按实际顺序一一对应传递数据。如果调用的是无参数函数,则实际参数表可以省略,但函数名后面必须有一对空括号。函数调用包括以下几个步骤:

(1)在程序源文件的开头以包含的方式指明函数(标准模块)所属函数库名,或者是函数(与主调函数不在同一文件)所属的文件名称,格式为

#include<函数库名 .h>

#include<文件名称 .c>

(2)为了在程序中使用函数调用语句,调用一个在其后定义的函数,一般应该在该函数调用语句之前,使用函数说明语句对该被调用函数做说明,以确保函数被正常调用,其格式为

类型标识符被调用函数的函数名(形参类型序列);

(3)调用函数的形式为

函数名(实参序列)

(4)函数调用的执行过程就是首先把实参传递给被调用函数的形参,这个过程称为形参和实参的结合。然后,程序控制转移到被调用函数的第一个语句开始执行,执行完被调用函数的最后一条语句或者执行到被调用函数中的return语句时,就从被调用函数返回主调用函数继续执行。

(5)主调用函数对被调用函数的调用可以有以下三种方式:

①函数调用语句。把被调用函数名作为主调用函数中的一条语句。②函数结果作为表达式的一个运算对象。此时被调用函数以一个运算对象的身份出现在一个表达式中。这就要求被调用函数带有return语句,以便返回一个明确的数值参加表达式的运算。被调用函数只能作为表达式的一部分。

③函数参数。被调用函数作为另一个函数的实际参数。

4.6Cx51语言程序设计

1.模块化程序设计

模块化程序设计就是遵循一定的模块分解和组织原则,把一个大程序分解为多个容易理解和实现的大小适当、功能明确、具有一定独立性的程序模块的过程。结构化编程是把任何程序的结构都限制为顺序、选择和循环三种基本结构,以提高程序的可读性和可靠性。

一个结构化程序应当具有以下特点:

(1)有一个入口、一个出口;

(2)没有死语句(永远执行不到的语句),每一个语句应当至少有一条从入口到出口的路径通过它;

(3)没有死循环(无限制的循环)。

2.文件命名规则

程序文件有几个常用的扩展名:

(1) .asm是汇编语言源文件;

(2) .a51是汇编语言源文件;

(3) .p51是PL/M语言源文件;

(4) .c51是Cx51语言源文件;

(5) .c是C语言源文件;

(6) .LST包含汇编、编译的程序和错误的列表文件;

(7) .OBJ文件为可重新定位的目标模块;

(8) .HEX文件为转换成Intel的目标文件格式;

(9) .lib为库文件;

(10) .m51/.map为连接/定位后的映像文件;

(11) .lnk为连接器、定位器使用的文件;

(12) .h为源文件的头文件。

4.7程序设计举例

4.7.1顺序程序

为了将汇编语言与Cx51语言进行对比,我们将上一章的例题3-49进行Cx51语言的改写。

4.7.2选择程序

【例4-12】

已知X、Y均为8位二进制有符号数,分别存在30H、31H中,试编写能实现下列符号函数的程序:

4.7.3循环程序

【例4-13】

编写一段程序,采用冒泡排序法,将内存地址为50H~57H中的无符号数,从小到大排序。

使用Cx51语言编写程序如下:

4.8习题

1.单片机识别的语言有几种,各有什么优缺点?

2.Cx51语言能识别的数据类型有哪几种?

3.如何在Cx51中定义变量?变量分为几种?

4.Cx51语言中能识别的数据存储类型有几种?分别有什么区别?

5.Cx51如何定义80C51特殊功能寄存器和80C51并行接口?

6.Cx51有几种运算符?它们的优先级是如何排列的?

7.Cx51有几种基本结构?如何画流程图?

8.在Cx51中如何使用数组?字符数组如何定义和使用?

9.什么是指针?基于KeilCx51有几种指针类型,如何定义和使用?

10.Cx51语言中函数是如何定义和使用的?函数分为几种?

11.在Cx51语言中有几种常见的文件扩展名?

12.什么是算法?

13.什么是结构化的算法?有什么优点?

14.字符常量与字符串常量有什么区别?

15.填空。

(1)若有以下定义():

chara;intb;

floatc;doubled;

则表达式a*b+d-c值的类型为

A.float B.int

C.cha D.double

(2)表示关系x≤y≤z的C语言表达式为()。

A.(X<=Y)&&(Y<=Z) B.(X<=Y)AND(Y<=Z)

C.(X<=Y<=Z) D.(X<=Y)&(Y<=Z)

(10)单片机片内RAM的低128字节可以分为______个区域,第一区域安排了______组工作寄存器,每组占用_______个RAM字节,工作寄存器组的选择由________中的两位来确定。

(11) KeilCx51编译器将变量、常量定义成不同存储类型,分别为_________、__________、___________、___________、___________、___________,将它们定位在不同存储区中。

(12)关键字“sfr”是对特殊功能寄存器的定义,定义特殊功能寄存器地址范围位于__________之间。

(13)已知a=30H,b=4DH,则a&b的值为____________。

(14)已知PSW的字节地址为0xd0H,字节分配如下:

试用三种方法对CY进行位声明____________、____________和____________。

(15)设i,j,k均为int型变量,则执行完下面的for循环后,k的值为

for(i=0,j=10;i<=j;i++,j--)k=i+j;

(16)若函数fun的类型为void,且有以下定义和调用语句:

16.将下列条件写成C语言的关系表达式或逻辑表达式:

(1) a>d或b>d;

(2) a不等于b;

(3) i大于等于15并且j大于等于25;

(4) h大于等于40 × b并且m小于12,或者,h小于40 × b并且m大于等于12;

(5) a、b、c、d均不为0;

(6) x、y之一等于9并且s、t之一等于9。

17.已知a=5、b=4,计算下列表达式的值:

(1) 4×a>6+b;

(2) 7>5||30==a*b||a>40;

(3) a>=b&&b*2==a+3&&a<0&&a*a+b*b>=a*b+b*a;

(4)

!a>b&&b<20||a>0。

(6)根据考试成绩,打印等级分。

(7

温馨提示

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

评论

0/150

提交评论