单片机C语言入门之九有参或无参函数流水灯
虽然在前面各章的程序中大都只有一个主函数main(),但实用程序往往由多个函数组成。函数是C源程序的基本模块,通过对函数模块的调用实现特定的功能。采用函数模块式的结构使程序的层次结构清晰,便于程序的编写、阅读、调试。
- C语言的函数兼有其它语言中的函数和过程两种功能,从这个角度看,又可把函数分为有返回值函数和无返回值函数两种。
- 有返回值函数:此类函数被调用执行完后将向调用者返回一个执行结果,称为函数返回值。如数学函数即属于此类函数。由用户定义的这种要返回函数值的函数,必须在函数定义和函数说明中明确返回值的类型。
- 无返回值函数:此类函数用于完成某项特定的处理任务,执行完成后不向调用者返回函数值。这类函数类似于其它语言的过程。由于函数无须返回值,用户在定义此类函数时可指定它的返回为“空类型”, 空类型的说明符为“void”。
- 从主调函数和被调函数之间数据传送的角度看又可分为无参函数和有参函数两种。
- 无参函数:函数定义、函数说明及函数调用中均不带参数。主调函数和被调函数之间不进行参数传送。此类函数通常用来完成一组指定的功能,可以返回或不返回函数值。
- 有参函数:也称为带参函数。在函数定义及函数说明时都有参数,称为形式参数(简称为形参)。在函数调用时也必须给出参数,称为实际参数(简称为实参)。进行函数调用时,主调函数将把实参的值传送给形参,供被调函数使用。
1.无参函数的定义形式。
类型标识符 函数名()
{
语句;
}
其中类型标识符和函数名称为函数头。在很多情况下都不要求无参函数有返回值,此时函数类型符可以写为void。类型标识符指明了本函数的类型,函数的类型实际上是函数返回值的类型。该类型标识符与前面介绍的各种说明符相同。函数名是由用户定义的标识符,函数名后有一个空括号,其中无参数,但括号不可少。{}中的内容称为函数体。
来看个无参函数例子,在你想调用的地方贴上Hello();就会输出Hello world:
void Hello()
{
printf ("Hello,world \n");
}
2.有参函数定义的一般形式
类型标识符 函数名(形式参数表列)
{
语句;
}
有参函数比无参函数多了一个内容,即形式参数表列。在形参表中给出的参数称为形式参数,它们可以是各种类型的变量,各参数之间用逗号间隔。在进行函数调用时,主调函数将赋予这些形式参数实际的值。形参既然是变量,必须在形参表中给出形参的类型说明。
例如,定义一个函数,用于求两个数中的大数,可写为:
int max(int a, int b)
{
if (a>b) return a;
else return b;
}
这是一个带返回值的有参函数,调用此函数时写, max(6,5);这个6和5就会分别传送给a和b两个参数,如果a大于b直接返回a的值,我们用一个变量接收这个值value=max(6,5),value就等于6。有返回值函数中至少应有一个return语句。如果没有返回值不需要return,类型标识符int改为void,调用时写,max(6,5),就会输出Hello,A,如:
void max(int a, int b)
{
if (a>b)
printf ("Hello,A \n");
}
在C程序中,一个函数的定义可以放在任意位置,既可放在主函数main之前(不需要声明),也可放在main之后(必须声明)。
函数就说这么多了,在这里要提一下什么是局部变量和全局变量,局部变量是在函数内作定义说明的。其作用域仅限于函数内,离开该函数后再使用这种变量是非法的。局部变量只在被调用期间才分配内存单元,调用结束立即释放。允许在不同的函数中使用相同的变量名。说白一点就是写在函数内的就叫局部变量,你在函数外面使用这些变量就会报错。
全局变量也称为外部变量,它是在函数外部定义的变量。它不属于哪一个函数,它属于一个源程序文件。其作用域是整个源程序都可以使用。main函数也是个函数,在这中定义的也不属于全局变量哦。
来看个单片机例子吧,有参和无参函数的演示与使用,两种不同速度的流水灯
#include<stc12.h> //STC12系列头文件 复制到工程目录下
#define uint unsigned int //宏定义uint来替代unsigned int 在程序中只需使用uint即可
#define uchar unsigned char //宏定义uchar来替代unsigned char 在程序中只需使用uchar即可
sbit LEDK = P1^4;// 控制三极管基极
//uint a,b,c; //在这里定义的叫全局变量,整个程序都可以使用
uchar code LEDarray[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
void Delay(uint time); //函数声明 在main函数后面写的函数都要先声明
void ForwardWater(); // 函数声明
void BackWater();
//main函数前面可以不写声明 直接使用
//void Delay(uint time) //有参延时函数 time的值决定了延时时间
//{
// uint x,y;
// for(x=time;x>0;x--) //time参数传递给X
// for(y=210;y>0;y--); //for嵌套
//}
void main(void)
{
LEDK=0; //置0使PNP型三极管导通LED负极接地
P0=0x00; //P0口电平初始化为0 关闭全部LED
P0M1=0x00;
P0M0=0xff; //P0口全部设置为推挽输出 见手册87页 IO口模式配置
while(1)
{
ForwardWater();
BackWater(); //写成函数的形式,简单明了,哪里需要亮哪里
}
}
void Delay(uint time) //有参延时函数 time的值决定了延时时间
{
uint x,y; //局部变量
for(x=time;x>0;x--) //time参数传递给X
for(y=210;y>0;y--); //for嵌套
}
void ForwardWater() //无参函数,led向前流动快速
{
uchar i; //局部变量
for(i=0;i<8;i++) //正向流动 快速
{
P0=LEDarray[i]; //i=0 P0=0x01 i=1 P0=0x02 ....i=7 P0=0x80
Delay(1000);//延时一会大概250ms
}
}
void BackWater() //无参函数,led向后流动慢速
{
uchar i; //局部变量
for(i=0;i<8;i++) //逆向流动 慢速
{
P0=LEDarray[7-i]; //i=0 P0=0x80 i=1 P0=0x40 ....i=7 P0=0x01
Delay(4000);//延时一会大概1S
}
}