在前面的学习中,我们明确了“位操作”和“字节操作”各自的特点。一般地,如果需要对成组数据进行处理,使用字节操作会简洁很多。现在我们来解决模式4问题,该模式要求依次点亮其中一个发光二极管并循环。我们可以使用位操作,但需要在点亮下一个指示灯时熄灭上一个指示灯,否则就无法实现每次只点亮一个灯的要求了。如果是字节操作,则通过给P0口合适的数值,确保每次只有一个位输出低电平,其他位均为高电平,见表2-5,P0口写入不同的数值,实现每次点亮其中一个指示灯。
表2-5 依次点亮一个灯
在学习并掌握模式2、模式3的基础上,相信读者可以很容易得到如图2-13所示的模式4的控制程序,请读者下载并验证程序。
图2-13 模式4控制程序
仔细观察图2-13所示的控制程序,我们发现每次改变P0口的状态语句下面都出现了完全一致的两条语句:
有没有办法不要每次都写这两条语句呢?答案是肯定的。C语言程序是由一个个函数组成的,好比一个班级由一个个不同的个体组成,我们可以假设每个个体就是一个函数,它具有特定的功能,如班长、学习委员、普通同学等。一个班级需要有一个班主任来管理,同样一个C语言程序也必须有一个而且只能有一个“主函数main”来实现对其他函数(我们称之为“子函数”)的调配与管理,从而实现一个期望的控制目标。必须强调的是:主函数main有且只有一个,必不可少。
因此,我们完全可以将上述两条实现延时的语句组织起来,用一个子函数来封装起来,主函数main只需简单“调用”这个函数即可,如图2-14所示。
图2-14 模式4控制程序(while语句)
动一动
请读者调试图2-14的源代码,并验证。在操作过程中,请务必注意大小写问题。我们已反复强调:C语言是严格区分大小写的。
要调用一次函数必须先定义或声明,图2-14中的主函数main调用了Yanshi子函数,而Yanshi子函数在main之前已定义了。请读者把子函数的定义写在主函数main的下面,再次编译程序,就会发现编译错误,这是因为犯了“先斩后奏”的错误——先调用了Yanshi子函数,后再定义这个Yanshi子函数。如果一定要把Yanshi子函数定义在主函数main的下面,则只能在主函数main前面“声明”这个在下面定义的Yanshi子函数。再次强调并请读者记住:无论是变量还是函数,要使用必先定义或声明!
那如何定义或声明一个函数呢?
2.2.4.1 函数的定义
函数定义的一般格式为
其中,“类型标识符”表示该函数执行后返回值的数据类型,如果该函数无返回值,可以写成void。类型标识符可以理解成这个函数的“产出”——执行后输出一个对应数据类型的结果。比如我们定义一个计算两个数相加的函数,这个函数执行后,返回相加的结果,并假定结果为“无符号字符型”,这时我们可以把“类型标识符”写作“unsigned char”;同理,若是这个函数执行后,没有“产出”,则此时“类型标识符”写成“void”。类型标识符是用户根据函数功能需要确定的,如果一个函数有“产出”,则一般在“函数体”中会有关键词“return”来执行“产出”操作。
函数名就是函数的名称,用户自己定义,如前文中出现的“Yanshi”。原则上,在符合C语言标识符规则的前提下,函数名可以自由命名,但一般应做到“顾名思义”,方便自己也方便其他读者读懂你的代码,准确把握这个函数的功能。如前文出现的“Yanshi”这个函数名,就做到中文意义上的顾名思义,表示要延时一段时间。这里需要特别强调的是:我们强烈建议读者,尽量不要使用中文拼音,而尽量使用英文单词及其组合。虽然刚开始比较困难,但日积月累,一段时间后,你就会感觉英文单词是那么自然。请读者把“Yanshi”这个函数名,替换成“Delay(英文单词,表示“延迟”的意思)”,并重新编译程序,验证是否可行。
函数名后面括号内表示输入参数,它可以是没有输入参数,此时写成“void”,也可以有一个或多个输入参数,输入参数也是用户根据需要确定的。还是以计算两个数相加为例,我们可以把两个加数作为输入参数。
被大括号括起来的内容,称为“函数体”,它一般包括“局部变量定义”和“函数体语句”两大部分。局部变量服务于本函数,只在函数内有效,函数体语句是为完成函数的特定功能而设置的语句。(www.xing528.com)
综上所述,我们给出两个数相加的子函数,请读者回答如下问题。
1)这个函数的类型标识符是____
2)这个函数的局部变量是____
3)这个函数的函数名____
4)这个函数的输入参数有____
5)return的意思是____
2.2.4.2 函数的声明
前文已反复强调:变量或函数要使用必先定义或声明。图2-14中的控制程序,在主函数main中调用了“Yanshi”子函数,满足先定义后调用的条件。但如果把“Yanshi”子函数定义在主函数main的后面,则会出现“先调用后定义”的错误,这时我们可以进行“声明”操作——在主函数main前面声明“Yanshi”子函数,如下:
void Yanshi(void);//声明Yanshi子函数
可见,声明一个函数就是去掉函数定义中的“函数体”部分,同时增加一个“分号”。
动一动
请读者把“Yanshi”子函数放在主函数main的后面,并在main之前添加“Yanshi”子函数的声明操作,然后验证程序。
2.2.4.3 函数的调用
我们可以使用“函数名”来实现对函数的调用。根据有无返回值、有无输入参数,函数的调用有如下几种样式。
➢无返回值,无输入参数,样式:函数名()。
➢无返回值,有输入参数,样式:函数名(参数列表)。
➢有返回值,无输入参数,样式:存放结果的变量=函数名()。
➢有返回值,有输入参数,样式:存放结果的变量=函数名(参数列表)。
函数调用的样式,必须与函数定义或声明相吻合。
动一动
请编写一个带有输入参数(数据类型为unsigned int)的延时子函数,要求实现指示灯与指示灯点亮的时间间隔逐渐加长,并下载验证。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。