51单片机学习记录(3) “LED流水灯“

51单片机学习记录(3)

实现流水灯的几种方式

方式1: 利用左移(<<)和右移(>>)

首先简单介绍左移和右移的基本知识(不考虑特殊况)

  1. 左移:对传来的数据翻译成二进制后,将数据的每一位的值向左移动指定位数,丢失的位数用0补充
  2. 右移:对传来的数据翻译成二进制后,将数据的每一位的值向右移动指定位数,丢失的位数用0补充

下面简单的通过例子来说明

数据11111110
左移2位00111111
右移2位111000

那么如何利用左移和右移来实现流水效果呢?

我们知道可以对整个P2引脚赋值来点亮LED,而加上左移和右移的操作,引起每一个灯电平的变化,流水效果就是基于此来实现的

LED87654321
P2口76543210
赋值10
左移1位01111111

可以看到第八个led 灯的引脚变成了低电平被点亮而其他灯的引脚都为高电平都熄灭,依次下去就能实现流水的效果。当然你需要利用一下延时函数,否则现象不明显,因为代码运行的速度非常的快。

#include <reg51.h>

typedef unsigned char u8;
typedef unsigned int u16;

#define P2 led //宏定义P2口

void delay(u16 i)
{
	while(i--);
}

void main()
{
	led = 0xfe; //先点亮第一个灯,然后再进入循环
	while(1)
	{
		led = led >> 1; //每次左移一位
		delay(1000);  //延时1s
	}
}

当然你也可以进行右移的操作,方法和上面是差不多的

但是上述的程序并不能一直让灯循环的流水,当左移的效果完成后所有灯状态都被点亮也不会在改变所以可以在此程序的基础上加上一条控制语句就能让led循环亮灭。

#include <reg51.h>

typedef unsigned char u8;
typedef unsigned int u16;

#define led P2 //宏定义P2口

void delay(u16 i)
{
	while(i--);
}

void main()
{
	led = 0xfe; //先点亮第一个灯,然后再进入循环
	while(1)
	{
		led = led << 1; //每次左移一位
		delay(1000);  //延时1s
		if(led  == 0)
		{
			led = 0xff;
			delay(1000);
		}
	/*如果灯处于全亮的状态(0相当于0x00也就是灯的每个引脚都是低电平)
	 让灯全部熄灭,然后在不断的进行移位的操作,达成循环亮
	*/
	}
}

方式2:利用<intrins.h>里的左移函数和右移函数

  1. 左移函数: _cror_(a,b )
  2. 右移函数: _crol_(a,b )

其中a表示 需要操作的对象, b表示 每次需要移动的次数 举个例子

LED87654321
P2口76543210
赋值10
第一次_cror_(P2,1)后01111111
第二次_cror_(P2,1)后10111111
第三次_cror_(P2,1)后11011111

依次类推,右移函数也是同样的道理,可见使用位移函数同样也是依次点亮但不同于普通的位移,位移函数依次点亮led灯的同时也会让先前亮的灯熄灭

#include <reg51.h>
#include <intrins.h>
#define led P2

typedef unsigned char u8;
typedef unsigned int u16;

void delay(u16 i )
{
	while(i--);
}

void main()
{
	u8 i;    // 定义一个临时变量,用来控制for循环的次数
	led = 0xfe; //先让一盏灯亮起
	delay(1000) //延时一会在进入for循环,让现象明显点
	
	/*进入for循环后灯先从左向右依次点亮,接着再从右向左依次点亮不断循环*/
	
	for(i=0;i<7;++i)
	{
		led = _cror_(led,1);
		delay(1000);
	}
	for(i=0;i<7;++i)
	{
		led = _crol_(led,1);
		delay(1000);
	}
}

最后,我们也可以通过改变延时的时间以及位移的位数来实现许多不一样的效果

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值