基于Proteus和Keil的C51程序设计项目教程(第2版):理论、仿真、实践相融合
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.7 初识函数

C语言是函数式语言,必须有且只能有一个名为main的主函数。C语言程序的执行总是从main()函数开始,在main()函数中结束的,函数不能嵌套定义,但可嵌套调用。

不管是main()主函数还是其他一般函数,都由“函数定义”和“函数体”两个部分构成。函数体由两类语句组成:一类为声明语句,用来对函数中将要用到的局部变量进行定义;另一类为执行语句,用来完成一系列功能或算法处理。所有函数在定义时都是相对独立的,一个函数中不能再定义其他函数。

2.7.1 函数格式

函数定义包括返回值类型、函数名(形式参数声明列表)等,格式如下。

返回值类型:也称为函数类型。若无返回值,则写void。

函数名:其定义与变量定义规则一样,最好见名知意。

形参表:若有参数传递,则其类型、数量、顺序与调用时的实参要一致;若无,则空或写void。[]内的各部分为可选项,根据具体函数书写。

返回语句:有三种形式,如下。

返回语句的功能:退出被调函数,返回主调函数,有表达式的同时把返回值带给主调函数。函数中可有多个return语句,若无return语句,则遇“}”时,自动返回主调函数。

函数模式:也就是编译模式、存储模式,可以为small、compact和large。省略时,则使用文件的编译模式。

reentrant:C51定义的关键字,表示该函数为可重入函数。所谓可重入函数,就是允许被递归调用的函数。

interrupt:C51定义的关键字,中断函数必须通过它进行修饰。m为中断号。

using:定义工作寄存器组所用的关键字。n为工作寄存器组号。

2.7.2 函数调用中参数的传递

函数调用的一般形式如下:

调用有参数的函数时,若实参列表包含多个实参,则实参之间用逗号隔开。

按照函数调用在主调函数中出现的位置,函数调用方式有以下三种:

(1)函数语句。把被调用函数作为主调用函数的一个语句时,不要求函数返回值,只要求函数完成一定的操作,如“delay(1000);”。

(2)函数表达式。函数被放在一个表达式中,以一个运算对象的方式出现时,要求被调函数带有返回语句,以返回一个明确的数值参加表达式的运算,如“c=2*max(a,b);”。

(3)函数参数。被调函数作为另一个函数的参数,如“disply(max(a,b));”。

举例:两个数据交换的C程序设计,无须有关单片机的一些设计(如串口定义等)。

● 形式参数:定义函数时函数名后面括号中的变量名。

● 实际参数:调用函数时函数名后面括号中的表达式。

图2-31 参数的传值分析

由此可见,数值传递不能解决主调程序中数据的互换,只有传地址时才能解决。而传地址必须通过指针,详见6.6.3节。

2.7.3 自定义函数的声明

函数必须先定义后再使用,如果函数的定义在调用语句之后,则在调用之前需对函数进行声明。

函数的声明是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便调用函数时系统能够对照检查。

● 函数的声明后面要加分号。

● 外部函数声明:

调用的函数不在本文件内部,而在其他C文件中,声明时须带extern。

2.7.4 预处理:#include引用库、自定义函数

预处理命令有三类:宏定义#define(见4.1.5节)、文件包含#include、条件编译(见2.3.3节)。它们的格式特点是由“#”开头,占单独书写行,语句尾不加分号。

通过#include可包含头文件*.h和源文件*.c。

1.包含库文件

C51软件包的库包含许多标准的应用程序,也称为库函数,使用库函数时应注意:

(1)函数功能;

(2)函数参数的数目和顺序,以及各参数的意义和类型;

(3)函数返回值的意义和类型;

(4)需要使用的包含文件,如#include<reg51.h>、#include<stdio.h>。

2.包含自定义文件

程序中可包含自定义的头文件(主要是宏定义、数据结构定义、函数说明等),也可自定义的函数,封装在一个头文件中,通过包含该头文件,可引用其中的函数,见6.1.3节中的seg_dis.h、6.4.4节中的key16.h。另外源文件*.c也可被包含。

注意:

(1)一个include命令只能包含一个头文件,若要包含多个头文件,则需分别使用include命令。

(2)如果文件1包含文件2,文件2要用到文件3中的内容,则可在文件1中用两个include命令分别包含文件2和文件3,但文件3应出现在文件2之前,即在文件file1.c中定义:

这样file1和file2都可使用file3中的内容,在file2中不必再写#include“file3.h”。

(3)文件包含可以嵌套,即在一个被包含的文件中又可以包含另一个被包含的文件。

2.7.5 设计变时长的延时函数头文件Dly_nms.h

在2.3.4节设计的延时函数Dly05s()的延时时间是固定的。为方便不同时长的应用,可将其设计为有参函数,通过调用语句传递或大或小的数值满足或长或短的延时要求,且将该函数设计为一头文件Dly_nms.h。其他工程只要包含该头文件,就可调用该延时函数头文件,达到共享目的。该头文件的设计如下:

2.7.6 进阶设计与思路点拨7:变速流水灯

设计某种亮灯规律的流水灯:(1)速度越来越快或越来越慢;(2)以渐变的速度在最快与最慢速度间循环运行。