如果你是静态显示,那么灰度是没戏了。如果是动态显示,那就先点亮一个LED,再将595的数据刷新,令所有的LED灭掉,然后亮第二个LED,再将595的数据刷新,令所有的LED灭掉,如此循环,来控制LED点亮的占空比就可以控制灰度了。但这个办法的关键是你刷新的频率一定要足够高,不然就会产生闪烁。
其实,你电路中最大的问题就是OE脚被你锁死了,通常的产品都是靠这个引脚来控制灰度的。另外,595到LED之间最好再加一级驱动芯片,例如,2003,2803,否则595驱动电流不足,很容易烧坏。
建议采用pwm控制 ,就是 脉宽调制。
把led按照周期开启和关闭,但是每个周期开启的时间受到控制,你就能看到渐变效果了。
实施方案:最简单就是设定一个控制变量,每个周期开始,检查该变量,不为0则开启led并缓存该变量,在周期内的每个节拍时间,对缓存值进行递减,减到0,关闭led。
如果想多个同时控制,就多设几个变量,分别计数控制pwm就可以了。
程序如下:
#include
#define uchar unsigned char
#define uint unsigned int
sbit CLK=P1^7;
sbit STB=P1^6;
sbit DATA=P1^5;
sbit OE=P1^2;
void init_sys();
void delay(uint t);
void delayms(uint t);
unsigned char ZKB;
void send_data(uint temp1,temp2)
{
uchar i;
CLK=0;
STB=0;
for(i=0;i<8;i++)
{
if(temp1>=0x80)DATA=1;
else DATA=0;
CLK=0;
delay(15);
CLK=1;
delay(15);
temp1=temp1<<1;
}
for(i=0;i<8;i++)
{
if(temp2>=0x80)DATA=1;
else DATA=0;
CLK=0;
delay(15);
CLK=1;
delay(15);
temp2=temp2<<1;
}
STB=0;
delay(15);
STB=1;
delay(15);
CLK=0;
STB=0;
DATA=0;
}
void delayms(uint t)
{
uint x,y;
for(x=t;x>0;x--)
for(y=100;y>0;y--);
}
void delay(unsigned int t)
{
unsigned int i;
for(i=0;i
;
}
}
void init_sys()
{
TMOD=0x01;
TH0=0xFF;
TL0=0XF6;
TR0=1;
ET0=1;
EA=1;
}
void timer0(void) interrupt 1
{
static uchar click=0;
TH0=0xFF;
TL0=0xF6;
++click;
if (click>=100)
click=0;
if (click<=ZKB)
OE=0;
else
OE=1;
}
void main ()
{
init_sys();
send_data(0x00,0x00);
while(1)
{
for(ZKB=0;ZKB<100;ZKB=ZKB+1)
{
delayms(100);
}
for(ZKB=100;ZKB>0;ZKB=ZKB-1)
{
delayms(100);
}
}
}
在等全亮的情况下,用pwm来控制 OE这个脚,调整PWM的占空比来实现led灯的渐亮效果,当然pwm的频率要稍微高些,免得led灯闪烁。
利用PWM方法,可以实现LED亮度渐变,但是在PROTEUS中观察,并不是很鲜明。