C51单片机C语言程序设计



《C51单片机C语言程序设计》由会员分享,可在线阅读,更多相关《C51单片机C语言程序设计(71页珍藏版)》请在装配图网上搜索。
1、,,,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,‹#›,单击此处编辑母版标题样式,L o g o,嵌 入 式 系 统,,C51,单片机,C,语言程序设计,,本章内容:,C51,语言概述,C51,数据类型和数据存储类型,C51,运算符和表达式,C51,程序结构,C51,函数,【,任务导入,】,,基于,C51,语言的静态,LED,显示系统的实现:利用,AT89C51,单片机的,I/O,端口驱动两个八段数码管从“,00”,到“,99”,流水显示,即通电后,显示“,00”,,间隔一段时间后,显示“,01”,,再间隔一段时间后,显示“,02”,,直到“,99”,,然后再显示“,0
2、0”,,往复循环。,【,任务分析,】,要实现用两个数码管循环显示数字,00,~,99,的功能,我们可把两个数码管的段选线分别连接到单片机的两组,I/O,口的共,16,根,I/O,口线上,再通过程序让单片机的两组,I/O,口分时输出,0,~,9,对应的段码就可以了。,,C51,语言概述,1,、,C,语言和,C51,语言,(,1,),C,语言是由早期的,BCPL,语言发展而来的。,1967,年,,剑桥大学,的理查兹,(Martin Richards),在对,CPL,语言进行简化的基础上设计了,BCPL(Basic Combined Pogramming Language),语言。,,1970,年,
3、美国,贝尔实验室,的汤普森,(Ken Thompson),以,BCPL,语言为基础,设计出简单且接近硬件的,B,语言 。,,1972,年,美国贝尔实验室的里奇,(D. M. Ritchie),又以,B,语言为基础,最终设计出了,C,的语言,,1978年,美国 电报公司(AT&T)贝尔实验室正式发表了C语言。,,1983,年,美国国家标准化协会制定了一个,C,语言标准通常称为,ANSI C,。,ANSI C,在被国际标准化组织,ISO,所接受后,又经过多次修正,形成了目前的,C,语言标准。,(,2,),C51,语言,,,用,C51,编写单片机程序时,需要根据单片机存储结构及内部资源定义相应的
4、数据类型和变量,而标准的,C,语言不需要考虑这些问题。另外,,C51,包含的数据类型、变量存储模式、输入输出处理、函数等方面与标准的,C,语言也有一定的区别。其他的语法规则、程序结构及程序设计方法则与标准的,C,语言相同。,,C,语言编译调试工具效率高,数据类型及运算符丰富,经过不断完善,能满足单片机的开发要求,形成了单片机,C,语言。为了和,ANSI C,区别,把,51,单片机,C,语言称为,C51,语言。,(,3,),C51,特点,,● 编程者不需要了解单片机的指令系统,仅要求对单片 机的存储器结构 有初步的了解,至于存储器的分配、寻址方式及数据类型等完全由编译器管理
5、。,●程序有规范化的结构,可以分为不同的函数,这种方式可以使程序结构化,将可变的选择与特殊操作组合在一起,增强程序的可读性。,●编程和程序的调试时间显著缩短,从而提高了编程的效率,提供的库函数包含许多标准的子程序,具有较强的数据处理能力,可以将编好的程序很容易地移植到新程序。,,C51,作为一种非常方便的语言得到了广泛的支持,目前已经成为单片机开发的主要编程语言。,简单,C51,程序介绍,【,例,1】,如图,1,所示,在口上接有一个,LED,发光二极管,,要求让发光二极管发光。,图,1,接有,LED,的单片机基本电路,#include ,sbit P1_0=P1^0;,void main( )
6、,{,P1_0=0;,while(1);,},程序如下:,,程序的开始是一个文件包含处理。这段程序中包含的是文件,以,.h,为后缀的称为头文件,该头文件的作用是把特殊功能寄存器中的符号和地址对应起来,这里主要是应用到,P1,这个符号,如果没有包含文件,,C51,编译器不知道,P1,具体指什么,在编译过程中就会发生错误。,给取名为,P1_0,,是通过编译器中增加的关键字,sbit,来定义的,,程序最后是主函数,每一个,C51,程序有且只有一个主函数,函数后面使用一对大括号“,{}”,,在“,{}”,中书写具体内容。,【,例,2】,如图,1,所示,要求口上接的,LED,发光二极管能闪烁发光。,#i
7、nclude ,#define uchar unsigned char,#define uint unsigned int,sbit P1_0=P1^0;,void Mdelay (uint Delay); /*,被调函数申明*,/,void main(void ),{ for(;;),{ P1_0=!P1_0; //,对,P1_0,取反,,Mdelay(1000);,},},void Mdelay (uint Delay) //,延时子程序,由,Delay,参数确定延时时间,{ uchar i;,for( ;Delay>0; Delay--),{ for (i=0; i<1
8、24;i++),{;},},},,与上例相同,,宏定义,即用一个指定的标识符来代替一个字符串,如第二行用,uchar,来代替,unsigned char,;,函数申明,如果被调函数在主调函数后面,一般需要声明,小结,(1),,C51,程序和,C,程序一样,也是由函数构成的。一个,C51,程序至有且只有一个,main,函数,可以有零个或多个其他函数,因此函数是,C51,程序的基本单位。,main,函数可以直接书写语句或者调用其他函数来实现功能,被调用的函数可以是编译器提供的库函数,也可以是用户根据需要编写的函数,(,如例中的,Mdelay,函数,),。使用,Keil C,编写的任何程序都可以直接
9、调用其提供的库函数,调用时只需要包含具有该函数的头文件即可。,Keil C,提供了,100,多个库函数供用户直接使用。,(2),一个函数由以下两部分组成。,函数的首部,包括函数名、函数类型、函数参数名、参数类型。如例中,Mdelay,函数的首部为,void Mdelay (uint Delay),↓ ↓ ↓ ↓,函数类型 函数名 参数类型 参数名,函数体,即函数首部下面大括号里的内容。,(3),一个,C51,程序从,main,函数开始执行,不管,main,函数在什么位置。,(4),,C51,中字母区分大小写
10、,如定义是,sbit P1_0=P1^0,,若后面写成,P1_0,,在编译时就会出现错误。,(5),,C51,书写自由,一行可以写几个语句,一个语句也能写在几行上。,(6),每个语句必须以分号结束。,(7),,C51,中的注释可以采用两种符号。第一种是“,/*…*/”,符号,从“,/*”,开始直到“*,/”,为止,中间的内容都是注释。第二种是“,//”,引导的注释语句,这种注释只对本行有效。,2 C51,数据类型和数据存储类型,,2.1,常量与变量,,1,、常量和符号常量,,,在程序运行过程中,其值不能改变的量称为常量,如,10,、,0,、,0x45,等。常量一般从字面形式即可以判断,这样的
11、常量称为字面常量或者直接常量。,,常量也可以用一个标识符来表示,称之为符号常量。,【,例,3】,如图,1,所示,要求点亮口上接的,LED,灯。,程序如下。,#define LIGHT 0xfe,#include ,void main( ),{,P1=LIGHT;,while(1);,},定义符号常量,LIGHT,,在以后的程序中出现的所有,LIGHT,,实际上都是指,0xfe,,使用符号常量的优点如下:,,(1),含义清楚。如上面程序中,从,LIGHT,就知道它代表灯亮,因此定义符号常量时,应考虑“见名知意”。在一个规范的,C51,程序中不提倡使用很多直接常量。如若定义,sum=10+20+3
12、0,,则在检查程序时往往会搞不清楚各个常数代表什么含义。,(2),在需要改变一个量时,可以做到一改全改。如,#define PORTA 0x7fff,,在程序中要使用端口,0x7fff,,可以用,PORTA,来代替,如果端口地址发生变化,变成,0x3fff,,只要把定义语句改为,#define PORTA 0x3fff,就行了。,变量,值可以改变的量称为变量。,,图,2,变量,,2.2,整型数据,,1,、整型常量的表示方法,,2,、整型变量,,,整型常量即整常数,包括正整数、负整数和,0,,不能是小数。 可以是十进制、八进制(以,0,开头)和十六进制(以,0x,开头)。,,整型变量的基本类型是
13、,int,,可以根据数值的范围将变量定义为基本整型、短整型或长整型,在,int,之前分别加上修饰符:,short(,短整型,),或,long(,长整型,),。在实际应用中,变量的值常常是正的,(,如年龄、学号等,),,为了充分利用变量的表数范围,可以将上面的三类定义成无符号型,即对以上三类分别加上修饰符,unsigned,。,表,4-1,,整型变量的数据类型,,类,,型,字,,节,,数,数值范围,int,2,-,2,15,~,2,15,-,1,unsigned [int],2,0,~,2,16,-,1,short [int],2,-,2,15,~,2,15,-,1,unsigned short
14、 [int],2,0,~,2,16,-,1,long [int],4,-,2,31,~,2,31,-,1,unsigned long [int],4,0,~,2,32,-,1,C51,中变量必须先定义才能使用,定义整型变量的方式为,修饰符 变量名,,例如:,int a; //,定义一个整型变量,a,unsigned int a1,a2; //,定义两个整型变量,a1,,,a2,long b; //,定义一个长整型变量,b,unsigned long b1,b2; //,定义两个长整型变量,b1,,,b2,,2.3,实型数据,,1,
15、、实型常量的表示方法,,2,.实型变量,,实数又称为浮点数,实数有以下两种表示形式。,(1),、十进制小数形式。由数字和小数点组成,如、等。,(2),、指数形式。如,34e2,或,34E2,都代表,34×102,。,标准,C,语言中的实型变量分为单精度,(float),、双精度,(double),和长双精度,(long double),三种,但,Keil C,不支持后两种,所以这里不做介绍。,float,型占用,4,个字节,,能提供的有效数字是有限的,在有效位以外的数字会被舍去 。,C51,中实型数的使用应该注意以下几点:,(1),、在,8,位单片机中一般不要使用实型数,这样会降低程序的运行速
16、度,增加程序的长度。,,(2),、程序中如果确实用到了实型数,一般不是因为要使用小数点,而是因为用其他类型的变量范围不够大。,,(3),、很多时候,可以用长整型来代替实型。,2.4,字符型数据,,1,、字符型常量的表示方法,,,C51,中字符型常量是用单引号括起来的一个字符,如,‘a’,、,‘x’,、,‘? ‘,等都是字符型常量。,C51,还允许一些特殊形式的字符型常量,,就是以一个“,\”,开头的字符序列。,,表,2,转义字符及其含义,字符形式,含,,义,ASCII,代码,\n,换行,将当前位置移到下一行开头,10,\t,水平制表,跳到下一个,Tab,位置,9,\b,退格,将当前位置移到前一
17、列,8,\r,回车,将当前位置移到本行开头,13,\f,换页,将当前位置移到下页开头,12,\\,反斜杠符“,\”,92,\',单引号字符,39,\",双引号字符,34,\ddd,1,~,3,位八进制数代表的字符,—,\xhh,1,~,2,位十六进制数代表的字符,—,2,、字符型变量的表示方法,,字符型变量用来存放字符常量,一个字符型变量只能存放一个字符。字符型变量的定义形式为:,char,变量名,,如:,char a;,表示定义了一个字符型变量,a,,,a,中可以存放一个字符,可以用下面的赋值语句给,a,赋值:,a='c';,,定义一个字符型变量,系统会为其分配,一个字节,的存储空间,实际上
18、,给字符型变量赋值后,并不是存储字符型变量本身,而是存储该字符型变量的,ASCII,码,如上面是将,'c',的,ASCII,码,99,存储在,a,中。由于,ASCII,码也一定是整数,字符型变量可以和前面所叙述的整型变量一样,通过整型数据来赋值,如:,char a=99;,2.5,数组类型,,1,、一维数组的定义,,数组的维数是指表示数组使用的下标个数,如果数组中每个元素只带有一个下标,称这样的数组为一维数组。一维数组的定义形式为:,,类型说明符 数组名,[,常量表达式,];,如:,int a[4];,2,、一维数组的引用,,C51,中,一个数组不能整体应用,数组名是一个地址常量,不能对其赋值
19、,只能使用数组中的元素。方法如下:,数组名,[,下标,],,下标可以是整型变量或整型表达式,如,a[0],、,a[i](i,是一个整型变量,),。,3,、一维数组的初始化,(1),、在定义数组时对数组元素初始化,如:,int a[4]={1,2,3,4};,经过初始化后,,a[0]=1,、,a[1]=2,、,a[2]=3,、,a[3]=4,。,(2),、可以只给一部分元素赋值,如:,int a[4]={1,2};,经过初始化后,,a[0]=1,、,a[1]=2,、,a[2]=0,、,a[3]=0,。,(3),、对全部数组元素赋值时,可以不指定数组长度。如: “,int a[4]={1
20、,2,3,4};”,可以写成“,int a[]={1,2,3,4};”,。,4,、字符数组,,字符数组是指数组中元素的数据类型是字符类型的一维数组。字符数组引用、初始化的方法都与一维数组相同,只是要注意字符数组的元素是字符,有特殊的字面表示格式。,字符数组初始化的方法也和一维数组相同。如:,char s[5]={'1', '2', '3', '4', '5'};,char s[5]={ '1', '2'};,char s[]={'1', '2', '3', '4', '5'};,2.6,指针类型,,指针的含义是地址,所谓变量的指针就是指变量的地址,定义指针类型的变量实际上是定义一种用来存储地址
21、的变量。,单片机中存,储器的地址,有两种,,一种是由,8,位二进制数,(1,字节,),来表示的,地址,如内部数据存储器 。,还有一种是由,16,位二进制数,(2,字节,),来表示,的地址,如程序存储器、外部数据存储器等。,1,、基于存储器的指针类型,,,所谓基于存储器的指针类型是指在定义指针变量时,就确定好它存储的是什么地方变量的地址,如是在内部数据存储器,还是外部数据存储器,或者是程序存储器,这样,这些指针的长度就可以具体确定,(1,字节或,2,字节,),。,,具体定义为,:,char xdata *ptr;,(1),、定义指针类型变量时,在变量名前加“*”,变量名取名规则和前面一般变量相同
22、。,(2),、,xdata,是指,ptr,里存储的是定义在外部数据存储器里变量的地址,所以,ptr,占,2,个字节。,2,、一般指针类型,一般指针包括,3,字节,其中的,2,字节用于存储地址,另外,1,字节用于存储类型,如表,4-3,所示。,表,3,一般指针构成,,地 址,第,1,字节,第,2,字节,第,3,字节,内 容,存储器类型,地址高,8,位,地址低,8,位,其中第,1,字节表示存储器类型,存储器类型编码如表,4-4,所示。,表,4,一般指针存储器类型,,存储器类型,内部数据存储器,外部数据存储器,外部数据存器一个页面,(256,字节,),内部数据存储器,程序存储器,值,1,2,3,
23、4,5,如一个一般指针指向地址为,0x1234,的外部数据存储器时,,其指针,】,值如表,4-5,所示。,表,5,指向外部数据存储器的指针值,,地 址,第,1,字节,第,2,字节,第,3,字节,内 容,0x02,0x12,0x34,2.7 Keil C51,中特有的数据类型,1,、位型变量,,位型变量实际是定义一个二进制位来存储数据,其值有“,0”,和“,1”,两种。定义形式如下:,bit,变量名,;,如:,bit flag; //,定义一个位变量,flag,使用位变量时还要注意以下几点。,(1),、不能定义位型数组。,(2),、不能定义位型指针。,2,、,sfr,型数据,,,8051,
24、单片机内部的特殊功能寄存器并不能直接被,C51,所接受,为了定义这些特殊功能寄存器,增加了,sfr,、,sfr16,、,sbit,这,3,个关键词。,(1),、,sfr,是定义特殊功能寄存器和其地址的对应关系,其用法为,sfr,变量名,=,地址值,;,(2),、在特殊功能寄存器中,有一些是由两个地址连续的,8,位寄存器组成,如,DPTR,是由,DPH,和,DPL,组成,可以分开定义这两个特殊功能寄存器,也可以用,sfr16,来定义,如:,sfr16 DPTR=0x82;,(3),、,sbit,是定义特殊功能寄存器中可以位寻址的相应位,,sbit,的用法有以下三种。,bit,位变量名,=,地址值
25、,;,sbit,位变量名,=SFR,名称,^,变量位地址值,;,sbit,位变量名,=SFR,地址,^,变量位地址值,;,2.8,数据的存储类型,,表,6 C51,存储类型与,8051,存储空间的对应关系,,存 储 区,描 述,data,片内,RAM,的低,128,字节,可在一个周期内直接寻址,bdata,片内,RAM,的位寻址区,,16,字节,idata,片内,RAM,的,256,字节,必须采用间接寻址,xdata,外部数据存储区,使用,DPTR,间接寻址,pdata,外部存储区的,256,字节,通过,P0,口的地址对其寻址。使用,MOVX @Ri,,需要两个指令周期,code,程序存储
26、区,使用,DPTR,寻址,3,运算符和表达式,,3.1,算术运算符和算术表达式,,(1),、,+,加法运算符,如,4+3,。,(2),、,-,减法运算符,如,5-3,。,(3),、* 乘法运算符,如,5*8,。,(4),、,/,除法运算符,如,10/3,。,(5),、,%,求模运算符或取余运算符,“,%”,两侧应该都为整型数据,如,10%3,。,,需要说明,基本的算术运算符都是双目运算符,即需要两个操作数;对于“,/”,,若两个整数相除,结果为整数,如有小数自动舍去,(,注意不是四舍五入,),,如,10/3,,结果是,3,,而不是,如果需要得到真实结果,需要写成。,1,、基本的算术运算符,(
27、1),、,++,自增运算符。,(2),、,--,自减运算符。,需要说明,,++,和,--,是单目运算符;,++,和,--,只能用于变量,不能用与常量和表达式;,++j,先自增,再使用,,j++,先使用,后自增,如:,a=2; b=++a;,结果是,b=3,,,a=3,。,a=2; b=a++;,结果是,b=2,,,a=3,。,2,、自增,/,自减运算符,,用算术运算符和括号将操作数,(,运算对象,),连接起来,形成符合,C51,语法规则的表达式,称为算术表达式,操作数包括常量、变量、函数等,如,a*b+(5-c/3),。,,C51,规定了运算符的优先性和结合性,在表达式求值的时候,先按运算符的
28、优先性运算,如先乘除求余,再运算加减,如,a-b*c,,,b,的左侧是减号,右侧是乘号,乘号的优先性大于减号,因此,相当于,a-(b*c),。如果在一个表达式中前后运算符的优先性相同,则按规定的结合方向处理,,C51,规定了算术运算符的方向是自左向右,如,a+b-c,,应先执行,a+b,的运算,再与,c,相减。,3,、算术表达式和运算符的优先性与结合性,,4,、各类数值性数据间的混合运算,,,C51,中,整型数据、字符型数据、实型数据都可以进行混合运算,转换规则如图,3,所示。,图,3,数据类型转换,3.2,赋值运算符和赋值表达式,,1,、赋值运算符,,,符号“,=”,为赋值运算符,其作用是将
29、一个数据赋给一个变量,如,x=5,的作用是将常数,5,赋给变量,x,。也可以将一个表达式的值赋给变量,如,x=5+y,。,,2,、类型转换,,赋值运算符的两侧如果类型不一样,也是可以赋值的,但赋值时需要进行数据类型转换,,3,.赋值表达式,,赋值表达式的一般形式为,变量 赋值运算符 表达式,如,a=5,、,a=5+6,、,a=b=5,等都是赋值表达式。,注意:赋值运算符的优先性低于算术运算符。,3.3,逗号运算符和逗号表达式,,,,在,C51,中,多个表达式可以用逗号分开,如,3+5,5+6,7+8,,其中的逗号称为逗号运算符,由逗号运算符组成的表达式称为逗号表达式,其一般形式为,表达式,1,
30、,表达式,2,…,,表达式,n,逗号表达式的求解过程是:先求表达式,1,,再求表达式,2,,直到最后一个表达式,但整个表达式的值是最后一个表达式的值。如,3+5,5+6,7+8,逗号表达式的值为,15,注意:逗号运算符的优先性低于赋值运算符。,3.4,关系运算符和关系表达式,1,、关系运算符,,C51,中提供了以下,6,种关系运算符。,(1) <,小于。,(2) <=,小于等于。,(3) >,大于。,(4) >=,大于等于。,(5) ==,等于。,(6) !=,不等于。,优先性的次序如下:,(1),、前,4,种关系运算符,(<,、,<=,、,>,、,>=),的优先性相同,后,2,种,(= =,
31、、,!=),的优先性也相同,前,4,种的优先性高于后,2,种。,(2),、关系运算符的优先性低于算术运算符。,(3),、关系运算符的优先性高于赋值运算符。,2,、关系表达式,,,用关系运算符将两个表达式连接起来的式子称为关系表达式,如:,a>b,、,a+b>b+c,、,a!=b,。,关系表达式的值只有两种:“真”和“假”。在,C51,中,运算结果如果是“真”,则用数值“,1”,表示;运算结果如果是“假”,则用“,0”,表示。,3.5,逻辑运算符和逻辑表达式,,1,.逻辑运算符,,C51,提供了以下,3,种逻辑运算符。,(1) &&,逻辑与。,(2) ||,逻辑或。,(3),! 逻辑非。,
32、“!”的优先性高于算术运算符,而“,&&”,和“,||”,的优先性相同,处于关系运算符和赋值运算符之间。,2,、逻辑表达式,,,用逻辑运算符将两个表达式连接起来的式子称为逻辑表达式,逻辑表达式的运算结果用“,1”,表示“真”,用“,0”,表示“假”。但在判断一个量是否为“真”时,以,0,代表“假”,而以非,0,代表“真”,如,(1),若,a=5,,,!a,的值为,0,;若,a=-2,,结果也一样。,(2),若,a=5,、,b=8,,则,a&&b,的值为,1,;若,a=0,、,b=8,,则,a&&b,的值为,0,。,,3.6,位操作运算符和表达式,,,C51,提供了如下的位操作运算符。,(1)
33、&,按位与。,(2) |,按位或。,(3) ^,按位异或。,(4) ~,按位取反。,(5) <<,位左移。,(6) >>,位右移。,4 C51,程序结构,,在结构上可以把,C51,程序分为,3,类,即顺序结构、选择结构和循环结构。,4.1,顺序结构,,,顺序结构是一种最基本、最简单的编程结构,在这种结构下,,程序按低地址向高地址顺序执行指令代码,下面通过一个例子来,熟悉,C51,的顺序结构。,【,例,5】,求两个数的和。,定义两个变量,先对其进行赋值,再求出两个数的和,程序,代码如下。,main( ),{ int a, b, sum;,a=3;,b=2;,sum=a+b;},4.2,选择
34、结构,,1,、,if,语句,,(1) if(,表达式,),语句,如果表达式为“真”,则执行语句,否则执行,if,语句后面的语句,如:,if (a<5),b=3;,(2) if(,表达式,),,语句,1,else,,语句,2,如果表达式为“真”,则执行语句,1,,否则执行语句,2,,如:,,if (a<5),b=3;,else,b=-3;,(3) if(,表达式,1),,语句,1,else if(,表达式,2),,语句,2,else if(,表达式,3),,语句,3,,,,else if(,表达式,m),,语句,m,else,,语句,n,如:,,if (a>10),b=1;,else if (
35、a>6),b=2;,else if (a>2),b=3;,else,b=4;,【,例,6】,电路如图,5,所示。要求:通电初始,灯全灭;按住,K1,,,8,个,LED,灯全亮;松开,K1,,灯全灭。,图,5,带,8,个,LED,灯和,2,个按钮的单片机电路,,程序如下:,#include "reg51.h",void main( ),{,P1=0xff; //,把,P1,口全部置,1,,,8,个灯灭,,for(; ;),{,P3=P3|0x01; //,把口置,1,if ((P3&0x01)==0) //,判断,K1,是否按下,,P1=0x00,;,// K1
36、,按下后,点亮全部灯,,else,P1=0xff; // K1,松开后,熄灭全部灯,,},},2,、,if,语句的嵌套,,if(,表达式,1),if (,表达式,2),语句,1,else,语句,2,else,if (,表达式,3),语句,3,else,语句,4,使用,if,嵌套语句特别要注意,if,和,else,配对,,else,总是和最近的,if,配对,,3,、条件运算符,,,,可以用,max=(a>b)? a:b,来表示。其中,(a>b)? a:b,为条件表,达式,执行过程是:如果,(a>b),为“真”,表达式的值为,a,;如,果,(a>b),为“假”,表达式的值为,b,。,条件运算符
37、的一般格式为:,表达式,1?,表达式,2:,表达式,3,,如:,if (a>b),max=a;,else,max=b;,4,、,switch,语句,,,实际问题中,往往遇到以一个变量或表达式的值为判断条件,将此变量或表达式的值分成几段,每一段对应一种选择或操作,这种情况用,if,语句来嵌套非常麻烦,于是,,C51,提供了,switch,语句。,switch,语句的一般结构如下:,switch (,表达式,),{ case,常量表达式,1:,语句,1,break;,case,常量表达式,2:,语句,2,break;,,,,case,常量表达式,n:,语句,n,break;,default:
38、,语句,n+1,,,break;,},说明:,(1),、,switch,语句后面的表达式可以是任何类型。,、若表达式的值与某一个,case,后面的常量表达式值相同,就,开始执行其后面的语句;如果没有一个,case,后面的常量表,达式值与表达式值相同,则执行,default,后面的语句。,(3),、每一个,case,后面的常量表达式值必须不同。,、执行完一个,case,后面的语句后,系统并不跳出,而是执行,后面的,case,语句,直到结束。如果需要执行完当前,case,语,句后,系统就跳出,需要在后面加,break,,如:,case,常量表达式,:,语句,;break;,4.3,循环结构,,构成
39、循环结构的主要有,while,、,do-while,和,for,等语句。,,1,、,while,循环语句,,while,语句的一般表达形式为:,,while (,表达式,),{,语句,},,当表达式的判断为“真”时,执行大括号内的语句,否则不执行。,2,、,do-while,循环语句,,do-while,语句是先执行循环体,然后判断循环条件是,否成立,其一般形式为:,,do,{,语句,},while(,表达式,),;,,while,和,do-while,语句虽然都是循环语句,但是两者是,有区别的,,do-while,语句不管条件是否成立,至少都会执,行一次循环体;而,while,语句,如果条件
40、不成立,则不会执,行循环体。,,3,、,for,循环语句,,for,语句的一般形式为:,for(,表达式,1,;表达式,2,;表达式,3),{,语句,},for,循环语句的执行过程如下。,(1),先求解表达式,1,。,(2),求解表达式,2,,如果结果为“真”,即条件成立,则执行循环体语句;如果结果为“假”,转到第,(5),步。,(3),求解表达式,3,。,(4),转回第,(2),步。,(5),退出,for,循环语句,执行下面的语句。,for,循环中有几种特例,分析如下。,(1),表达式,1,可以没有,但其分号不能省略。,(2),表达式,2,也可以没有,同样分号不能省略,这样认为条件永远满足。
41、,(3),表达式,3,也可以省略。,(4),如果三个表达式都省略,即,for(; ;),,它的作用相当于,while(1),,构成了一个无限循环的过程。,4,、,break,语句和,continue,语句,,,在一个循环语句中,可以通过判断条件来退出循环,也可以通过,break,语句来强制退出循环。,continue,语句用于结束本次循环,即跳过循环体下面的语句,而直接进行下一次是否循环的判断。,【,例,11】,电路如图,5,所示。要求:开机后,全部灯不亮;按下,K1,后,则从,VD1,开始依次点亮,至,VD8,后停止并全部熄灭;待再次按下,K1,,重复上面过程;如果中间,K2,被按下,则灯立
42、即全部熄灭,并返回初始状态。,#include "reg51.h",#include "intrins.h",void Delay( unsigned int delaytime) //,延时子程序,{ unsigned char i;,for( ; delaytime>0;delaytime--),for( i=0; i<=124; i++);,},void main( ),{ unsigned char light=0xfe;,unsigned char i;,for(;;),{ P3=P3|0x03;,if ((P3&0x01)= =0),{ for(i=0;i<=7;i++),{
43、 light=0xfe;,Delay(1000);,if ((P3&0x02)= =0),break;,light=_crol_(light, i);,P1=light,;,,},},P1=0xff;,},},5 C51,函数,,5.1,函数的定义,,,一个完整的,C51,程序可由一个主函数和若干个子函数组成,由主函数调用子函数,子函数之间也可以互相调用,同一个函数可以被一个或多个函数调用任意次。,从函数的形式上划分,函数有无参函数和有参函数两种形式,下面分别讨论两种函数的定义方法。,1,、无参函数的定义,,无参函数的定义形式为:,类型标识符 函数名,(void),{,函数体,},类型标识
44、符是指定函数返回值的类型,如果函数没有返回值,则可以定义“,void”,类型,函数名的取名规则和变量的取名规则一样。,2,、有参函数的定义,,有参函数的定义形式为,类型标识符 函数名,(,形式参数列表,),{,函数体,},,3,、函数参数传递,,,函数之间参数的传递由函数调用时主调函数的实际参数,(,简称实参,),和被调函数的形式参数,(,简称形参,),之间的数据传递完成。所谓的实际参数是指调用时函数名后面括号里的表达式,其个数和被调函数的形式参数个数一致,以,int max (int x, int y),为例,定义的形式参数有,x,和,y,两个,当主调函数调用时,将会写成如下形式:,a=ma
45、x(5,9);,,a,是假设主调函数中的一个变量,,5,和,9,是实际参数,在调用时,把,5,赋给,x,、,9,赋给,y,。,5.2,函数的调用,,1,、函数的调用形式,,函数调用的一般形式为,函数名,(,实参列表,),函数在调用时一般有三种调用方式。,(1),、把函数作为一个语句,如:,Delay();,这时不要求函数有返回值,只要求函数完成一定的功能操作。,、函数在一个表达式中,出现函数表达式,这要求函数带回,一个确定的值以参加表达式的运算。,(3),、函数作为参数调用,如:,c=max(a,max(b,c));,max(b,c),的返回值是作为外部,max,的一个参数。,2,.调用函数的
46、声明和函数原型,,在一个函数中调用另一个函数必须同时具备以下一些条件。,(1),、被调函数一定存在,可以自己编写,也可以是库函数。,(2),、如果是库函数,一般应在文件开头用,#include,命令将调用库函数时所用到的信息包含到文件中。,(3),、如果使用用户自定义的函数,而且该函数与调用它的函数,(,主调函数,),在同一文件中,一般还应该在主调函数中对被调用的函数做声明。,函数原型的一般形式有以下两种。,(1),、函数类型 函数名,(,参数类型,1,,参数类型,2,…),(2),、函数类型 函数名,(,参数类型,1,参数名,1,,参数类型,2,参数名,2,…),注意:如果被调函数在主调函数
47、的后面,可以不用声明。,5.3,局部变量和全局变量,,,一个,C51,程序中的变量可以仅在一个函数中使用,也可以在所有的函数中使用,这就要引入局部变量和全局变量的概念。,1,.局部变量,,在一个函数内部定义的变量称为局部变量,它只在这个函数,内有效。,,2,.全局变量,,,一个源文件可以包含一个函数或若干个函数,在函数之外定义的变量称为全局变量,全局变量在本文件的任何函数中都可以使用 。,库函数介绍,,1,.函数名,_crol_,,2,.函数名,_cror_,,3,.函数名,_irol_,,4,.函数名,_iror_,,5,.函数名,_lrol_,,6,.函数名,_lror_,,7,.函数名,
48、_nop_,,8,.函数名,_testbit_,,5.5,中断程序的编写,,使用汇编语言编写中断程序时,首先使用,ORG,伪指令在指定的地址处写上跳转指令,转到真正的中断程序入口;然后在主程序中设定中断优先级,开启相应的中断允许位;最后开启总中断允许位,这样,一旦中断发生,就可以转到相应的中断服务程序中去。应用,C51,语言编写中断程序与此类似,在,main,函数中直接对各位进行操作,以确定中断优先级、开启中断允许和总中断允许,而中断子程序采用以下的格式:,,返回值 函数名,interrupt n,,其中,,n,对应中断源的编号,其值从,0,开始。以,8051,单片机为例,,n,的编号为,0,
49、~,4,,分别对应外部中断,0,、定时,/,计数器,0,中断、外部中断,1,、定时,/,计数器,1,中断、串行口中断。,【,例,16】,如图,6,所示,,8051,单片机的口引脚接有按钮,,按下此按钮后,引脚所接的,LED,点亮,再次按下后熄灭,,如此反复。,,图,6 INT0,中断实验,,程序如下。,#include ,sbit P1_0=P1^0,void main( ),{ IT0=1; //,设置为下降沿触发,,EA=1; //,开中断总允许,,EX0=1; //,开外部中断,0,for(; ;),{;},},void int0
50、(void) interrupt 0,{ P1_0=~P1_0; //P1_0,取反,},5.6,寄存器组的切换,,,工作寄存器组分配的方法是使用,using n,指定,其中,n,的值为,0,~,3,,对应,4,组工作寄存器。如,void timer0( ) interrupt 0 using 0,表示在该中断子程序中使用,0,组工作寄存器。,学习了,using,的用法后可以给出中断服务的完整语法,其内容如下:,返回值类型 函数名,(,参数,) interrupt n [using n],【,任务实施,】,1),、设计方案,,,用两个八段,LED,显示器显示,00,~,99,的数
51、字,只需用单片机的两组,I/O,口产生对应的十位和个位的段码驱动电平即可。另外为了让人眼能分辨出实时显示的数字,还需用软件实现一定的延时。,2),、硬件电路实现,,图,7,数码管显示电路,,3),、系统程序实现,,,#include "reg51.h",unsigned char code display[10]={0xc0, 0xf3, 0xa4, 0xb0,0x99, 0x92, 0x82, 0xf8, 0x80,0x90}; //,定义数组,有,10,个元素,分别按顺序存储,//,数字,0,~,9,显示对应信号输入,//,数组分配的存储空间在程序存储器中,void Delay( uns
52、igned int delaytime) //,延时子程序,{ unsigned char i;,for( ; delaytime>0;delaytime--),for( i=0; i<=124; i++);,},void main( ),{ unsigned char x, y;,P0= display[0];,P1= display[0]; //,初始,个位和十位都显示,0,,for( ;;),{ for (x=0; x<=9; x++),{ P0= display[x];,for (y=0; y<=9; y++),{ P0= display[y];,Delay(1000);,},},},},,本题采用双重循环的结构来显示,00,~,99,的变换,十位从,0,到,9,变化为外循环,而十位显示每一个数字时,个位也要从,0,到,9,变化为内循环。,
- 温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。