项目七 让我的单片机智能化——函数

项目七 让我的单片机智能化——函数

一、项目简介

小到手表、收音机、电脑,大到火车、飞机、航母,都包含了许多元器件——相对独立的模块,它们可以分别被维修、更新或替换,而不影响其他部分。

类似地,在程序中也可以制造和使用自己的“元器件”——功能相对独立的模块——函数。一个个函数可以被看作是“蒙着面干活”的黑箱,它们分别用于实现不同的功能,并随时听候我们调用。

有了函数,不仅可大大简化编程的复杂度,还可以使程序逻辑更为清晰。

函数能够实现C语言的模块化程序设计,通过函数,可以让单片机智能化运行。

二、项目目标

本项目为C语言的模块化程序设计,将相对独立的功能用函数来实现。要求了解C语言中函数的概念,掌握函数的定义方法、函数的参数、函数的调用方法、函数的原型与声明。

三、工作任务

根据本项目的要求,以任务驱动的方式,用函数实现模块化程序设计。

① 用有参函数控制LED闪烁速度。

② 按键识别功能模块的函数实现。

③ 按键控制LED流水灯速度。

四、知识准备

1.函数概述

在设计一个较大的程序时,往往分为若干个程序模块,每一个模块包括一个或多个函数。一个C语言程序可以由一个主函数和若干个其他函数构成。由主函数调用其他函数,其他函数再调用别的函数。程序中函数调用的示意图如图7-1所示。

图7-1 程序中函数调用示意图

C语言的函数有以下特点:

① C语言程序由函数组成,包括一个主函数main()和若干其他函数。

C程序的执行是由main()函数开始的,如果在main()函数中调用其他函数,在调用后,返回至main()函数,在main()函数中结束整个程序的运行。

② 函数之间是调用的关系,调用某函数的函数称为主调函数,被调用的函数称为被调函数,如图7-2所示。

图7-2 函数调用示意图

主函数可以调用其他函数,其他函数可以相互调用,但主函数不能被其他函数调用。

③ 一个C51程序由一个或多个文件构成。

④ 每个函数都是平行的,任何函数都不从属于其他函数。

⑤ 从用户角度,函数可以分为:

☆标准函数,即库函数,是由系统提供的,用户不必自己定义,可以直接使用的函数。

☆用户自定义的函数,是用于解决用户特定需要的函数。

⑥ 根据函数形式,函数可以分为:

☆无参函数。

☆有参函数。

⑦ 根据函数有无返回值,函数可以分为:

☆有返回值函数。

☆无返回值函数。

2.函数定义

在C语言中,在程序中用到的函数必须“先定义,后使用”。

定义函数时,应该包括以下四项内容:

① 指定函数的名字,以便以后按名字调用。

② 指定函数的类型,即函数返回值的类型。

③ 指定函数的参数的类型和名字,在调用函数时,向它们传递数据。无参函数调用时,不需要这项。

④ 指定函数的功能。这是函数体要实现的。

3.定义函数的一般形式

函数的定义由两部分组成:

① 头部(第一行)。头部给出了函数名,还规定了函数的返回值类型,以及各个参数的类型和参数名。

② 函数体。即头部下面用{ }包起来的语句,用于实现函数的功能。函数体包括声明部分和语句部分。

函数根据有无参数,可分为无参数函数和有参数函数。

4.无参数函数定义的一般形式

5.有参数函数定义的一般形式

6.空函数

空函数什么工作也不做,没有任何实际作用。其用途是先分配好函数名,等以后扩充函数功能时补上函数体、参数、类型。

小贴士

之前学习过的项目任务中的C语言语句都可以写在函数体中,实现各个项目任务功能的模块化。

C语言中各个函数是相互独立的。函数的定义不能嵌套,在一个函数体内部不允许再定义另外一个函数。

例如,下面的函数定义是错误的:

正确的写法是:

关于函数定义的说明:

① 函数类型。

定义函数时,函数类型应写在函数名之前,其规定了函数返回值的数据类型。函数类型可以是int、long、short、float、char等。如果不写函数类型,默认是int型。

如果要规定函数没有返回值,函数类型应使用关键字void,而不能省略。

例如,下面定义的ledOff()函数的功能是熄灭所有LED灯,该函数不需要返回值,可以定义为:

② 函数名。

函数名必须符合C语言的标识符命名规则。最好给函数取一个“见名知意”的名字。一个好的函数名能够反映该函数的功能。

例如:

ledOff,熄灭所有LED灯;

ledOn,点亮所有LED灯。

③函数名后的()必不可少,即使函数没有参数。如果少了(),那么就不是函数定义了。

7.函数的参数

一个程序由若干个函数组成,各函数调用时,经常要传递一些数据,即调用函数把数据传递给被调用函数,经过被调用函数处理后,得到一个确定的结果,在返回调用函数时,将结果带回调用函数,如图7-3所示。

图7-3 函数参数传递

各函数之间的数据往来通过参数传递和返回语句实现。

8.形式参数和实际参数

函数参数:用于函数之间数据的传递。

形式参数:定义函数时给出的参数。

实际参数:调用函数时给出的参数。

说明:

① 定义函数时,必须说明形参的类型。形参只能是变量,不能是常量或表达式。

② 子函数被调用之前,形参和子函数中的变量不占内存;调用结束并返回后,形参所占的内存被收回。

③ 实参可以是常量、变量或表达式,因为传递过来的是具体数值。

④ 实参和形参类型必须一致(或可以安全转换)。

⑤ C语言中,实参和形参传递是“按值传递”,即单向传递,只与参数相对位置有关,而与变量名无关。

9.函数值

函数值也就是函数的返回值,是一个具体的值。

说明:

① 函数使用return语句返回值。

② 一个函数内可以有多个return语句,执行到任何return语句时,函数都将立即返回到调用函数。

③ return后面的()可以省略,可以返回一个表达式,先求解表达式的值,再返回。

(1)函数值的类型

说明:

① 函数值的类型即函数的类型。

例如,函数max是int型,函数的返回值也是int型。

② 省略了类型说明的函数,默认是int型。

③ return中表达式的值一般和函数类型相同,如果不一致,则需要进行类型转换。

(2)无返回值

说明:

① 如果函数中没有return语句,可以使用void类型。

② 如果一个函数被声明为void类型,没有返回值,那么就不允许再引用它的返回值,只能单纯地调用它。

10.函数调用

(1)函数语句

形式为:

例如:

说明:

这种方式不要求函数带返回值,函数只执行一定操作。

(2)函数表达式

函数的返回值参与运算。

例如:

说明:

void类型函数不能使用这种调用方式。

(3)函数调用的执行过程

① 计算实参表达式的值。

② 按照位置,将实参的值一一传递给形参。

③ 执行被调用函数。

④ 当遇到return(表达式)语句时,计算表达式的值并返回调用函数。

11.函数原型

在程序中调用函数需满足以下条件:

① 被调用函数必须存在,并且遵循“先定义,后使用”的原则。

② 如果被调用函数在主调函数之后定义,则在调用之前需要给出原型说明。

原型说明: