- 流水灯控制原理、设计过程
本次实验采用锁存器74HC753与译码器74HC138以及一个或非门来实现流水灯控制。
原理图(添加了一点点说明)如下:
首先,要理解怎么使小灯点亮。
如图所示,小灯右端连接着电源(VCC),只有在左端为低电平的时候,小灯才会亮,也就是锁存器Q端输出为低电平的时候才会使小灯亮。
要使Q端输出低电平:(1)使锁存器控制端LE=1,/OE=0,锁存器此时状态为:D端输入与Q端输出一致,在P端输入低电平,Q端就能输出低电平。(2)使锁存器控制端LE=0,/OE=0,锁存器此时状态为锁定,Q端输出保持为之前的输出,不论P端怎么改变。
显然,D端输入受P0控制;/OE接地,恒为0;LE受Y4C控制。所以,Y4C控制着LE,同时也控制着锁存器的状态。Y4C作为或非门的输出,输入端WR接地,恒为0,输入端Y4为译码器的输出端Y4。译码器E1、/E2、/E3称为输入使能端,只有E1=1同时/E2=0和/E3=0时,输入信号才对3-8译码功能有效。由图可知,E1=1,E2=E3=0,所以此时译码器具备译码功能。此时,Y4的输出取决于CBA,也就是P2的输入。
综上所述,要使小灯点亮,需1.CBA=001➡Y4=0➡Y4C=1➡LE=1(锁存器输入等于输出)
2. D端输入0,Q端输出0
3.CBA=000➡Y4=1➡Y4C=0➡LE=0(锁存器处于锁定状态)
4.小灯亮!
流水灯控制原理:
为了实现小灯L1、L2、L3......依次点亮,需在Q端Q0、Q1、Q2......依次输出低电平且其余口输出高电平,来保证只有一个小灯亮且依次亮,并且循环往复,实现流水灯效果。
P0输入控制着D端输入,也就是控制Q端哪个口为低电平,也就是控制哪个小灯亮。
P2输入控制着锁存器的运行状态,在小灯点亮后锁定一下,实现小灯亮。
设计思路:
先使第一个灯L1点亮,其他灯不亮:
P2=0x80;使电路中译码器输出Y4=0,锁存器此时输入等于输出。
P0=0xfe; 此时只有P00为低电平,其他位都为高电平,L1点亮,其他小灯不亮。
P2=0x00;使电路中译码器输出Y4=1,锁存器此时锁定,L1保持点亮。
要使小灯L1灭掉,可以:
P2=0x80;
P0=0xff;
P2=0x00;
但是不需要专门让它灭掉,只需要使接下来的灯也都单独亮就好了。
接下来使第二个灯L2点亮,其他灯不亮:
P2=0x80;
P0=0xfd;
P2=0x00;
再使第三个灯L3点亮,其他灯不亮:
P2=0x80;
P0=0xfb;
P2=0x00;
.
.
.
.
.
.
在最初加个while(1)一直循环,由于计算机运算速度太快,流水灯速度过快,肉眼无法观察到,所以需要在每一个小灯亮了之后延时一会儿,也就是添加一个延时器:
for(i=0;i<=200;i++)
{
for(j=0;j<200;j++);
}
这样做的代码是这样的:
#include "stc15f2k60s2.h"
void main()
{
int i,j;
while(1)
{
P2=0x80;
P0=0xfe;
P2=0x00;
for(i=0;i<200;i++){
for(j=0;j<200;j++);}
P2=0x80;
P0=0xfd;
P2=0x00;
for(i=0;i<200;i++){
for(j=0;j<200;j++);}
P2=0x80;
P0=0xfb;
P2=0x00;
for(i=0;i<200;i++){
for(j=0;j<200;j++);}
P2=0x80;
P0=0xf7;
P2=0x00;
for(i=0;i<200;i++){
for(j=0;j<200;j++);}
P2=0x80;
P0=0xef;
P2=0x00;
for(i=0;i<200;i++){
for(j=0;j<200;j++);}
P2=0x80;
P0=0xdf;
P2=0x00;
for(i=0;i<200;i++){
for(j=0;j<200;j++);}
P2=0x80;
P0=0xbf;
P2=0x00;
for(i=0;i<200;i++){
for(j=0;j<200;j++);}
P2=0x80;
P0=0x7f;
P2=0x00;
for(i=0;i<200;i++){
for(j=0;j<200;j++);}
}
}
确实是个笨方法,但是可以实现流水灯效果。
为了让代码更简洁、高级,可以运用取反“~”和移位“<<”操作来实现。
由于C语言的移位,操作后“形成的空位”是“补0”的。要实现LED灯亮的移位,需要这样处理:原始操作数为0x01(二进制00000001),左移1位后为(00000010)输出时采用反码操作(~取反操作)变成(11111101),以此类推。即:
Unsigned char x=0x01;
P2=0x80;
P0=~x;
P2=0x00;
x=x<<1;
再在此基础上加入循环:
unsigned char x=0x01;
while(1)
{
P2=0x80;
P0=~x;
P2=0x00;
delay(1000);
x=x<<1;
if(x==0)
{
x=0x01;
}
}
再定义一个延时器:
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;++i)
{
for(j=0;j<113;++j);
}
}
把这些组合在一起就得到了简化版:
#include "stc15f2k60s2.h"
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;++i)
{
for(j=0;j<113;++j);
}
}
void main()
{
unsigned char x=0x01;
while(1)
{
P2=0x80;
P0=~x;
P2=0x00;
delay(1000);
x=x<<1;
if(x==0)
{
x=0x01;
}
}
}
至此,流水灯设计完毕,若要改变流水方向,只需更改P0端输入x以及反方向移位即可。
#include "stc15f2k60s2.h"
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;++i)
{
for(j=0;j<113;++j);
}
}
void main()
{
unsigned char x=0x80;
while(1)
{
P2=0x80;
P0=~x;
P2=0x00;
delay(1000);
x=x>>1;
if(x==0)
{
x=0x80;
}
}
}
若要使流水灯左右往复流水,可以将从左到右流水和从右到左流水结合即可。
代码:
#include "stc15f2k60s2.h"
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;++i)
{
for(j=0;j<113;++j);
}
}
void main()
{
int a,b;
unsigned char x=0x80;
while(1)
{
for(a=0;a<8;a++)
{
P2=0x80;
P0=~x;
P2=0x00;
delay(1000);
x=x>>1;
}
if(x==0)
{
x=0x01;
}
for(b=0;b<8;b++)
{
P2=0x80;
P0=~x;
P2=0x00;
delay(1000);
x=x<<1;
if(x==0)
{
x=0x80;
}
}
}
}
间隔点亮只需将移位操作变成移两位即可。
代码:
#include "stc15f2k60s2.h"
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;++i)
{
for(j=0;j<113;++j);
}
}
void main()
{
int a;
unsigned char x=0x80;
while(1)
{
for(a=0;a<8;a++)
{
P2=0x80;
P0=~x;
P2=0x00;
delay(2000);
x=x>>2;
if(x==0)
{
x=0x80;
}
}
}
}
按顺序点亮只需调整移位即可。“<<”逻辑左移。左移时,低位补0;高位移出的部分舍弃。
代码:
#include "stc15f2k60s2.h"
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;++i)
{
for(j=0;j<113;++j);
}
}
void main()
{
int a;
unsigned char x=0xfe;
while(1)
{
for(a=0;a<8;a++)
{
P2=0x80;
P0=x<<a;
P2=0xff;
delay(5000);
}
}
}
实现顺序点亮再顺序熄灭:按顺序点亮如上一例子,移位操作即可。按顺序熄灭需要设置一个中间变量。全亮时,P0=0x00,熄灭第一个小灯时P0=0x8f,熄灭第二个小灯时P0=0xc0,熄灭第三个小灯时P0=0xe0......这样看比较难看出规律,看图:
代码如下:
#include "stc15f2k60s2.h"
void delay(unsigned int k)
{
unsigned int i,j;
for(i=0;i<k;++i)
{
for(j=0;j<113;++j);
}
}
void main()
{
int a;
unsigned char x,b;
while(1)
{
x=0xff;
for(a=0;a<=8;a++)
{
P2=0x80;
P0=x>>a;
P2=0xff;
delay(5000);
}
x=0x80;
P2=0x80;
P0=x;
P2=0xff;
delay(5000);
b=x/2;
for(a=0;a<=8;a++)
{
x=x+b;
P2=0x80;
P0=x;
P2=0xff;
delay(5000);
b=b/2;
}
}
}
这就是几种不同模式的流水灯。