分类: 嵌入式
2014-06-09 20:33:50
2、点亮LED3、LED5、LED7、LED9
实现的方法与上面例子的方法一样,只是在程序中,对需要点亮的LED灯分别进行声明。
源程序代码:
//******************************
// 名称:点亮LED3、LED5、LED7、LED9
//******************************
// 作用:使点亮LED3、LED5、LED7、LED9位置的灯同时被点亮
//******************************
#include
sbit led3=P1^1;
sbit led5=P1^3;
sbit led7=P1^5;
sbit led9=P1^7;
void main()
{
led3=0;
led5=0;
led7=0;
led9=0;
}
将程序下载到单片机里面,可以看到4个灯同时被点亮。
当我们需要操作更多个LED灯就需要对多个I/O口分别进行声明和操作,程序会比较复杂。所以我们就要考虑能不能对程序进行简化。上面的编程方法是对单片机P1口的某一位直接进行操作,能不能对P1口所有位直接进行操作?我们来研究下P1口的输出数据,比如上例中要点亮4个灯,P1口的二进制输出由高位到低位分别为01010101,改成十六进制为0x55。所以如果要用P1口直接操作,就将大括号中的命令改为P1=0x55即可;其完整的程序如下:
源程序代码:
//******************************
// 名称:点亮LED3、LED5、LED7、LED9
//******************************
// 作用:使点亮LED3、LED5、LED7、LED9位置的灯同时被点亮
//******************************
#include
void main()
{
P1=0x55;
While(1);
}
我们可以看到程序简化了许多,不需要对操作位进行声明。
当程序执行完P1=0x55命令后,没有给单片机指定需要执行的其他命令,而单片机只要有电源就会不断工作,所以单片机会不断的执行这条命令。而我们要求单片机执行这条命令以后就停止。所以就用到了while()命令。
第五行命令while(1)命令,1永远为真,while命令后面没有需要执行的命令,所以执行完这条命令后,单片机就停止在这一条命令,不再往下执行其他命令。
前面的例子控制的灯都是固定不变化的,接下来就要学习怎么让灯点亮一段时间后熄灭,然后再点亮。实现LED灯闪烁。
3、使LED2灯亮灭闪动
要实现闪烁,就是在亮灭之间要加一个延时。延时的实现有很多种方法,如果不要求精确值,用for语句就可以简单实现延时。
源程序代码:
//******************************
// 名称:LED2闪烁
//******************************
// 作用:使LED2按照要求亮灭闪烁
//******************************
#include
#define uint unsigned int
sbit led2=P1^0;
uint i,j;
void main()
{
while(1)
{
led2=0;
for(i=1000;i>0;i--)
for(j=114;j>0;j--);
led2=1;
for(i=1000;i>0;i--)
for(j=114;j>0;j--);
}
}
第二行#define uint unsigned int,是定义一个新的名称。由于原来的名称太繁琐,每次输入都比较麻烦,所以希望能够用一个新的名称代替老的名称,使输入简单方便。比如unsigned int重新定义后,以后输入的时候,就直接可以用uint代替就可以了。注意:后面没有“;”。
延时用for语句来实现,可以粗略计算延时时间为,当内部变量值为114时,延迟时间由外部输入变量值来决定,1000就是1000ms,即1s。前提条件是晶振的频率为11.0592MHz。
查看上例的程序,延时的for语句都是相同的,实现的功能也是一样的,都是延时。能不能把这部分程序独立出来,编写成一个子函数,当需要的时候,直接调用此子函数就行了。
子函数的写法有两种:一种是带参数的,一种是不带参数的。
不带参数的子函数:
void delay1s()
{
uint i,j;
for(i=1000;i>0;i--)
for(j=114;j>0;j--);
}
在延时子函数中,定义了局部变量。局部变量就是在某个子函数中定义的变量,当子函数被调用时,单片机为变量申请内部存储空间,当调用结束后,就自动释放掉。全局变量是在主函数外面定义的变量,贯穿在程序的执行整个过程中,申请的空间直到最终程序执行完才会释放。由于单片机的RAM一般都比较小,所以能够定义在子函数的就定义成局部变量,以节约内存。
注意:如果子函数在主函数的后面,在调用的时候,一定要在开头进行声明,要不然会报错。
LED0.C(11): warning C206: 'delay1s': missing function-prototype
LED0.C(18): error C231: 'delay1s': redefinition
LED0.C(21): error C231: 'delay1s': redefinition
完整的源程序代码如下:
//********************************
// 名称:LED2闪烁
//********************************
// 作用:调用不带参的子函数实现延时1s
//********************************
#include
#define uint unsigned int
void delay1s(); //需要声明调用的子函数
sbit led2=P1^0;
void main()
{
while(1)
{
led2=0;
delay1s();
led2=1;
delay1s();
}
}
void delay1s()
{
uint i,j; //定义局部变量
for(i=1000;i>0;i--)
for(j=114;j>0;j--);
}
带参数的子函数:
void delayms(unsigned int xms)
{
uint i,j;
for(i=1000;i>0;i--)
for(j=114;j>0;j--);
}
带参数的子函数顾名思义就是要带一个参数,xms就是子函数的形参,当把具体的数值带到子函数里面去的时候,具体的数值就是实参。形参的好处就是,一旦实参确定后,程序中的所有同名称的形参都会被改为这个数值。
完整的源程序代码如下:
//*******************************************
// 名称:LED2闪烁
//*******************************************
// 作用:调用带参数的子函数实现亮500毫秒灭800毫秒
//*******************************************
#include
#define uint unsigned int
void delayms(uint); //需要声明调用的子函数
sbit led2=P1^0;
void main()
{
while(1)
{
led2=0;
delayms(200); //亮200ms
led2=1;
delayms(800); //灭800ms
}
}
void delayms(unsigned int xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=114;j>0;j--);
}
到此,我们完成了一个灯的闪烁,多个灯的闪烁也可以用同样的方法。但是仅仅闪烁还不能满足我们的要求,我们要求灯能够按照我们的要求熄灭和点亮,实现一定的效果,这就是流水灯。接下来要实现流水灯左移效果。