第4章单片机C语言2_第1页
第4章单片机C语言2_第2页
第4章单片机C语言2_第3页
第4章单片机C语言2_第4页
第4章单片机C语言2_第5页
已阅读5页,还剩13页未读 继续免费阅读

下载本文档

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

文档简介

4.7函数,4.6.1函数的分类及定义C语言程序由函数组成,从用户使用角度划分,函数分为库函数和用户定义函数:库函数是编译系统已经为用户设计好的一系列标准函数(见本书附录二),用户只需正确调用,如前面所用到的头文件reg51.h等,有的头文件中包括了一系列函数,要使用其中的函数必须先使用#Include来申明,然后才能调用。用户自定义函数是用户根据任务自己编写编写的函数。从参数形式上函数分为无参函数和有参函数。无参函数:函数中无参数定义。有参函数:函数中定义了形式参数,在调用时,调用函数用实际参数代替形式参数,调用完将运算结果给调用函数。,4.6.2函数的定义无参函数的定义:返回值类型函数名()函数体语句如果函数没有返回值,可以将返回值类型设为void;函数以“”开始,以“”结束。有参函数的定义:返回值类型函数名(形式参数表)形式参数类型说明/*单独说明*/函数体语句return(返回形参名)也可以这样定义:返回值类型函数名(类型说明形式参数表)/*说明放在参数表内*/函数体语句return(返回形参名)其中形式参数表中的各项要用,隔开,通过return语句将需返回的值返回给调用函数。,4.6.3.函数的调用函数调用的形式为:函数名(实际参数表);对于无参函数当然不存在实际参数表。实参和形参的数目要相等类型要一致。,函数的调用方式有三种函数调用语句:即把被调函数名作为调用函数的一个语句,如fun1();被调函数作为表达式的运算对象:如rett=2*get(a,b);此时get函数中的a,b应为实参,用它的返回值参予式中的运算。被调函数作为另一个数的实际参数:如m=max(a,get(a,b);函数get(a,b)作为max()的一个实际参数被调用。,4.7.4对被调函数的说明,如果被调函数出现在主函数之后,在主函数前应对被调函数加以说明,形式为:返回值类型被调函数名(形参表);如: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);/*函数返回值*/此例被调函数放在主函数之后、所以在主函数前要先对被调函数进行说明。,被调函数出现在主函数之前,可以不对被调函数说明。下面给出一个简单例子:intfun1(a,b)inta,b;intc;c=a+b;return(c);main()intd,u=3,v=2;d=2*fun1(u,v);此例中被调函数出现在主函数前,所以不需事先说明。,4.8单片机的C语言编程实例由于C51编译器是针对单片机的,因此ANSIC中的scanf和printf等用于PC机的输入输出语句无效。运算的数据可以通过设置变量的方法来置入或取出,也可以由用户自行通过具体的内存地址置入数据或从特定地址取出数据。C语言的上机调试和汇编程序使用同一仿真调试软件。下面是一个C语言程序编译后生成的机器代码及对应的反汇编程序。,4.8.1、C语言程序的反汇编程序(源代码)在2.4节曾用汇编语言完成了外部RAM的000EH单元和000FH单元的内容交换,现改用C语言编程。C语言对地址的指示方法可以采用指针变量,也可以引用absacc.h头文件作绝对地址访问,下面采用绝对地址访问的方法。,#includemain()charc;for(;)c=XBYTE14;XBYTE14=XBYTE15;XBYTE15=c;程序中为方便反复观察,使用了死循环语句for(;),用Ctrl+C可退出死循环。,左面程序通过编译后的机器代码和反汇编程序如下:0000LJMP0014H0003MOVDPTR,#000EH0006MOVXA,DPTR0007MOVR7,A0008INCDPTR0009MOVXA,DPTR000AMOVDPTR,#000EH000DMOVXDPTR,A000EINCDPTR000FMOVA,R70010MOVXDPTR,A0011SJMP0003H0013RET0014MOVR0,#7FH0016CLRA0017MOVR0,A0018DJNZR0,0017H001AMOVSP,#07H001DLJMP0003,例中可见:一进入C语言程序,首先执行将内部RAM的07FH128个单元清零,然后置SP为07H(视变量多少不同,SP置不同值,依程序而定),因此如果要对内部RAM置初值,一定要在执行了一条C语言语句后进行。C语言编译程序会按照定义设定变量,自行安排寄存器或存贮器作参数传递区,通常使用R0R7(一组或两组,视参数多少定),因此,在设置数据时,要设法避开R0R7的地址区域。如果不特别指定变量的存贮类型,通常被安排在内部RAM中。,4.8.2、顺序程序的设计,例1.完成1980524503的编程分析:两个乘数比较大,其积更大,采用unsignedlong类型,设乘积存放在外部数据存贮器0号开始的单元。程序如下:,上机通过软件仿真调试,在变量观察窗口看到运算结果c=485281915,即为乘积的十进制数。观察XDATA区(外部RAM)的0000H0003H单元分别为1CECD07B,即存放的是485281915的十六进制数。观察DATA区:000102030405060708090A0B1CECD07B00004D5D00005FB7c变量(积)a变量b变量,由于定义为unsignedlong类型,给每个变量分配了四个单元,如果定义类型不对,将得不到正确的结果。如果未定义变量类型,默认为内部RAM,将a、b、c变量安排在内部RAM中。对于复杂的运算通常采用查表的方法。和汇编程序设计一样,在程序存贮器中建立一张表,在C语言中将表格定义为数组,表内数据(元素)的偏移量就是数组的下标。数组的使用也要先进行定义:即说明数组名、维数、数据类型和存贮类型,在定义数组的同时还可以给数组各元素赋初值。通过下例说明C51数组的定义方法和用C语言编查表程序的方法,例4-6片内RAM20H单元存放着一个05H的数,用查表法,求出该数的平方值放入内部RAM21H单元。,main()charx,*p;charcodetab6=0,1,4,9,16,25;p=0 x20;x=tab*p;p+;*p=x;,4.8.3、循环程序的设计,C语言的循环语句有以下几种形式1.while(表达式)语句;其中表达式为循环条件,语句为循环体,当表达式值为真(值为1),重复执行“语句”。,3.for(表达式1;表达式2;表达式3;)语句;,循环体语句可以只有一条,以“;”结尾;也可以由多条组成复合语句,复合语句必须用括起;也可以没有语句,这时通常用于等待中断。,for(;);,for(i=0;i=10;i+)sum+=i;,for(i=0;i=10;i+)sum+=i;tot=tot+sum;,N,Y,4.7.4、分支程序的设计C语言的分支选择语句有以下几种形式:1.If(表达式)语句;句中表达式为真则执行语句,否则执行下一条语句。当花括号中的语句不只一条时,花括号不能省。2.If(表达式)语句1;else语句2;句中表达式为真则执行语句1,否则执行语句2再执行下一条语句,见下面流程图。If语句可以嵌套。,例:片内RAM的20H单元存放一个有符号数x,函数y与x有如下关系式:(设y存放于21H单元)xx0y=20Hx=0x+5x0,程序如下:main()signedcharx,*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(;),上机调试时要退出死循环可用Ctrl+C。,3.Switchcase语句该语句常用于多分支转移,格式如下:switch(表达式)case常量表达式1:语句1;break;case常量表达式2:语句2;break;case常量表达式n:语句n;break;default;(语句n+1;,4-9.有两个数a和b,根据R3的内容转向不同子程序r3=0,执行子程序pr0(完成两数相加)r3=1,执行子程序pr1(完成两数相减)r3=2,执行子程序pr2(完成两数相乘)r3=3,执行子程序pr3(完成两数相除)分析:C语言中的子程序即为函数,因

温馨提示

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

最新文档

评论

0/150

提交评论