用单片机实现流水灯(进阶版)

cathy的头像

看到这个标题,很多人会想:“流水灯?谁不会流水灯啊。单片机入门的第一节课不就是实现跑马灯嘛?” 别急,慢慢看嘛,就算是简单的跑马灯,也可以玩出花样的哟。

先说说我今天讲的内容吧,首先:如何用P1口(只有八个引脚哟)实现八个流水灯,然后:如何用P1口实现十六个流水灯。最后,用32个引脚,P1,P2,P3,P4实现1024个流水灯呢?可能有人会说了,“不可能!!!”别急,再到最后,就是控制很多很多个!那我们就开始吧。

一、实验目的

1、熟悉P1口作输出口的原理与方法。

2、掌握循环延时,并能计算延时时间。

3、能熟练的使用keil编程和proteus仿真。

4、实现多个流水灯的控制

二、实验内容

1、用keil编写程序,编译运行。

2、用proteus进行仿真检验。

3、用面包板进行搭线展示,用2个流水灯实现流水效果。

三、实验原理

将单片机的P1口的0和1接上Led灯,采用共阴极的接法,当单片机的P1^0和P1^1引脚为低电平时,由于二极管的单项导通性,Led被点亮,即可实现循环流水效果。必要的知识还是需要滴,上图!

“用单片机实现流水灯(进阶版)"

四、电路图

实物图:

“用单片机实现流水灯(进阶版)"

proteus仿真结果:

“用单片机实现流水灯(进阶版)"

五、流程图

“用单片机实现流水灯(进阶版)"

六、源代码

#include <reg51.h>
sbit Led_0 = P1^0;
sbit Led_1 = P1^1;
sbit touch = P1^2;	//HTTM触摸开关

void delay()
{
	int i,j;
	for(i=0;i<200;i++)
	for(j=0;j<200;j++);
}
void main()
{
	touch = 0;
	while(1)
	{					   //说明:此按键为HTTM触摸开关
					      //按下为高电平,灯亮;不按下为低电平,灯灭
		if(touch == 1)	  //有按键被按下
		{
			Led_0 = 1;
			Led_1 = 0;
	  		delay();
	 		Led_0 = 0; 
			Led_1 = 1;
	  		delay();
		}
		else 	//没有按键被按下
		{							    
			Led_0 = 1;
			Led_1 = 1;
		}
	}
}

看到这里,有人就要说了,我都看么那么久了,你这不就是一个流水灯吗?还故弄玄虚搞那么久,我手中的西瓜刀已经准备好了,你继续表演吧。

行,马上就开始表演。

七、流水灯进阶

既然我们都写过流水灯,那我们一定对延时函数一定都不陌生,就随便给个延时等待嘛,但是有没有人想过,这个延时函数到底延时了多久?

“三分钟,我要这个延时函数的全部信息!”

我:可以用定时器测试的。

“不,我没学过定时器,但是我现在就要!快给我一个简单的方法!”

我:行,办法就在下面。

1、用C语言设计,如何计算延时时间

对于延时时间可以通过示波器进行准确的查看。在这里我准备了两段延时函数,分别是1ms,test(自定义)来进行测试,前面的1ms是经过精确计算无误的时间,后面的test则是自己需要计算的延时函数。
1ms测试结果(准确时间)

“用单片机实现流水灯(进阶版)"

测试结果:1ms时间准确。

Test延时函数测试

“用单片机实现流水灯(进阶版)"

Test延时函数测试结:delay = (909-605)ms = 304ms。

源代码如下:

#include <reg51.h>
sbit Out = P1^0;

void Delay1ms(void)   //测试1ms 误差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=142;b>0;b--)
            for(a=2;a>0;a--);
} 
void Delay10ms(void)   //测试10ms 误差 0us
{
    unsigned char a,b,c;
    for(c=5;c>0;c--)
        for(b=4;b>0;b--)
            for(a=248;a>0;a--);
}
void Delay_Test(void) //测试结果304ms
{
	int i,j;
	for(i=0;i<250;i++)
	for(j=0;j<150;j++);
}
void main()
{
	while(1)
	{
	 Out = 1;
	 Delay_Test();
	 Out = 0;
	 Delay_Test();
	}
}

