一个流水灯就有八种方式,你觉得那种更好呢?(单片机花式点灯)

流水灯相信大家都不陌生吧,百度get到(流水灯是若干个灯泡依次点亮,视觉上感觉到灯光在流动就叫做流水灯。),就流水灯也太简单了吧,但是我想分享的是多种方式操作流水灯,例如P0,P1,P2,P3口都可以用来接LED灯。

下面我会分别使用这个四个口来操作流水的,使用不同的方式实现,其中不乏有最简单的直接付给低电平,也有使用指针来操作LED灯的控制码。相对来说还是很简单的,不多说了,来看代码。

1、移位函数操作流水灯

#include

#include //左移函数头文件

/***********************/

typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;

typedef unsigned char u8;

/***********************/

#define led P1

/****************************************************************

***************

* 函 数 名 : delay

* 函数功能 : 延时函数,i=1 时,大约延时 10us

*****************************************************************

**************/

void delay(u16 i)

{

while(i--);

}

/***********************/

void main()

{

u8 i;

led=~0x01;//0x01取反即为 0xFE

delay(50000); //大约延时 450ms

while(1)

{

for(i=0;i<7;i++)

{

P1=_crol_(led,1);//将 led 左移一位

delay(50000);

}

for(i=0;i<7;i++)

{

P1=_cror_(led,1);//将 led 右移一位

delay(50000);

}

}

}

2、P3口操作流水灯

这里先解释一下什么是控制码,简单来说我们需要点亮LED灯就需要给这个灯输低电平。然而代码中我们一般用16进制数来表示二进制数,当芯片去读这个16进制数会自动转换从二进制。

例如

unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

0xfe 转化成二进制就是 1111 1110 低位为0这样第一个灯就会亮

下面这种方式就是属于比较笨的方法,一个一个的给低电平

#include

#include //左移函数头文件

/***********************/

typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;

typedef unsigned char u8;

/***********************/

#define led P1

#define led P3

/****************************************************************

***************

* 函 数 名 : delay

* 函数功能 : 延时函数

*****************************************************************

**************/

void delay(u16 i)

{

while(i--);

}

void main(void){

while(1){

P3 = 0xfe ; //16 进制转换为二进制 1111 1110 第一个灯点亮,下面同理

delay(2000);

P3 = 0xfd ; //1111 1101

delay(2000);

P3 = 0xfb ; //1111 1011

delay(2000);

P3 = 0xf7;

delay(2000);

P3 = 0xef;

delay(2000);

P3 = 0xdf;

delay(2000);

P3 = 0xbf;

delay(2000);

P3 = 0x7f;

delay(2000);

}

}

3、右移操作流水灯

#include

//#include //左移函数头文件

/***********************/

typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;

/***********************/

#define led P1

/****************************************************************

***************

* 函 数 名 : delay

* 函数功能 : 延时函数

*****************************************************************

**************/

void delay(u16 i)

{

while(i--);

}

/***********************/

void main()

{

unsigned char i;

while(1){

P1 = 0xff;

delay(200000);

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

P1 = P1>>1;//将0xff右移动以为高位就变成0 低电平LED 灯亮

//1111 1111 右移动一位后就变成0111 1111

delay(20000);

}

}

}

4、do -while 流水灯写法

这个写法其实是多余的,就是用的循环方式不同而已,见谅。

#include

#include //左移函数头文件

/***********************/

typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;

/***********************/

#define led P3

/****************************************************************

***************

* 函 数 名 : delay

* 函数功能 : 延时函数,i=1 时,大约延时 10us

*****************************************************************

**************/

void delay(u16 i)

{

while(i--);

}

void main(void){

do

{

P3 = 0xfe ; //16 进制转换为二进制 1111 1110 第一个灯点亮,下面同理

delay(2000);

P3 = 0xfd ; //1111 1101

delay(2000);

P3 = 0xfb ; //1111 1011

delay(2000);

P3 = 0xf7;

delay(2000);

P3 = 0xef;

delay(2000);

P3 = 0xdf;

delay(2000);

P3 = 0xbf;

delay(2000);

P3 = 0x7f;

delay(2000);

}while(1);

}

5、字符数组控制P0口流水灯

这种使用将控制码放在数组中的方式就会让代码显得很优雅,嘻嘻。

#include

/***********************/

typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;

#define led P0

/****************************************************************

***************

* 函 数 名 : delay

* 函数功能 : 延时函数

*****************************************************************

**************/

void delay(u16 i)

{

while(i--);

}

void main(void){

unsigned char i;

unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

while(1){

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

P0 = Tab[i];

delay(2000);

}

}

}

6、指针数组控制P0 口流水灯

使用指针的优势恐怕现在是不能凸显出来,如果对比的同学应该知道正确使用指针后代码执行数度贼快,哈哈哈。

#include

/***********************/

typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;

#define led P0

/****************************************************************

***************

* 函 数 名 : delay

* 函数功能 : 延时函数

*****************************************************************

**************/

void delay(u16 i)

{

while(i--);

}

void main(void){

unsigned char i;

unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

unsigned char *P[] = {&Tab[0],&Tab[1],&Tab[2],&Tab[3],&Tab[4],&Tab[5],&Tab[6],&Tab[6],&Tab[7]};

while(1){

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

P0 = *P[i];

delay(2000);

}

}

}

7、数组的指针控制P0口流水灯

这个要仔细看就会发现和上面第6种方法的区别,指针在数组种的使用方法有很多种。

#include

/***********************/

typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;

#define led P0

/****************************************************************

***************

* 函 数 名 : delay

* 函数功能 : 延时函数

*****************************************************************

**************/

void delay(u16 i)

{

while(i--);

}

void main(void){

unsigned char i;

unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//流水灯控制码

unsigned char *P

P = Tab;

while(1){

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

P0 = *(p+i);//*(p+i)相当于a[i],通过指针引用数组元素

delay(2000);

}

}

}

8、指针作为参数控制流水灯

这里就是用函数来操作控制码,毕竟模块化编程还是需要了解的。

#include

/***********************/

typedef unsigned int u16; //对数据类型声明定义,就是将 u16定义为无符号整型 ;

#define led P0

/****************************************************************

***************

* 函 数 名 : delay

* 函数功能 : 延时函数

*****************************************************************

**************/

void delay(u16 i)

{

while(i--);

}

void led_flow(unsigned char *p){

unsigned char i;

while(1){

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

P0 = *(p+i);//*(p+i)相当于a[i],通过指针引用数组元素

delay(2000);

}

}

}

void main(void){

unsigned char code Tab[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//流水灯控制码

unsigned char *P;

P = Tab;

led_flow(p);//调用函数传入指针

}

以上就是我总结的关于流水灯的操作方式,可能代码中会有小错误,但是相信都开始学单片机的同学还是有一定的编程能力,一定能找出我写的bug哈哈哈。

友情链接