单片机应用技术(C语言版)第4版3.4 C语言的函数课件_第1页
单片机应用技术(C语言版)第4版3.4 C语言的函数课件_第2页
单片机应用技术(C语言版)第4版3.4 C语言的函数课件_第3页
单片机应用技术(C语言版)第4版3.4 C语言的函数课件_第4页
单片机应用技术(C语言版)第4版3.4 C语言的函数课件_第5页
已阅读5页,还剩14页未读, 继续免费阅读

下载本文档

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

文档简介

3.4C语言的函数《单片机应用技术(C语言版)》刚刚我们已经进入了C语言函数这一章节的学习,了解了这一节的整体框架。接下来我们就从基础入手,先厘清函数到底有哪些分类,又该如何完成一个合法函数的定义,这是我们后续使用自定义函数、调用库函数的核心基础。搞懂这部分内容,我们才能看懂实际代码里的函数写法,接下来我们就先展开讲解。C51编译器为51单片机开发提供了一套完整的预置工具集合,也就是我们所说的库函数。这套库函数按照功能划分为八个核心分类,不同分类对应不同的头文件,开发人员可以根据项目需求灵活引入调用。第一个分类是寄存器库函数,对应头文件REGXXX.H,这也是几乎所有51单片机C语言项目都会引入的基础头文件。它的核心作用,是提前定义好51单片机所有特殊功能寄存器SFR,以及寄存器对应每一个位的别名,开发人员不需要手动逐一定义寄存器地址,直接调用P1、TCON这些预定义的寄存器变量即可完成硬件操作,大幅降低了开发的入门门槛,也减少了手动定义带来的地址错误风险。其余七个分类分别承担不同开发功能,对应不同的开发场景。一般输入输出函数对应STDIO.H,承担串口数据的输入输出处理;内部函数对应INTRINS.H,提供空操作、移位等基础操作能力;字符函数对应CTYPE.H、字符串函数对应STRING.H,处理文本类数据操作;数学函数对应MATH.H提供常用数学计算能力;标准函数对应STDLIB.H,提供内存分配、数据转换等通用能力;绝对地址访问函数对应ABSACC.H,支持直接对指定内存地址进行读写操作,满足直接操作硬件的特殊需求。C51为单片机开发提供了一套成熟的标准库函数,这套工具按功能领域划分成多个不同的头文件,方便开发者按需调用,大幅降低了底层开发的重复工作量。第一类是寄存器库函数,对应头文件REGXXX.H,它完成的核心工作是预定义51单片机所有特殊功能寄存器和对应位,开发者无需手动配置寄存器地址,直接调用变量即可操作硬件,省去了最基础也最容易出错的底层定义环节。第二类就是我们当前讲的一般输入/输出函数,对应头文件STDIO.H,它专门负责操作51单片机的串口,实现单片机和外部设备的数据收发交互。无论是向上位机发送调试信息,还是接收上位机下发的控制指令,都要依托这组库函数完成,是嵌入式开发中调试环节和对外通信的核心工具。除此以外,C51标准库还覆盖了开发全流程的各类需求:内部函数提供空操作、移位等基础运算能力,字符、字符串函数处理文本数据,数学函数支持复杂运算,标准函数提供内存管理、类型转换工具,绝对地址访问函数则帮开发者直接操作指定内存地址,满足自定义硬件的访问需求。完整的库体系让开发者可以聚焦业务逻辑开发,不用重复造轮子。C51为单片机开发提供了丰富的预定义库工具,不同头文件封装了不同场景的功能,我们继续逐个梳理它们的作用。梳理到内部函数所在的INTRINS.H头文件时,就能发现它的实用性。这一头文件封装的功能,直接对应51单片机开发最基础的位操作需求,包含空操作指令,以及变量的循环左移、循环右移操作。这些功能看似简单,实际却是很多单片机经典项目的核心基础,比如我们常见的流水灯项目,就需要依靠循环移位操作实现点亮位置的逐次移动,如果没有这个预定义的内部函数,开发者需要手动编写移位逻辑,不仅增加编码工作量,还容易出现位运算错误,拖慢开发进度。C51把这些开发过程中高频复用的基础操作封装成库函数,既降低了初学者的入门门槛,也能帮助经验丰富的开发者简化代码,提升开发效率,这正是C51库函数体系设计的核心价值之一。调用库函数必须遵循语法规则,核心前提在于先声明后使用。对于系统提供的预定义库函数,声明逻辑依托预处理指令实现。开发者需要在源程序起始位置,通过`#include`指令将对应库的头文件加载到当前项目中。头文件中存储了库函数的定义、参数规则与返回值信息,只有完成头文件包含,编译器才能识别开发者对库函数的调用,避免出现未定义标识的编译错误。示例代码完整展示了库函数调用的实际流程。代码开头两行分别导入了51单片机寄存器操作对应的`reg51.h`头文件,以及实现位操作的`intrins.h`内部库头文件,这满足了两个库中函数调用的前置声明要求。后续主函数中,开发者既直接调用了寄存器库定义的P1端口变量,又调用了内部库提供的`_cror_`循环右移函数,配合自定义的延时函数实现了P1端口电平循环移位的效果。这个案例直观印证了库函数调用的核心逻辑,证明遵循头文件包含规则,就能便捷复用系统封装好的功能,简化程序开发流程。除了编译系统预先提供的库函数,C51语言允许开发者根据实际功能需求编写自定义函数,灵活实现多样化的业务逻辑。自定义函数拥有统一的语法结构,这套结构保证了代码的可维护性与可读性,适配单片机开发的工程化要求。完整的自定义函数由函数头与函数体两个核心部分构成,函数头包含三个关键要素:函数类型、函数名与形式参数列表。函数类型本质是函数返回值的数据类型,它明确告知调用者,当前函数执行完成后,会返回什么类型的数据供后续逻辑使用,结构中最后出现的return语句,负责携带这个返回值传回函数调用处,完成数据交互。进入大括号包裹的函数体区域,开发者需要依次完成两个核心步骤:先声明函数内部使用的局部变量,再编写实现具体功能的执行语句,最后搭配return语句完成返回逻辑。这套标准结构是C51函数开发的基础框架,掌握这套结构,才能搭建出符合语法规范、运行稳定的自定义功能模块。int标记当前函数的返回值类型,代表函数最终会向调用处返回一个整型数据,这对应我们需求中的“整数最大值”本身,整数就是C语言中的整型数据类型。max是当前自定义函数的函数名,遵循C语言标识符命名规则,做到见名知意,直接传递出函数“求最大值”的功能,降低代码的阅读维护成本。括号内的三个int型形参a、b、c,承接调用函数时传入的三个待比较整数,建立起函数内部运算和外部输入的连接通道。大括号包裹的内容为函数体,首先声明一个存储中间结果的局部整型变量z,完成第一次比较:若a大于b,则把a的值赋值给z,反之则把b赋值给z,此时z存储前两个数的最大值。接着将z与第三个数c比较,若c更大则更新z的值,至此z存储三个数中的最大值。最后通过return语句将z的值,也就是三个整数的最大值返回给函数调用处,完成整个求最大值的计算逻辑,清晰展示了有参有返回值自定义函数的完整结构。我们学习C51自定义函数的一种基础定义格式,就是无返回值带参数的函数。这种函数的核心特征,体现在函数声明开头的`void`关键字上,它明确标记该函数的类型为空类型,代表函数执行完成后不需要向主调程序返回任何结果。这种函数的应用场景非常广泛。当我们只需要函数完成某一项具体操作,比如控制单片机端口电平、实现延时等待、刷新显示内容这类操作时,不需要函数返回运算结果,就可以用这种格式定义函数。本页给出的格式中,括号内保留了形式参数列表,意味着函数可以接收主调程序传入的参数,实现更灵活的功能。例如我们编写延时函数时,可以将延时时长作为参数传入,这样一个函数就能适配不同场景的延时需求,不需要重复编写多份功能相近的代码。即使函数不需要返回值,格式中仍然保留return语句。该语句在这里的作用,大多是提前终止函数执行的流程,而非返回具体数值。如果不需要提前退出,也可以省略return语句,函数会在执行完最后一句函数体语句后自动退出。这种定义格式平衡了功能灵活性和代码简洁性,是51单片机C语言开发中最常用的函数格式之一。这是C51语言中无形式参数函数的标准定义格式。函数定义的核心组成部分依次为函数类型、函数名与参数列表,当参数列表位置标记为void时,代表该函数不存在任何形式参数。理解这个格式的核心,要明确形式参数的作用。形式参数是函数接收外部传入数据的接口,用于将函数外部的数据传递到函数内部参与运算处理。当函数不需要从外部获取任何数据即可完成既定功能时,就可以将参数列表声明为void,明确告知编译器该函数不接收任何输入数据。这种定义方式在嵌入式开发中十分常用。比如单片机程序中固定逻辑的初始化函数,不需要外部传入参数就能完成端口配置、中断设置等固定操作,就可以采用这种无参数的定义格式,既符合语法规范,也能提升代码的可读性,让其他开发者一眼就能判断出函数不需要输入数据,降低代码维护的沟通成本。我们学习完带返回值带参数、无返回值带参数、带返回值无参数的自定义函数结构后,来看最后一种最特殊的自定义函数定义格式。这种格式将函数类型声明为void,也就是空类型,代表整个函数执行完成后不需要向调用位置返回任何结果,因此可以省略return语句。括号内同样声明为void,代表函数不需要从调用位置接收任何输入数据,没有形式参数。这种函数结构非常实用,很多单片机开发的场景都会用到它。我们最常用的主函数main,多数情况下就采用这种结构编写,因为主函数是整个程序的入口,程序从这里开始执行,不需要给其他位置返回运行结果,也不需要调用者传入参数,完全匹配这种结构的特性。此外我们编写驱动硬件执行固定动作的功能函数时,比如控制蜂鸣器发声、控制LED亮起,这类操作只需要执行对应指令,不需要返回值,也不需要额外输入参数,同样可以使用这种结构定义。3.4.1函数的分类和定义C51的库函数寄存器库函数REGXXX.H一般输入/输出函数STDIO.H内部函数INTRINS.H字符函数CTYPE.H字符串函数STRING.H数学函数MATH.H标准函数STDLIB.H绝对地址访问函数ABSACC.H定义了51单片机的所有SFR和相应的位C51的库函数寄存器库函数REGXXX.H一般输入/输出函数STDIO.H内部函数INTRINS.H字符函数CTYPE.H字符串函数STRING.H数学函数MATH.H标准函数STDLIB.H绝对地址访问函数ABSACC.H操作51单片机的串口C51的库函数寄存器库函数REGXXX.H一般输入/输出函数STDIO.H内部函数INTRINS.H字符函数CTYPE.H字符串函数STRING.H数学函数MATH.H标准函数STDLIB.H绝对地址访问函数ABSACC.H51单片机的空操作、变量的左移/右移库函数的调用

