51单片机(七)—— LED进阶控制

        在《51单片机(五)》和《51单片机(六)》中,我们对LED的控制比较简单,都只是点亮的操作,在本文中,我们进行一些相对复杂的操作,来更加熟悉单片机IO口的使用。

一、闪灯

        在这个实验中,我们只对LED1进行控制,让它闪烁,代码如下所示

#include<reg52.h> //包含头文件,一般情况不需要改动,

sbit LED1=P0^0;   //用sbit关键字定义LED1到P00端口,

/********************************************************************/
/*                            延时函数                              */
/*              x决定延时时间的长短,x值越大,延时越长              */
/*                     x的取值范围为0~65535                         */
/********************************************************************/
void delay(unsigned int x)
{
	unsigned int i;
	for(i=0;i<x;i++);
}

/********************************************************************/
/*                              主函数                              */
/********************************************************************/
void main (void)
{
	for(;;)         //主循环
	{
		LED1=0;            //将P00口赋值0,对外输出低电平,灯点亮。
		delay(10000);      //调用延时函数
		LED1=1;            //将P00口赋值1,对外输出高电平,灯熄灭。
		delay(10000);      //调用延时函数
	}
}

        程序往往由多个函数组成,函数是C源程序的基本模块,通过对函数模块的调用实现特定的功能。用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来使用函数。

        C语言的函数兼有其它语言中的函数和过程两种功能,从这个角度看,可把函数分为有返回值函数和无返回值函数两种。有返回值函数:此类函数被调用执行完后将向调用者返回一个执行结果,称为函数返回值。由用户定义的这种要返回函数值的函数,必须在函数定义和函数说明中明确返回值的类型。无返回值函数:此类函数用于完成某项特定的处理任务,执行完成后不向调用者返回函数值。这类函数类似于其它语言的过程。由于函数无须返回值,用户在定义此类函数时可指定它的返回为“空类型”, 空类型的说明符为“void”。

        可以看出例程中的delay()函数没有返回值。

        函数调用。程序中是通过对函数的调用来执行函数体的,其过程与其它语言的子程序调用相似。在C语言中,可以用以下几种方式调用函数:

1、函数表达式:函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。例如:z=max(x,y)是一个赋值表达式,把max的返回值赋予变量z。

2、函数语句:函数调用的一般形式加上分号即构成函数语句。例如:delay();以函数语句的方式调用函数。

3、函数实参:函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。

       在程序用delay()函数是一个延时函数,由于为了实现灯闪烁的效果,因此delay()函数的延时时间没有经过精确计算,在以后的实验中,我们将会对如何精确计算延时函数的延时时间进行介绍。

二、流水灯

     这个实验的现象是, 8个LED灯从LED1开始点亮,依次点亮LED2直到点亮LED8,然后开始循环,任何时刻只有一个LED灯亮。  

#include<reg52.h> //包含头文件,一般情况不需要改动,

#define LED   P0    //宏定义,定义P0为LED

/********************************************************************/
/*                            延时函数                              */
/*              x决定延时时间的长短,x值越大,延时越长              */
/*                     x的取值范围为0~65535                         */
/********************************************************************/
void delay(unsigned int x)
{
	unsigned int i;
	for(i=0;i<x;i++);
}

/********************************************************************/
/*                              主函数                              */
/********************************************************************/
void main (void)
{
    unsigned char q;     
	LED=0xfe;     //给LED赋初值0xfe,即1111 1110,LED1点亮
	for(;;) 
	{
		for(q=0;q<8;q++)
		{
		    delay(30000);
			LED<<=1;            //LED左移一位
			LED=LED|0x01;       //LED与0x01按位做或,即LED最低位置1,其它位不变。
		}
        LED=0xfe;
	}
}

       在上面的代码中,用到了“|”运算。“|”是按位或运算。在数字电路中,或运算的规则是

             1|1=1;

             1|0=1;

             0|1=1;

             0|0=0;

        程序中LED有8位,例如LED=0xfe,其二进制值为1111 1110,则LED左移一位为1111 1100,再与0x01做按位或运算1111 1100|0000 0001=1111 1101

三、查表显示

        在这个实验中,我们使LED以更加复杂的方式点亮,代码如下

#include<reg52.h>   //包含头文件,一般情况不需要改动

#define LED   P0    //宏定义,定义P0为LED

/********************************************************************/
/*                              显示表格                            */
/********************************************************************/
unsigned char code table[]={
	                            0xe7,0xc3,0x81,0x00,
	                            0x18,0x3c,0x7e,0xff,
         				0x7e,0xbd,0xdb,0xe7,                             					0xe7,0xdb,0xbd,0x7e,
					0xff,0x55,0xaa,0x55,
					0xaa,0xff,0x00,0xff	
							};

/********************************************************************/
/*                            延时函数                              */
/*              x决定延时时间的长短,x值越大,延时越长              */
/*                     x的取值范围为0~65535                         */
/********************************************************************/
void delay(unsigned int x)
{
	unsigned int i;
	for(i=0;i<x;i++);
}

/********************************************************************/
/*                              主函数                              */
/********************************************************************/
void main (void)
{
	unsigned char q;  

	for(;;)        //主循环
	{
		for(q=0;q<24;q++)   //for循环,循环24个周期
		{
			LED=table[q];   //显示表格中的内容
			delay(30000);   //延时
		}
	}
}

1、在程序中,对table的定义如下:

      unsigned char code table[]

        在这个定义中使用了关键字code,那么带code与不带code有什么区别呢?带code关键字的是常量,被存放在单片机的ROM存储器中;不带code关键字的是变量,被存放在单片机的RAM存储器中。由于单片机的RAM空间相对较小,资源比较宝贵,一般把不需要变化的值和一些固定参数定义为code类型的常量。

2、数组。程序中定义的table[],实际上是一个一维数组,一维数组的定义方式为:

类型说明符 数组名 [常量表达式];

        其中:类型说明符是任一种基本数据类型或构造数据类型。数组名是用户定义的数组标识符。方括号中的常量表达式表示数据元素的个数,也称为数组的长度。程序中定义数组时,方括号中为空,这种数组的长度不是固定的,可以在数组中添加新的元素。在数组使用过程中,数组方括号中的内容代表数组中的元素,table[0]表示数组中的第一个元素,table[15]表示数组中的第十六个元素。

 

发布了78 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/bhniunan/article/details/104333810