函数是执行某些相关功能的自包含执行代码段。 通常C语言编译器都会自带一个标准函数库,里面是一些常用的函数。 标准函数已经由编译软件厂商编写和定义,用户可以直接调用,无需定义。 但标准函数不足以满足用户的特殊要求,因此C语言允许用户根据需要编写具有特定功能的函数。 要调用它,必须首先定义它。
定义的schema如下:
函数类型函数名(形参列表)
函数类型是描述所定义函数的返回值的类型。 返回值实际上是一个变量。 只需根据变量类型定义函数类型即可。 如果函数不需要返回值,则函数类型可以写成“void”,表示该函数没有返回值。 注意函数体的返回值类型必须与函数类型一致,否则会出错。
而函数名的定义遵循C语言变量命名规则,但同一个程序中不能定义同名的函数,这会导致编译错误(同一个程序中允许存在同名的变量,因为变量被分为全局变量和局部变量)。
形式参数是指调用函数时传入函数体参与运算的变量。 可以是一个、多个或没有。 当函数不需要形参时(即无参数函数),括号应为空或写为“void”,但括号不能缺失。
函数体可以包含局部变量和程序语句的定义。 如果函数想要返回一个运算值,就必须使用return语句来返回。 如果函数的{}符号中不能写入任何内容,那么它就成为空函数。 您可以在程序项目中编写一些空函数,并且在以后的修改和升级中可以轻松地扩展这些空函数中的功能。
函数调用
(1)函数调用的一般说明
一个函数定义后,必须被其他函数调用后才能执行。 C语言中的函数可以相互调用,但是在调用函数之前必须指定函数的类型,即使是标准库函数也不例外。
标准库函数的描述会根据功能写在不同的头文件中。 使用时只需在文件开头使用#include预处理语句引入相应的头文件即可。 例如,前面使用的printf函数的描述被放置在名为stdio.h的头文件中。
调用是指一个函数体引用另一个已定义的函数来实现所需的功能。 此时函数体称为主调用函数,函数体中引用的函数称为被调用函数。 main函数只与被调用函数相关。
一个函数体可以调用多个其他函数。 这些被调用的函数还可以调用其他函数,而且它们还可以嵌套。 但在C51语言中,有一个函数是不能被其他函数调用的,这就是main函数。
标准库函数只要使用#include引入头文件并写上说明,就可以在程序中直接调用该函数。 如果调用自定义函数,函数类型描述必须写成如下形式:
类型标识符函数的名称(形参列表);
当被调用函数定义和调用函数在同一个文件中时,使用这种描述方法。 您还可以将它们写入带有 filename.h 的文件中,并使用 #include "filename.h" 引入它们。
如果被调用函数的定义和调用函数不在同一个文件中,则应按如下方式解释,表明被调用函数的定义在同一个项目的不同文件中。 这样解释的函数也可以称为外部函数,定义如下:
extern类型标识符函数的名称(形参列表);
函数的定义和描述是完全不同的。 从编译的角度来看,函数的定义就是将函数编译并存放在ROM中的某个地址,而函数描述则告诉编译器在程序中使用哪些函数并确定该函数。 的地址。 如果同一文件中被调用函数定义在调用函数之前,则此时无需指定函数类型。 也就是说,在主函数之前定义的函数不需要在程序中编写函数类型描述。 您可以在函数体中调用另一个函数(嵌套调用),但不允许在函数定义中定义另一个函数。 还要注意函数定义和描述中的“类型、参数列表、名称”必须一致。
(2)函数调用的一般形式
调用函数的一般形式如下:
函数名称(实参列表)
“函数名称”是指被调用的函数。
实际参数表可以有零个或多个参数。 多个参数应以逗号分隔。 每个参数的类型和位置应与函数定义时的形参一一对应。 它的作用是传递参数给被调用函数中的形参,如果类型与类型不对应,就会出现一些错误。 当被调用函数为无参数函数时,不写参数,但后面的括号不能省略。
我们来看看实际应用中函数调用的不同方式:
1. 函数声明
例如 printf("Hello World!n");
它以“Hello World!n”为参数调用printf库函数,其中函数调用被视为一条语句。
2. 功能参数
“函数参数”方式是指将被调用函数的返回值作为另一个被调用函数的实参,如temp=StrToInt(CharB(16)); CharB 的返回值作为 StrToInt 函数的实际参数传递。
3. 函数表达式
例如 temp=Count();
对该函数的调用在表达式中显示为操作数,称为函数表达式。 示例中,Count()返回一个int类型的返回值,直接赋值给temp。 注意,这种调用方法要求被调用函数能够返回相同类型的值,否则会出现不可预知的错误。
C51通用头文件
以下是一些常用的C51头文件:
absacc.h – 包含允许直接访问 8051 不同存储区域的宏定义;
assert.h——该文件定义了assert宏,可以用来建立程序的测试条件;
ctype——字符转换和分类程序;
intrins.h – 包含程序原型的文件,指示编译器生成嵌入的内部代码;
math.h——数学程序;
reg51.h——51的特殊寄存器;
reg52.h——52的特殊寄存器;
setjmp.h – 定义 jmp_buf 类型以及 setjmp 和 longjmp 程序的原型;
stdarg.h – 可变长度参数列表程序;
stdlib.h——存储区分配器;
stdio.h——标准输入输出程序;
string.h——字符串操作程序,缓冲区操作程序。
对于常用的MCS-51单片机,必须包含头文件reg51.h,因为该文件定义了51单片机的相关寄存器和位,以便在程序中使用这些资源。
reg51.h文件的具体内容如下:
#ifndef __REG51_H__
#定义__REG51_H__
/* BYTE寄存器*/ //单元定义
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA 0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfrACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfrTMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
/* 位寄存器 */
/* PSW */ //位定义
位 CY = 0xD7;
sbit AC = 0xD6;
位 F0 = 0xD5;
sbit RS1 = 0xD4;
sbit RS0 = 0xD3;
sbit OV = 0xD2;
位 P = 0xD0;
/* TCON */
位 TF1 = 0x8F;
位 TR1 = 0x8E;
sbit TF0 = 0x8D;
位 TR0 = 0x8C;
sbit IE1 = 0x8B;
sbit IT1 = 0x8A;
sbit IE0 = 0x89;
sbit IT0 = 0x88;
/* IE */
sbit EA = 0xAF;
sbit ES = 0xAC;
sbit ET1 = 0xAB;
sbit EX1 = 0xAA;
sbit ET0 = 0xA9;
sbit EX0 = 0xA8;
/* IP */
sbit PS = 0xBC;
sbit PT1 = 0xBB;
sbit PX1 = 0xBA;
sbit PT0 = 0xB9;
sbit PX0 = 0xB8;
/* P3 */
sbit RD = 0xB7;
sbit WR = 0xB6;
位 T1 = 0xB5;
位 T0 = 0xB4;
sbit INT1 = 0xB3;
sbit INT0 = 0xB2;
sbitTXD = 0xB1;
sbit RXD = 0xB0;
/* 斯康 */
位 SM0 = 0x9F;
位 SM1 = 0x9E;
sbit SM2 = 0x9D;
sbit REN = 0x9C;
sbit TB8 = 0x9B;
sbit RB8 = 0x9A;
sbit TI = 0x99;
sbit RI = 0x98;
#万一
Absacc.h是8051单片机不同存储区域的宏定义,如下:
#define CBYTE ((unsigned char volatile code *) 0) //定义程序存储器;
#define DBYTE((unsigned char volatile data *)0) //定义片内数据存储区域;
#define PBYTE ((unsigned char volatile pdata *) 0) //定义页寻址空间;
#define XBYTE ((unsigned char volatile xdata *) 0) //定义片外数据存储区域。
insides.h文件指示编译器生成嵌入代码,如无操作执行、位指令、堆栈操作指令等。该文件的具体内容如下:
外部无效_nop_(无效); //无操作8051 NOP指令
外部位_testbit_(位); //测试并清除8051 JBC指令位
extern unsigned char _cror_(无符号字符,无符号字符); //字符循环左移
extern unsigned int _iror_ (unsigned int, unsigned char); //字符循环右移
extern unsigned long _lror_ (unsigned long, unsigned char); //整数循环右移
extern unsigned char _crol_(无符号字符,无符号字符); //整数循环右移
extern unsigned int _irol_ (unsigned int, unsigned char); // 整数循环左移
extern unsigned long _lrol_ (unsigned long, unsigned char); //长整型循环左移
外部无符号字符 _chkfloat_(float); //测试并返回源点状态
extern void _push_ (unsigned char _sfr); //压入栈
extern void _pop_ (unsigned char _sfr); //弹出堆栈