跳转到主要内容

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

cathy 提交于

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

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

<strong><font color="#004a85">一、实验目的</font> </strong>

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

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

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

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

<strong><font color="#004a85">二、实验内容</font> </strong>

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

2、用proteus进行仿真检验。

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

<strong><font color="#004a85">三、实验原理</font> </strong>

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

<center><img src="http://mcu.eetrend.com/files/2022-01/博客/100556699-238348-1.png&quot; alt=“用单片机实现流水灯(进阶版)"></center>

<strong><font color="#004a85">四、电路图</font> </strong>

实物图:

<center><img src="http://mcu.eetrend.com/files/2022-01/博客/100556699-238349-2.png&quot; alt=“用单片机实现流水灯(进阶版)"></center>

proteus仿真结果:

<center><img src="http://mcu.eetrend.com/files/2022-01/博客/100556699-238350-3.png&quot; alt=“用单片机实现流水灯(进阶版)"></center>

<strong><font color="#004a85">五、流程图</font> </strong>

<center><img src="http://mcu.eetrend.com/files/2022-01/博客/100556699-238351-4.png&quot; alt=“用单片机实现流水灯(进阶版)"></center>

<strong><font color="#004a85">六、源代码</font> </strong>

<pre style="overflow-x:auto; background-color:#e9e9e9;">#include &lt;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&lt;200;i++)
for(j=0;j&lt;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;
}
}
}</pre>

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

行,马上就开始表演。

<strong><font color="#004a85">七、流水灯进阶</font> </strong>

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

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

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

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

我:行,办法就在下面。

<strong>1、用C语言设计,如何计算延时时间</strong>

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

<center><img src="http://mcu.eetrend.com/files/2022-01/博客/100556699-238352-5.png&quot; alt=“用单片机实现流水灯(进阶版)"></center>

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

Test延时函数测试

<center><img src="http://mcu.eetrend.com/files/2022-01/博客/100556699-238353-6.png&quot; alt=“用单片机实现流水灯(进阶版)"></center>

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

源代码如下:

<pre style="overflow-x:auto; background-color:#e9e9e9;">#include &lt;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&lt;250;i++)
for(j=0;j&lt;150;j++);
}
void main()
{
while(1)
{
Out = 1;
Delay_Test();
Out = 0;
Delay_Test();
}
}</pre>

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

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

<center><img src="http://mcu.eetrend.com/files/2022-01/博客/100556699-238354-7.png&quot; alt=“用单片机实现流水灯(进阶版)"></center>

实现结果如下:

源代码如下:

<pre style="overflow-x:auto; background-color:#e9e9e9;">#include &lt;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&lt;250;i++)
for(j=0;j&lt;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 &lt; 8)
{
Crol_Flow_1();
delay_ms();
count++;
}
else if (count &lt; 16)
{
Crol_Flow_2();
delay_ms();
count++;
}
}
}</pre>

<strong><font color="#004a85">八、说点什么</font> </strong>

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

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