51单片机实现流水灯

使用52单片机P2口点完成水灯

1.原理:

如果需要让LED灯点亮,那么就得给他一端高电平,一端低电平,而52单片机是弱上拉,强下拉,所以让单片机P2口负责低电平,另外给LED电源以防LED电压不足。

2.仿真图如下:

在运行Proteus进行仿真时,需要注意将电阻阻值进行设置,建议为220,否则LED灯可能不会亮

3.实现方法:

实现流水灯效果一共有三种方式:

第一种是库函数法,利用已经封装的库函数#include <intrins.h>里面的左移函数_crol_或者是右移函数_cror_来实现流水灯效果

第二种是利用C语言里面的位运算符:按位左移符:<<        或者是按位右移符:>>来实现

第三种更简单,是利用数组法把八位二进制数转换成两位十六进制数存放在一个数组里,利用循环来改变LED灯的状态,达到流水灯的效果

接下来进行代码演示

3.1.库函数法
位移函数
#include <reg52.h>
#include <intrins.h>//位移函数_crol_和_cror_的头文件
#define uint unsigned int   //用该方法给unsigned int型数据类型取别名为uint
#define uchar unsigned char


/*
位移函数说明:
#include <intrins.h>为头文件,必须加上,否则报错
左移:
_crol_(x,y)为其中一个函数,x可以为变量,值应该为一个十六进制数,y为左移的位数
右移:
_cror_(x,y)为其中一个函数,x可以为变量,值应该为一个十六进制数,y为右移的位数
*/



//延时函数,参数z单位为毫秒,1000ms=1s
//该延时函数利用到了C语言的嵌套循环,空语句
void delay(uint z)
{
  uint x,y;
  for(x = z;x > 0;x--)
     for(y = 114;y > 0;y--);
}


void main()
{
   P2 = 0xfe;  //P2为单片机控制LED的IO口
   delay(1000);
   while(1)
   {
      P2 = _crol_(P2, 1);//循环往左移一位,地位的补去高位
                  			 //_cror_ 循环往右移一位,高位的补去低位
      delay(1000);  //延时1s
   }
}

效果如下图:

3.2.数组法
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code LED[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //字符型数组,存放十六进制数
 

// 延时函数:毫秒延时
void delay(uint z)
{
	uint x,y;
	for(x = 0; x < z; x++)
		for(y = 0; y < 113; y++);
}

void main()
{

	uchar i;
	while(1)
	{
		for(i=0;i<8;i++)//将for循环与数组结合,不断改变LED灯状态达到流水灯效果
		{
			P2 = LED[i];
			delay(1000);//延时1s
		}
	}
}

效果如下图:

3.3.1位运算符法(暗灯流水)
#include"reg52.h"
#define uint unsigned int
#define uchar unsigned char

//延时函数
void delay(uint t)
{
	uint x,y;
	for(x=t;x>0;x--)
	{
		for(y=110;y>0;y--);
	}
}



void main()
{
	uchar i;
	while(1)
	{
		P2=0x01;  
		//给P2口赋初值必须放在死循环里,否则程序执行完for循环后会因为P2口
		//未复位而而导致LED全部常量
		delay(1000);
		for(i=0;i<8;i++)
		{
			P2=P2<<1;
			delay(1000);
		}
	}
}

效果如下图:

此处为暗灯流水效果

3.3.2位运算符法(亮灯流水)

这里以用到了C语言位运算符(<<)的一些特性:

假如设:unsigned char num=0xfe;

即:        num(1111 1110)

当num左移一位:num<<1;

                num(1111 1100)

num再次左移一位:num<<1;

                num(1111 1000)

由于位移运算符只会补充低位的特性,所以我们可以结合取反(~)来进行操作,如下:

假如设:unsigned char num=0x01;

              unsigned char k;

即:        num(0000 0001)

取反为: num(1111 1110)

当k=1,num左移一位:num<<k;

               num(0000 0010)

取反为: num(1111 1101)

当k=2,num再次左移两位:num<<k;

               num(0000 1000)

取反为: num(1111 0111)

此时就可以实现流水灯的亮灯流水效果

#include <REGX52.H>
#define uint unsigned int
#define uchar unsigned char



//延时函数,参数为毫秒,1000ms=1s
void delay(uint x)
{
	uint i,j;
	for(i=0;i<x;i++)
	for(j=110;j>0;j--);
}



void main()
{
	while(1)
	{
		uint y;             //循环变量y
		for(y=0;y<8;y++)
		{
			P2=~(0x01<<y);  //利用<<只会补充低位的特性,左移取反,实现亮灯流水
			delay(200);
		}
	}
}

效果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值