#include<reg51.h>//包含寄存器库函数头文件,调用51单片机SFR

#include<intrins.h>//包含内部函数库头文件,调用左移、右移函数voiddelay(unsignedinti)

//定义延时函数

{unsignedintk;

for(k=0;k<i;k++);}

voidmain()//主函数

{

P1=0x7F;

//调用P1端口寄存器变量

while(1)//无限循环

{

P1=_cror_(P1,1);//调用左移函数,将P1的二进制数值循环左移一位

delay(5000);//延时

}}使用函数时必须先声明再使用使用库函数时,必须在源程序的开始处使用预处理命令#include将相应的头文件包含进来函数类型函数名(形式参数列表){局部变量声明;

函数体语句;return语句;}函数返回值的类型返回函数的返回值用户自定义函数//求三个整数的最大值intmax(inta,intb,intc){

intz;

if(a>b)z=a;

elsez=b;

if(c>z)z=c;

returnz;}

函数类型函数名形式参数列表

return(z);函数体

void函数名(形式参数列表){局部变量声明;

函数体语句;return语句;}函数类型是空类型,没有返回值。函数类型函数名(void){局部变量声明;

函数体语句;return语句;}没有形式参数。

void函数名(void){局部变量声明;

函数体语句;}函数类型是空类型,没有返回值。没有形式参数。信号灯闪烁控制C语言程序3.4.2函数调用C51的函数调用原则:先定义(或声明),后调用

