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)。