《单片机的C语言编程---课外自学内容三.ppt》由会员分享,可在线阅读,更多相关《单片机的C语言编程---课外自学内容三.ppt(92页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第10章单片机C语言编程单片机原理、接口及应用单片机原理、接口及应用单片机原理、接口及应用单片机原理、接口及应用第10章C语言编程第10章单片机C语言编程内内 容容 提提 要要 C51程序结构程序结构C51的数据类型的数据类型数据的存贮类型和存贮模式数据的存贮类型和存贮模式C51对对SFR、可寻址位、存储器和、可寻址位、存储器和I/O口的定义口的定义C51的运算符的运算符函函数数 C语言编程实例语言编程实例 单片机资源的单片机资源的C语言编程实例语言编程实例汇编语言和汇编语言和C语言的混合编程语言的混合编程C语言函数库的管理与使用语言函数库的管理与使用小结小结 第10章单片机C语言编程51系列
2、单片机支持三种高级语言,即PL/M,C和BASIC。8052单片机内固化有解释BASIC语言,BASIC语言适用于简单编程而对编程效率运行速度要求不高的场合;PL/M是一种结构化的语言,很象PASCAL,PL/M编译器好象汇编器一样产生紧凑的机器代码,可以说是高级汇编语言,但它不支持复杂的算术运算,无丰富库函数支持,学习PL/M无异于学习一种新的语言。C语言是一种通用的程序设计语言,其代码率高,数据类型及运算符丰富,并具有良好的程序结构,适用于各种应用的程序设计,是目前使用较广的单片机编程语言。第10章单片机C语言编程单片机的C语言采用C51编译器(简称C51)。由C51产生的目标代码短、运行
3、速度高、所需存储空间小、符合C语言的ANSI标准,生成的代码遵循Intel目标文件格式,而且可与A51汇编语言或PL/M51语言目标代码混和使用。第10章单片机C语言编程应用C51编程具有以下优点:(1)C51管理内部寄存器和存贮器的分配,编程时,无需考虑不同存储器的寻址和数据类型等细节问题;()程序由若干函数组成,具有良好的模块化结构;()有丰富的子程序库可直接引用,从而大大减少用户编程的工作量。()C语言和汇编语言可以交叉使用.汇编语言程序代码短、运行速度快、但复杂运算编程耗时。如果用汇编语言编写与硬件有关的部分程序,用C语言编写与硬件无关的运算部分程序,充分发挥两种语言的长处,可以提高开
4、发效率。第10章单片机C语言编程10.1C51程序结构程序结构 同标准C一样,C51的程序由一个个函数组成,这里的函数和其他语言的“子程序”或“过程”具有相同的意义。其中必须有一个主函数main(),程序的执行从main()函数开始,调用其他函数后返回主函数main(),最后在主函数中结束整个程序而不管函数的排列顺序如何。第10章单片机C语言编程C语言程序的组成结构如下所示语言程序的组成结构如下所示:全局变量说明/*可被各函数引用*/main()/*主函数*/局部变量说明/*只在本函数引用*/执行语句(包括函数调用语句)fun1(形式参数表)/*函数1*/形式参数说明局部变量说明执行语句(包括
5、调用其他函数语句)funn(形式参数表)/*函数n*/形式参数说明局部变量说明执行语句第10章单片机C语言编程C语言的语句规则:1.每个变量必须先说明后引用,变量名英文大小写是有差别的。2.C语言程序一行可以书写多条语句,但每个语句必须以“;”结尾,一个语句也可以多行书写为好。3.C语言的注释用/*/表示。4.“”花括号必须成对,位置随意,可在紧挨函数名后,也可另起一行,多个花括号可以同行书写,也可逐行书写,为层次分明,增加可读性,同一层的“”花括号对齐,采用逐层缩进方式书写。第10章单片机C语言编程10.2C51的数据类型的数据类型C51的数据有常量和变量之分。常量在程序运行中其值不变的量,
6、可以为字符,十进制数或十六进制数(用0 x表示)。常量分为数值型常量和符号型常量,如果是符号型常量,需用宏定义指令(#define)对其进行定义(相当于汇编的“EQU”伪指令)如:#definePI3.1415那么程序中只要出现PI的地方,编译程序都译为3.1415。变量在程序运行中其值可以改变的量。一个变量由变量名和变量值构成,变量名即是存贮单元地址的符号表示,而变量的值就是该单元存放的内容。定义一个变量,编译系统就会自动为它安排一个存贮单元,具体的地址值用户不必在意。第10章单片机C语言编程10.2.1C51变量的数据类型变量的数据类型无论哪种数据都是存放在存贮单元中的,每一个数据究竟要占
7、用几个单元(即数据的长度)都要提供给编译系统,正如汇编语言中存放数据的单元要用DB或DW伪指令进行定义一样,编译系统以此为根据预留存贮单元,这就是定义数据类型的意义.C51编译器支持数据类型见表10.1。第10章单片机C语言编程表10-1C51的数据类型第10章单片机C语言编程对表10.1作如下说明:1.字符型(char)、整型(int)和长整型(long)均有符号型(signed)和无符号型(unsigned)两种,如果不是必须,尽可能选择unsigned型,这将会使编译器省却符号位的检测,使生成的程序代码比signed类型短得多。2.程序编译时,C51编译器会自动进行类型转换,例如将一个位
8、变量赋值给一个整型变量时,位型值自动转换为整型值;当运算符两边为不同类型的数据时,编译器先将低级的数据类型转换为较高级的数据类型,运算后,运算结果为高级数据类型。3.51单片机内部数据存贮器的可寻址位(20H2FH)定义为bit型,而特殊功能寄存器的可寻址位(即地址为X0H和X8H的SFR的各位)只能定义为sbit类型。第10章单片机C语言编程10.2.2关于指针型数据关于指针型数据(1)关于指针型变量在汇编语言程序中,要取存贮单元m的内容可用直接寻址方式,也可用寄存器间接寻址方式,如果用R1寄存器指示m的地址,用R1取m单元的内容。相对应的在C语言中用变量名表示取变量的值(相当于直接寻址),
9、也可用另一个变量(如P)存放m的地址,P就相当于R1寄存器。用*P取得m单元的内容(相当于汇编的间接寻址方式)这里P即为指针型变量。下面表格表示两种语言将m单元的内容送n单元的对照语句。注:注:上表省略了汇编语言程序中对符号地址上表省略了汇编语言程序中对符号地址n和和m用用EQU伪指令进行具体地伪指令进行具体地址定义的址定义的 语句以及语句以及C语言对变量语言对变量n、m和指针变量和指针变量P进行类型定义的语句,实进行类型定义的语句,实际程序设计中,此步是不可际程序设计中,此步是不可 缺少的。表中缺少的。表中&为取地址运算符,为取地址运算符,*为取内容运算为取内容运算符。符。表10-2汇编语言
10、和C语言的对照第10章单片机C语言编程(2)指针型数据的类型指针型数据的类型由于C51是结合51单片机硬件的,51单片机的不同存贮空间,有不同的地址范围,即使对于同一外部数据存贮器,又有用Ri分页寻址(Ri为八位)和用DPTR寻址(DPTR为十六位)两种寻址方式,而指针本身也是一个变量,有它存放的存贮区和数据长度。因此,在指针类型的定义中要说明:被指的变量的数据类型和存贮类型;指针变量本身的数据类型(占几个字节)和存贮类型(即指针本身存放在什么存贮区)。例如类型定义为data或idata,表示指针指示内部数据存贮器;而pdata表示指针指向外部数据存贮器,用Ri间址。以上均为八位地址;而类型c
11、ode/xdata表示指针指向外部程序存贮器或外部数据存贮器指针,本身(即被指示地址)应为十六位长度。如果想使指针能适用于指向任何存贮空间,则可以定义指针为通用型,此时指针长度为3字节,第一字节表示存贮器类型编码,第二、三字节分别表示所指地址的高位和低位。第一字节表示的存贮器类型编码见表10-3:表10-3通用型指针的存贮类型编码 第10章单片机C语言编程10.3数据的存贮类型和存贮模式数据的存贮类型和存贮模式10.3.1数据的存贮类型数据的存贮类型C51是面向8XX51系列单片机及硬件控制系统的开发语言,它定义的任何变量必须以一定的存贮类型的方式定位在8XX51的某一存贮区中,否则便没有意义
12、。因此在定义变量类型时,还必须定义它的存贮类型,C51的变量的存贮类型如表10-4所示:第10章单片机C语言编程表10-4C51的变量的存贮类型 访问内部数据存贮器(idata)比访问外部数据存贮器(xdata)相对要快一些,因此,可将经常使用的变量置于内部数据存贮器中,而将较大及很少使用的数据变量置于外部数据存贮器中。例如定义变量x语句:datacharx(等价于chardatax)。如果用户不对变量的存贮类型定义,则编译器承认默认存贮类型,默认的存贮类型由编译控制命令的存贮的模式部分决定。第10章单片机C语言编程10.3.2存贮器模式存贮器模式存贮器模式决定了变量的默认存贮器类型、参数传递
13、区和无明确存贮区类型的说明。C51的存贮器模式有SMALL、LARGE和COMPACT(见表10-5)。在固定的存贮器地址进行变量参数传递是C51的一个标准特征,在SMALL模式下参数传递是在内部数据存贮区中完成的。LARGE和COMPACT模式允许参数在外部存贮器中传递。C51同时也支持混合模式,例如在LARGE模式下生成的程序可将一些函数分页放入SMALL模式中从而加快执行速度。例如设例如设C语言源程序为语言源程序为PROR.C,若使程序中的变量类型和参数传递区限定若使程序中的变量类型和参数传递区限定 在在外部数据存贮区外部数据存贮区,有两种方法:,有两种方法:方法方法1:用:用C51对对
14、PROR.C进行编译时,使用命令进行编译时,使用命令C51 PROR.C COMPACT。方法方法2:在程序的第一句加预处理命令:在程序的第一句加预处理命令#pragma compact 表10-5存贮器模式 第10章单片机C语言编程10.3.3变量说明举例变量说明举例datacharvar;/*字符变量var定位在片内数据存贮区*/charcodeMSG=PARAMETER:;/*字符数组MSG定位在程序存贮区*/unsignedlongxdataarray100;/*无无符符号号长长型型数数组组定定位位在在片片外外RAM区区,每每元元素素占占4bytes*/floatidatax,y,z;
15、/*实型变量x,y,z,定位在片内用间址访问的内部RAM区*/bitlock;/*位变量Lock定位在片内RAM可位寻址区*/unsignedintpdatasion;/*无符号整型变量sion定位在分页的外部RAM*/unsignedcharxdatavector1044/*无无符符号号字字符符型型三三维维数数组组,定定位位在在片片外外RAM区区*/sfrP0=0 x80;/*定义P0口,地址为80H*/charbdataflags;/*字符变量flags定位在可位寻址内部RAM区*/sbitflag0=flags0;/*定义flag0为flags.0*/第10章单片机C语言编程如果在变量说
16、明时略去存贮器类型标志符,编译器会自动选择默认的存贮器类型。默认的存贮器类型由控制指令SMALL、COMPACT和LARGE限制。例如如果声明charvar,则默认的存贮器模式为SMALL,var放在data存贮区;如果使用COMPACT模式,var放入idata存贮区;在使用LARGE模式的情况下,var被放入外部数据存贮区(xdata存贮区)。10.3.4指针变量说明举例longxdata*px;/*指针px指向long型xdata区(每个数据占四个单元,指针自身在默认存贮器(如不指定编译模式在data区),指针长度为2个字节*/charxdata*datapd;/*指针pd指向字符型xd
17、ata区,自身在data区,长度2字节*/datacharxdata*pd;/*与上例等效*/dataint*pn;(和int*datapn及intr*pn等效)/*定义一个类型为int型的通用型指针,指针自身在data区长度为3字节*/第10章单片机C语言编程在上例的指针声明中包含如下几个内容:1)指针变量名(如px)前面冠以“*”,表示px为指针型变量,此处*不带取内容之意。2)指针指向的存贮类型,即指向哪个存贮区,它决定了指针本身的长度(见表10.1)。存贮类型声明的位置在数据类型和指针名(如*px)之间,如无次项声明,则此指针型变量为通用型。3)指针指向的存贮区的数据类型,即被指向的存
18、贮区以多少个单元作一个数据单位,当程序通过指针对该区操作时,将按此规定的单元个数的内容作为一个数据操作。4)指针变量自身的存贮类型,即指针处于什么区与自身的长度无关,该声明可位于声明语句的开头,也可在“*”和变量名之间。此项由编译模式放在默认区,如无规定编译模式,通常在data区。第10章单片机C语言编程10.4C51对对SFR、可寻址位、存储器和可寻址位、存储器和I/O口的定义口的定义10.4.1特殊功能寄存器特殊功能寄存器SFR定义定义C51提供了一种自主形式的定义方式,使用特定关键字sfr如sfrSCON=0 x98;/*串行通信控制寄存器地址98H*/sfrTMOD=0 x89;/*定
19、时器模式控制寄存器地址89H*/sfrACC=0 xe0;/*A累加器地址E0H*/sfrP1=0 x90;/*P1端口地址90H*/定义了以后,程序中就可以直接引用寄存器名。C51也建立了一个头文件reg51.h(增强型为reg52.h),在该文件中对所有的特殊功能寄存器的进行了sfr定义,对特殊功能寄存器的有位名称的可寻址位进行了sbit定义,因此,只要用包含语句#include,就可以直接引用特殊功能寄存器名,或直接引用位名称。要特别注意:在引用时特殊功能寄存器或者位名称必须大写。第10章单片机C语言编程10.4.2 10.4.2 对位变量的定义对位变量的定义C51对位变量的定义有三种方
20、法:1.将变量用bit类型的定义符定义为bit类型:如bitmn;mn为位变量,其值只能是“0”或“1”,其位地址C51自行安排在可位寻址区的bdata区。2.采用字节寻址变量.位的方法:如bdataintibase;/*ibase定义为整型变量*/sbitmybit=ibase15;/*mybit定义为ibase的D15位*/这里位是运算符“”相当于汇编中的“”,其后的最大取值依赖于该位所在的字节寻址变量的定义类型,如定义为char最大值只能为7。第10章单片机C语言编程3.对特殊功能寄存器的位的定义方法1:使用头文件及sbit定义符;多用于无位名的可寻址位。例如#includesbitP1
21、-1=P11;/*P1-1为P1口的第1位*/sbitac=ACC7;/*ac定义为累加器A的第7位*/方法2:使用头文件reg51.h,再直接用位名称。例如#includeRS1=1;RS0=0;方法3:用字节地址位表示例如sbitOV=0 xD02;方法4:用寄存器名.位定义例如sfrPSW=0 xd0;/*定义PSW地址为d0H*/sbitCY=PSW7;/*CY为PSW7*/第10章单片机C语言编程10.4.3C51对存贮器和外接对存贮器和外接I/O口的绝对地址访问口的绝对地址访问1.对存贮器的绝对地址访问利用绝对地址访问的头文件absacc.h可对不同的存贮区进行访问。该头文件的函数
22、有:CBYTE(访问code区字符型)DBYTE(访问data区字符型)PBYTE(访问pdata或I/O区字符型)XBYTE(访问xdata或I/O区字符型)还有CWORD、DWORD、PWORD和XWORD四个函数,它们的访问区域同上,只是访问的类型为int型。例10-1#include#define com XBYTE0 x07ff 那么后面程序com变量出现的地方,就是对地址为07ffH的外部RAM或I/O口进行访问。第10章单片机C语言编程例10-2XWORD0=0 x9988;即将9988H(int类型)送入外部RAM的0号和1号单元。使用中要注意:absacc.h一定要包含进程序
23、,XBYTE必须大写。2.对外部I/O口的访问由于单片机的I/O口和外部RAM统一编址,因此对I/O口地址的访问可用XBYTE(MOVXDPTR)或PBYTE(MOVXRi)进行。例10-3XBYTE0Xefff=0 x10;将10H输出到地址为EFFFH端口第10章单片机C语言编程10.5C51的运算符的运算符1赋值运算符:将“”的右边的值赋值给左边的变量.2.C51的算术运算符:(加或正号);(减或负号);*(乘号);/(除号);%(求余)优先级为:先乘除,后加减,先括号内,再括号外3.C51的关系运算符有六种:(小于);(大于);=(小于等于);=(大于等于);=(相等);!=(不相等)
24、优先级:前四个高,后二个“=”和“!=”级别低。第10章单片机C语言编程4C51的逻辑运算符有三种:&(逻辑与);|(逻辑或);!(逻辑非);逻辑表达式和关系表达式的值相同,以0代表假,以1代表真。以上三种运算的优先级见图10.1。5C51的按位操作的运算符有六种:&(按位与);(按位或);(按位异或);(位取反);(位右移)(注:补零移位)例1.a=0 xf0H;表达式a=a值为0FH例2.a=0 xea;表达式a2值为A8H,即a值左移两位,移位后空白位补0。6.自增、自减运算符:+i,-i(在使用i之前,先使i值加1,减1)i+,i-(在使用i之后,再使i值加1.,减1)例设i原值为5j
25、=+i则j值为6,i值也为6j=i+则j值为5,i值为6|非算术运算关系运算&和|=赋值运算图图10-1 运算符的优先级运算符的优先级 第10章单片机C语言编程7复合赋值运算符:+=;-=;*=;/=;%=;=;&=;=;|=。例:a+=b相当于a=a+b。a=7.相当于a=a7.。8.对指针操作的运算符:&取地址运算*间址运算符例a=&b;取b变量的地址送变量ac=*b;将以b的内容为地址的单元的内容送c这里要注意:“&”与按位与运算符的差别,如果“&”为“与”,&的两边必须为变量或常量;“*”与指针定义时指针前的“*”的差别。如char*pt,这里的“*”只表示pt为指针变量,不代表间址取
26、内容的运算。第10章单片机C语言编程10.6函函数数C语言程序由函数组成,下面介绍函数的要点。10.6.1函数的分类及定义从用户使用角度划分,函数分为库函数和用户自定义函数。库函数是编译系统为用户设计的一系列标准函数(见本书附录二),用户只需调用,而无需自己去编写这些复杂的函数,如前面所用到的头文件reg51.h、absacc.h等,有的头文件中包括一系列函数,要使用其中的函数必须先使用#include包含语句,然后才能调用。用户自定义函数是用户根据任务编写的函数从参数形式上函数分为无参函数和有参函数。有参函数即是在在调用时,调用函数用实际参数代替形式参数,调用完返回结果给调用函数。第10章单
27、片机C语言编程10.6.2函数的定义函数的定义函数以“”开始,以“”结束。无参函数的定义:返回值类型 函数名()函数体语句 如果函数没有返回值,可以将返回值类型设为void。有参函数的定义:返回值类型 函数名(形式参数表列)形式参数类型说明 函数体语句return(返回形参名)也可以这样定义返回值类型 函数名(类型说明 形式参数表列)函数体语句 return(返回参形名)其中形式参数表列的各项要用“,”隔开,通过return语句将需返回的值返回给调用函数。第10章单片机C语言编程10.6.3函数的调用函数的调用函数调用的形式为:函数名(实际参数表列);实参和形参的数目相等类型一致,对于无参函数
28、当然不存在实际参数表列。函数的调用方式有三种:函数调用语句:即把被调函数名作为调用函数的一个语句;如fun1()。被调函数作为表达式的运算对象,如result=2*get(a,b)此时get函数中的a,b应为实参,其以返回值参予式中的运算。被调函数作为另一个数的实际参数如m=max(a,get(a,b);函数get(a,b)作为函数max()的一个实际参数。第10章单片机C语言编程10.6.4对被调函数的说明对被调函数的说明如果被调函数出现在主调函数之后,在主调函数前应对被调函数作以说明,形式为:返回值类型被调函数名(形参表列);如果被调函数出现在主调函数之前,可以不对被调函数说明。下面以一个
29、简单例子来说明intfun1(a,b)inta,b;intc;c=a+b;return(c);main()intd,0u=3,v=2;d=2*fun(u,v);上例被调函数在主调函数前,不用说明。第10章单片机C语言编程intfun1(a,b);main()intd,u=3,v=2;d=2*fun1(u,v);intfun1(a,b);inta,b;intc;c=a+b;return(c);上例中被调函数在主调函数后,在前面对被调函数进行说明。第10章单片机C语言编程10.7C语言编程实例语言编程实例由于C51编译器是针对单片机的,因此ANSI C中的scanf和printf等对PC电脑的键盘
30、和监视器的输入、输出语句无效。运算的数据可以通过变量置入或取出,这时C51会自动安排使用的存贮单元。当然也可以用户自行通过具体的内存地址置入数据或从特定地址取出数据,这就少不了要会观察具体地址的内容或改变该地址的内容,C语言的编程上机调试见本教材的实验部分。下面通过一个例子说明C语言程序编译后生成的机器代码及对应的反汇编程序,从中引出一些道理。第10章单片机C语言编程10.7.1 10.7.1 顺序程序的设计顺序程序的设计例例105完成完成1980524503的编程的编程分析:两个乘数比较大,其积更大,采用unsignedlong类型,设乘积存放在外部数据存贮器0号开始的单元。程序如下:mai
31、n()unsignedlongxdata*p;/*设定指针p指向类型为unsignedlong的外部RAM区*/unsignedlonga=19805;/*设置a为unsignedlong类型,并赋初值*/unsignedlongb=24503,c;/*设置b和积为unsignedlong类型,并赋初值*/p=0;/*设地址指向0号单元*/c=a*b;*p=c;/*积存入外部RAM0号单元*/第10章单片机C语言编程 上机通过软件仿真调试,在变量观察窗口看到运算结果c=48528195,即为乘积的十进制数。观察XDATA区(外部RAM)的0000H0003H单元分别为1C EC D0 7B,即
32、存放的为乘积的十六进制数。观察DATA区(内部RAM区):地址 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 1C EC D0 7B 00 00 4D 5D 00 00 5F B7 C变量(积)a变量 b变量 可见定义为unsigned long类型,给每个变量分配四个单元,如果定义类型不对,将得不到 正确的结果。对于复杂的运算通常采用查表的方法。如同汇编程序设计一样,在程序存贮器建立一张表,在C语言中表格定义为数组,表内数据(元素)的偏移量表现为下标。数组的使用如同变量一样,要先进行定义:说明数组名、维数、数据类型和存贮类型,在定义数组的同时,还可以给数组各元素赋初
33、值。通过下例说明C51数组的定义方法和用C语言编查表程序的方法。第10章单片机C语言编程例106片内RAM20H单元存放着一个005H的数,用查表法,求出该数的平方值放入内部RAM21H单元。main()charx,*pcharcodetab6=0,1,4,9,16,25;p=0 x20;x=tab*p;p+;*p=x;第10章单片机C语言编程10.7.2循环程序的设计循环程序的设计C语言的循环语句有以下几种形式1.while(表达式)语句;其中表达式为循环条件,语句为循环体,当表达式值为真(值为非0),重复执行“语句”。语句可只一条以“;”结尾;可以多条组成复合语句,复合语句必须用括起;也可
34、以没有语句,通常用于等待中断,或查询。2.do语句;while(表达式)表达式为真执行循环体“语句”,直至表达式为假,退出循环执行下一个语句。3.for(表达式1;表达式2;表达式3;)语句;其中语句为循环体。执行过程是:执行表达式1后进入循环体,如表达式2为假,按表达式3修改变量,再执行循环体,直到表达式2为真.语句中的表达式可以省其中任一项甚至全部,但二个分号不可省,如for(;语句;为无限循环,for(i=4;i+)语句i从4开始无限循环,for(;i100;)相当于while(i100)第10章单片机C语言编程例10-7while(P1&0 x01)=0);即如果P1.0=0,循环执行
35、空语句,直到P1.0变为1,此语句用于对P1.0进行检测。例10-8分析下列程序的执行结果:main()intsum=0,i;dosum+=I;i+;while(i=10);本程序完成0+1+2+10的累加,执行后sum=55例10-9将例10-8改用for语句编程mainintsum=0,i;for(i=0;i10;i+)sun+=i;第10章单片机C语言编程10.7.3分支程序的设计分支程序的设计C语言的分支选择语句有以下几种形式:1.if(表达式)语句;句中表达式为真执行语句,否则执行下一条语句。当花括号中的语句不只一条,花括号不能省。2.if(表达式)语句1;else语句2;句中表达式
36、为真执行语句1,否则执行语句2为了能无论哪种情况,执行完后都执行下一条语句。if语句可以嵌套。3.switch(表达式)case常量表达式1:语句1;break;case常量表达式2:语句2;break;case常量表达式n:语句n;break;default:语句n+1;第10章单片机C语言编程说明:语句先进行表达式的运算,当表达式的值与某一case后面的常量表达式相等,就执行它后面的语句。当case语句后有break语句时,执行完这一case语句后,跳出switch语句,当case后面无break语句,程序将执行下一条case语句。如果case中常量表达式值和表达式的值都不匹配,就执行de
37、fault后面的语句。如果无default语句就退出switch语句。default的次序不影响执行的结果,也可无此语句。case语句适于多分支转移的情况下使用。第10章单片机C语言编程例10-10片内RAM的20H单元存放一个有符号数x,函数y与x有如下关系式:xx0y=20Hx=0 x+5x0设y存放于21H单元,程序如下main()charx,*p,*y;p=0 x20;y=0 x21;for(;)x=*p;if(x0)*y=x;if(x0)*y=x+5;if(x=0)*y=0 x20;程序中为观察不同数的执行结果,采用了死循环语句for(;)。第10章单片机C语言编程例10-11有两个
38、数a和b,根据R3的内容转向不同的处理子程序:r3=0,执行子程序pr0(完成两数相加)r3=1,执行子程序pr1(完成两数相减)r3=2,执行子程序pr2(完成两数相乘)r3=3,执行子程序pr3(完成两数相除)分析:C语言中的子程序即为函数,因此需编四个处理的函数,如果主函数在前,主函数要对子函数进行说明;如果子函数在前,主函数无须对子函数说明,但是无论子、主函数的顺序如何,程序总是从主函数开始执行,执行到调用子函数就会转到子函数执行.在C51编译器中通过头文件reg51.h可以识别特殊功能寄存器,但不能识别R0R7通用寄存器,因此R0R7只有通过绝对地址访问识别,程序如下:第10章单片机
39、C语言编程#include#definer3DBYTE0 x03intc,c1,a,b;pr0()c=a+b;pr1()c=a-b;pr2()c=a*b;pr3()c=a/b;main()a=90;b=30;for(;)switch(r3)case0:pr0();break;case1:pr1();break;case2:pr2();break;case3:pr3();break;c1=56;在上述程序中,为便于调试观察,加了在上述程序中,为便于调试观察,加了C1=56C1=56语句,并使用了死循环语句语句,并使用了死循环语句for(;)for(;),用,用Ctrl+C Ctrl+C 可退出死
40、循环。可退出死循环。第10章单片机C语言编程10.8 10.8 单片机资源的单片机资源的C C语言编程实例语言编程实例例例10-1210-12 在在3.13.1节节曾曾用用汇汇编编语语言言完完成成了了外外部部RAMRAM的的000EH000EH单单元元和和000FH000FH单单元的内容交换,现改用元的内容交换,现改用C C语言编程。语言编程。C C语语言言对对地地址址的的指指示示方方法法可可以以采采用用指指针针变变量量,也也可可以以引引用用absacc.habsacc.h头头文件作绝对地址访问,下面采用绝对地址访问方法。文件作绝对地址访问,下面采用绝对地址访问方法。#includemain(
41、)charc;for(;)c=XBYTE14;XBYTE14=XBYTE15;XBYTE15=c;第10章单片机C语言编程程序中为方便反复观察,使用了死循环语句程序中为方便反复观察,使用了死循环语句for(;)for(;)只要用只要用Ctrl+CCtrl+C即可退出即可退出死循环。死循环。上面程序通过编译,生成的机器代码和反汇编程序如下上面程序通过编译,生成的机器代码和反汇编程序如下:0000 020014 LJMP 0014H 0000 020014 LJMP 0014H 0003 90000E MOV DPTR0003 90000E MOV DPTR,#000EH#000EH 0006 E
42、0 MOVX A 0006 E0 MOVX A,DPTRDPTR0007 FF MOV R70007 FF MOV R7,A A0008 A3 INC DPTR0008 A3 INC DPTR0009 E0 MOVX A0009 E0 MOVX A,DPTRDPTR000A 90000E MOV DPTR000A 90000E MOV DPTR,#000EH#000EH000D F0 MOVX DPTR000D F0 MOVX DPTR,A A 000E A3 INC DPTR000E A3 INC DPTR000F EF MOV A000F EF MOV A,R7R7 0010 F0 MOV
43、X DPTR 0010 F0 MOVX DPTR,A A0011 80F0 SJMP 0003H0011 80F0 SJMP 0003H0013 22 RET0013 22 RET0014 787F MOV R00014 787F MOV R0,#7FH#7FH0016 E4 CLR A0016 E4 CLR A0017 F6 MOV R00017 F6 MOV R0,A A0018 D8FD DJNZ R00018 D8FD DJNZ R0,0017H0017H001A 758107 MOV SP001A 758107 MOV SP,#07H#07H 001D 020003 LJMP 000
44、3H 001D 020003 LJMP 0003H第10章单片机C语言编程例中可见:例中可见:一一进进入入C C语语言言程程序序,首首先先执执行行初初始始化化,将将内内部部RAMRAM的的0 07FH 7FH 128128个个单单元元清清零零,然然后后置置SPSP为为07H(07H(视视变变量量多多少少不不同同,SPSP置置不不同同值值,依依程程序序而而定定),因因此此如如果果要要对对内内部部RAMRAM置置初初值值,一一定定要要在在执行了一条执行了一条C C语言语句后进行。语言语句后进行。C C语语言言程程序序设设定定的的变变量量,C51C51自自行行安安排排寄寄存存器器或或存存贮贮器器作作
45、参参数数传传递递区区,通通常常在在R0R0R7(R7(一一组组或或两两组组,视视参参数数多多少少定定),因因此此,如果对具体地址置数据,应避开这些如果对具体地址置数据,应避开这些R0R0R7R7的地址。的地址。如果不特别指定变量的存贮类型,通常被安排在内部如果不特别指定变量的存贮类型,通常被安排在内部RAMRAM中。中。第10章单片机C语言编程10.8.2 10.8.2 并行口及键盘的并行口及键盘的C C语言编程语言编程例例10-13用用P1.0输出输出1KHz和和500Hz的音频信号驱动扬声器的音频信号驱动扬声器,作作报警信号报警信号,要求要求1KHz信号响信号响100ms,500Hz信号响
46、信号响200ms,交替交替进行进行,P1.7接一开关进行控制接一开关进行控制,当开关合上当开关合上,响报警信号响报警信号,当开当开关断关断Kk告警信号停止告警信号停止,编出程序编出程序.分析分析500Hz信号周期为信号周期为2ms,信号电平为每信号电平为每1ms变反一次变反一次.1KHz信号周期为信号周期为1ms,信号电平每信号电平每500 s变反一次。用变反一次。用C语言编程语言编程如下:如下:第10章单片机C语言编程#includesbitP10=P10;0;sbitP17=P17;7;main()main()unsigned char i,j;unsigned char i,j;whil
47、e(1)while(1)while(P17=0)while(P17=0)for(i=1;i=150;i+)/*for(i=1;i=150;i+)/*控制音响时间控制音响时间*/P10=P10=P10;P10;for(j=0;j=50;j+);/*for(j=0;j=50;j+);/*延时完成信号延时完成信号gougou周期时间周期时间*/for(i=1;i=100;i+)/*for(i=1;i=100;i+)/*控制音响时间控制音响时间*/P10=P10=P10;P10;for(j=0;j=100;j+);/*for(j=0;j=100;j+);/*延时,完成信号周期时间延时,完成信号周期时间
48、*/第10章单片机C语言编程例例10-14在在下图中下图中8XX518XX51接有五个共阴极数码管的动态显示接口电路,接有五个共阴极数码管的动态显示接口电路,开关打向位置开关打向位置“1 1”时,显示时,显示“1234512345”字样,当开关打向字样,当开关打向“2 2”时,显时,显示示HELLO字样,字样,C语言编程程序清单如下。语言编程程序清单如下。图图10-7 接五个接五个共阴极数码管的动态显示接口共阴极数码管的动态显示接口 第10章单片机C语言编程用用C语言完成上述功能编程语言完成上述功能编程#include#defineuintunsignedint#deefineucharuns
49、ignedcharsbitP17=P17;main()ucharcodetab15=0 x86,0 xdb,0 xcf,0 xe6,0 xed;/*“15”的的字字形形码码,因因P1.7接接的的开开关关,最最高高位位送送的的“1”*/ucharcodetab25=0 xf8,0 xf9,0 xb8,0 xb8,0 x,bf;/*“HELLO”的段码的段码“1”*/uchari;unitj;while(1)p3=0 x011 for(i=0;i+)if(p17=1)P1=tab1i;elseP1=tab2i;P3=1;for(j=0;j=25000;j+);第10章单片机C语言编程例例10-15
50、以以P1.0P1.3作输出线,以作输出线,以P1.4P1.7作输入线,如图作输入线,如图4-6所示所示。C语言编程程序清单如下:语言编程程序清单如下:#include#defineucharunsignedchar#defineuintunsignedintvoiddlms(void);ucharkbscan(void);/*函数说明函数说明*/voidmain(void0;ucharkey;while(1)key=kbscan();/*键盘扫描函数,返回键码送键盘扫描函数,返回键码送key保存保存*/dlms();voiddlms(void)/*延时延时*/uchari;for(i=200;