#include<reg51.h>//包含寄存器库函数头文件,调用51单片机SFR

#include<intrins.h>//包含内部函数库头文件,调用左移、右移函数voiddelay(unsignedinti)//定义延时函数

{unsignedintk;

for(k=0;k<i;k++);}

voidmain()//主函数

{

P1=0x7F;//调用P1端口寄存器变量

while(1)//无限循环

{

P1=_cror_(P1,1);//调用左移函数,将P1的二进制数值循环左移一位

delay(5000);//延时

}}要使用库函数,必须先在程序开始处使用#include预处理命令,进行库函数使用声明C51的函数调用原则:先定义(或声明),后调用

#include<reg51.h>//包含寄存器库函数头文件,调用51单片机SFR

#include<intrins.h>//包含内部函数库头文件,调用左移、右移函数voiddelay(unsignedinti)//定义延时函数

{unsignedintk;

for(k=0;k<i;k++);}

voidmain()//主函数

{

P1=0x7F;//调用P1端口寄存器变量

while(1)//无限循环

{

P1=_cror_(P1,1);//调用左移函数,将P1的二进制数值循环左移一位

delay(5000);//延时

}}要使用自定义函数,必须在调用前先进行函数定义。然后调用,实参5000传递给函数的形参i。C51的函数调用原则:先定义(或声明),后调用#include<reg51.h>//包含寄存器库函数头文件,调用51单片机SFR#include<intrins.h>//包含内部函数库头文件,调用左移、右移函数voiddelay(unsignedinti);//声明要使用延时函数voidmain()//主函数