2、当LED的数量远多于接口数量时(如50,100,1000个),该怎么实现流水灯?

解答如下:实现方法较多,这里我采用的是3-8译码器,通过3-8译码器的级联可以实现led数目的增加,实现50,100个没有问题,如果要实现1000个则需要4-16译码器,并通过级联的方式实现。

“用单片机实现流水灯(进阶版)"

实现结果如下:

源代码如下:

#include <reg51.h>
//用6个IO口点亮16个流水灯
//实现效果:可以用8个IO口点亮16个流水灯,
//分别为3 3显示 2片选,最多可控制16*4=64个 
/* 
	如果采用4-16译码器,包括片选端,那么一个占8个位置,可以亮16*16=256
	一共有32/8=4那么4*256=1024个灯,满足一千个灯
*/
sbit crol_1 = P1^0;
sbit crol_2 = P1^1;
sbit crol_3 = P1^2;	//设置控制代码
sbit crol_4 = P1^3;
sbit crol_5 = P1^4;
sbit crol_6 = P1^5;	//第二个译码器
sbit select_1 = P1^6;
sbit select_2 = P1^7;//片选
static int count = 0;

void delay_ms()	//设置延时函数
{
	int i,j;
	for(i=0;i<250;i++)
		for(j=0;j<250;j++);
}
void Crol_Flow_1()  //前八个
{
	select_1 = 1;	//设置片选端
	select_2 = 0;
	switch (count)
	{
		case 0:
			crol_3 = 0,crol_2 = 0,crol_1 = 0;
			break;
		case 1:
			crol_3 = 0,crol_2 = 0,crol_1 = 1;
			break;
		case 2:
			crol_3 = 0,crol_2 = 1,crol_1 = 0;
			break;
		case 3:
			crol_3 = 0,crol_2 = 1,crol_1 = 1;
			break;
		case 4:
			crol_3 = 1,crol_2 = 0,crol_1 = 0;
			break;
		case 5:
			crol_3 = 1,crol_2 = 0,crol_1 = 1;
			break;
		case 6:
			crol_3 = 1,crol_2 = 1,crol_1 = 0;
			break;
		case 7:
			crol_3 = 1,crol_2 = 1,crol_1 = 1;
			break;
	}
}
void Crol_Flow_2()  //后八个
{
	select_1 = 0;	//片选端
	select_2 = 1;	
	switch (count)  //设计亮的顺序
	{
		case 8:
			crol_6 = 0,crol_5 = 0,crol_4 = 0;
			break;
		case 9:
			crol_6 = 0,crol_5 = 0,crol_4 = 1;
			break;
		case 10:
			crol_6 = 0,crol_5 = 1,crol_4 = 0;
			break;
		case 11:
			crol_6 = 0,crol_5 = 1,crol_4 = 1;
			break;
		case 12:
			crol_6 = 1,crol_5 = 0,crol_4 = 0;
			break;
		case 13:
			crol_6 = 1,crol_5 = 0,crol_4 = 1;
			break;
		case 14:
			crol_6 = 1,crol_5 = 1,crol_4 = 0;
			break;
		case 15:
			crol_6 = 1,crol_5 = 1,crol_4 = 1;
			break;
	}
}
void main()
{	  
	while(1)
	{
		if(count == 16)
			 count = 0; //若是等于16则清零
		else if(count < 8)
		{
			Crol_Flow_1();
			delay_ms();
			count++;
		}
		else if (count < 16)
		{
		 	Crol_Flow_2();
			delay_ms();
			count++;
		}
	}
}

八、说点什么

其实大致的思路就是借用3-8译码器扩展引脚啦,是不是感觉豁然开朗呢。实现1024个流水灯也不难啦,用4-16的是不是就可以啦?好好思考一下。当然这只是我的思路,还有其它的方法。

————————————————
版权声明:本文为CSDN博主「会水的芝麻」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42369840/article/details/103429499
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。