{

P1=0x7F;//调用P1端口寄存器变量

while(1)//无限循环

{

P1=_cror_(P1,1);//调用左移函数,将P1的二进制数值循环左移一位

delay(5000);//延时

}}voiddelay(unsignedinti)//定义延时函数

{unsignedintk;

for(k=0;k<i;k++);}使用自定义函数还可以在调用前先进行函数使用声明。然后调用在主函数后面再进行函数定义C51的函数调用原则:先定义(或声明),后调用while(1) //等待按键按下{

P2=0x0f;

//向所有的列线上输出低电平

P0=0xff;i=P0; //读入行值

i&=0x0f;

//屏蔽掉高四位

if(i!=0x0f) //行值不为全1,有键按下

{delay10ms();//延时消抖

i=P0;

//再次读入行值

i&=0x0f;

//屏蔽掉高四位

if(i!=0x0f)

//行值不为全1,说明有键按下

{key=scan_key();//执行逐列扫描子程序判断键值}}}unsignedcharscan_key(void){

unsigned

chari,temp,m,n;

bitfind=0; //有键按下标志位

P0=0xff;//P0口低四位做输入口,先输出全1

for(i=0;i<4;i++){

P2=0xfe<<i;//逐列送出低电平

temp=~P0; //读行值,并取反,全1-->全0temp=temp&0x0f;//屏蔽掉行值高4位

if(temp!=0x00)//判断有无键按下

{m=i;//列号i保存至m变量

find=1; //置找到按键标志

switch(temp) //判断哪一行有键按下,记录行号到n变量

{case0x01:n=0;break;//第0行有键按下

case

0x02:n=1;break;//第1行有键按下

case

0x04:n=2;break;//第2行有键按下

case

0x08:n=3;break;//第3行有键按下

default:break;}}}

if(find==0)return-1;//无键按下则返回-1

else

return(n*4+m);//否则返回键值,键值=行号*4+列号}有返回值函数函数调用后,将其返回值赋值给变量感谢您的观看Thanks

for

your

attention.

刚刚我们已经进入了C语言函数这一章节的学习,了解了这一节的整体框架。接下来我们就从基础入手,先厘清函数到底有哪些分类,又该如何完成一个合法函数的定义,这是我们后续使用自定义函数、调用库函数的核心基础。搞懂这部分内容,我们才能看懂实际代码里的函数写法,接下来我们就先展开讲解。C51编译器为51单片机开发提供了一套完整的预置工具集合,也就是我们所说的库函数。这套库函数按照功能划分为八个核心分类,不同分类对应不同的头文件,开发人员可以根据项目需求灵活引入调用。第一个分类是寄存器库函数,对应头文件REGXXX.H,这也是几乎所有51单片机C语言项目都会引入的基础头文件。它的核心作用,是提前定义好51单片机所有特殊功能寄存器SFR,以及寄存器对应每一个位的别名,开发人员不需要手动逐一定义寄存器地址,直接调用P1、TCON这些预定义的寄存器变量即可完成硬件操作,大幅降低了开发的入门门槛,也减少了手动定义带来的地址错误风险。其余七个分类分别承担不同开发功能,对应不同的开发场景。一般输入输出函数对应STDIO.H,承担串口数据的输入输出处理;内部函数对应INTRINS.H,提供空操作、移位等基础操作能力;字符函数对应CTYPE.H、字符串函数对应STRING.H,处理文本类数据操作;数学函数对应MATH.H提供常用数学计算能力;标准函数对应STDLIB.H,提供内存分配、数据转换等通用能力;绝对地址访问函数对应ABSACC.H,支持直接对指定内存地址进行读写操作,满足直接操作硬件的特殊需求。C51为单片机开发提供了一套成熟的标准库函数,这套工具按功能领域划分成多个不同的头文件,方便开发者按需调用,大幅降低了底层开发的重复工作量。第一类是寄存器库函数,对应头文件REGXXX.H,它完成的核心工作是预定义51单片机所有特殊功能寄存器和对应位,开发者无需手动配置寄存器地址,直接调用变量即可操作硬件,省去了最基础也最容易出错的底层定义环节。第二类就是我们当前讲的一般输入/输出函数,对应头文件STDIO.H,它专门负责操作51单片机的串口,实现单片机和外部设备的数据收发交互。无论是向上位机发送调试信息,还是接收上位机下发的控制指令,都要依托这组库函数完成,是嵌入式开发中调试环节和对外通信的核心工具。除此以外,C51标准库还覆盖了开发全流程的各类需求:内部函数提供空操作、移位等基础运算能力,字符、字符串函数处理文本数据,数学函数支持复杂运算,标准函数提供内存管理、类型转换工具,绝对地址访问函数则帮开发者直接操作指定内存地址,满足自定义硬件的访问需求。完整的库体系让开发者可以聚焦业务逻辑开发,不用重复造轮子。C51为单片机开发提供了丰富的预定义库工具,不同头文件封装了不同场景的功能,我们继续逐个梳理它们的作用。梳理到内部函数所在的INTRINS.H头文件时,就能发现它的实用性。这一头文件封装的功能,直接对应51单片机开发最基础的位操作需求,包含空操作指令,以及变量的循环左移、循环右移操作。这些功能看似简单,实际却是很多单片机经典项目的核心基础,比如我们常见的流水灯项目,就需要依靠循环移位操作实现点亮位置的逐次移动,如果没有这个预定义的内部函数,开发者需要手动编写移位逻辑,不仅增加编码工作量,还容易出现位运算错误,拖慢开发进度。C51把这些开发过程中高频复用的基础操作封装成库函数,既降低了初学者的入门门槛,也能帮助经验丰富的开发者简化代码,提升开发效率,这正是C51库函数体系设计的核心价值之一。调用库函数必须遵循语法规则,核心前提在于先声明后使用。对于系统提供的预定义库函数,声明逻辑依托预处理指令实现。开发者需要在源程序起始位置,通过`#include`指令将对应库的头文件加载到当前项目中。头文件中存储了库函数的定义、参数规则与返回值信息,只有完成头文件包含,编译器才能识别开发者对库函数的调用,避免出现未定义标识的编译错误。示例代码完整展示了库函数调用的实际流程。代码开头两行分别导入了51单片机寄存器操作对应的`reg51.h`头文件,以及实现位操作的`intrins.h`内部库头文件,这满足了两个库中函数调用的前置声明要求。后续主函数中,开发者既直接调用了寄存器库定义的P1端口变量,又调用了内部库提供的`_cror_`循环右移函数,配合自定义的延时函数实现了P1端口电平循环移位的效果。这个案例直观印证了库函数调用的核心逻辑,证明遵循头文件包含规则,就能便捷复用系统封装好的功能,简化程序开发流程。除了编译系统预先提供的库函数,C51语言允许开发者根据实际功能需求编写自定义函数,灵活实现多样化的业务逻辑。自定义函数拥有统一的语法结构,这套结构保证了代码的可维护性与可读性,适配单片机开发的工程化要求。完整的自定义函数由函数头与函数体两个核心部分构成,函数头包含三个关键要素:函数类型、函数名与形式参数列表。函数类型本质是函数返回值的数据类型,它明确告知调用者,当前函数执行完成后,会返回什么类型的数据供后续逻辑使用,结构中最后出现的return语句,负责携带这个返回值传回函数调用处,完成数据交互。进入大括号包裹的函数体区域,开发者需要依次完成两个核心步骤:先声明函数内部使用的局部变量,再编写实现具体功能的执行语句,最后搭配return语句完成返回逻辑。这套标准结构是C51函数开发的基础框架,掌握这套结构,才能搭建出符合语法规范、运行稳定的自定义功能模块。int标记当前函数的返回值类型,代表函数最终会向调用处返回一个整型数据,这对应我们需求中的“整数最大值”本身,整数就是C语言中的整型数据类型。max是当前自定义函数的函数名,遵循C语言标识符命名规则,做到见名知意,直接传递出函数“求最大值”的功能,降低代码的阅读维护成本。括号内的三个int型形参a、b、c,承接调用函数时传入的三个待比较整数,建立起函数内部运算和外部输入的连接通道。大括号包裹的内容为函数体,首先声明一个存储中间结果的局部整型变量z,完成第一次比较:若a大于b,则把

温馨提示

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

评论

0/150

提交评论