74HC595驱动LED点阵或数码管的正确用法

这几天有些时间想做LED点阵玩玩,所以需要学习74HC595芯片,上网找了几个例程和关于74HC595的几篇应用,照猫画虎实际操作一下,哪知根本不可行,教程都是错误的。

于是自己潜心研究了 4天,现在已经可以对74HC595随心所欲的控制了,因此可以下结论了,网上关于74HC595的用法资料绝大多都是错的,误导严重。

网上最误导人的3个错误观点:

1、连续给8个SCK(11脚),最后给1个LCK(12脚),就可以把已经传送的8位数据全部一下锁存到8个存储寄存器当中去。

2、OE非先置1(输出高阻态,LED先不显示),然后发8个数据,再给1个LCK,8个数据锁存上之后,再把OE非置0,刷新显示。

3、SCLR(10脚)只清空移位寄存器,不清空锁存器。

如果按照上面的思路做,根本是做不成的。

74HC595正确的工作原理是这样的:(网上根本没有任何相关的说法)

1、只有1个移位寄存器,但有1+8个,共9个锁存器,见下图。其中第1个锁存器可以理解为中转前置锁存器,它并没有连接Q0-Q7,后面8个锁存器连接了Q0-Q7。

当第1次SCK和LCK时,移位寄存器中=第1位数据,前置锁存器=第1位数据。但是并没有进入到Q0-Q7所对应的锁存器当中去。Q0到Q7=NON。

当第2次SCK和LCK时,移位寄存器中=第2位数据,前置锁存器=第2位数据。同时前置锁存器把之前的第1位数据才更新到Q0对应的锁存器当中去。此时Q0=第1位。Q1到Q7=NON。

当第3次SCK和LCK时,移位寄存器中=第3位数据,前置锁存器=第3位数据。同时前置锁存器把之前的第2位数据才更新到Q0对应的锁存器当中去,Q0把之前的第1位数据给Q1,此时Q0=第2位。Q1=第1位。Q2到Q7=NON。

当循环8次后(给出8个SCK和8个LCK后),移位寄存器中=第8位数据,前置锁存器=第8位数据。但Q0-Q6里分别对应第7位-第1位数据,第8位数据并没有更新到Q0,同时Q7=NON。

这就是为什么给出循环8次的程序,总是不能显示第8位数据的原因。

因此要全部显示8位,需要再多给一次SCK和LCK

那么问题来了,最后给这次SCK和LCK,全部显示8位了。但是:移位寄存器和前置锁存器中又锁定了8位之外的第9位无用数据。

那么我们就可以用到SCLR(10脚)了。

给SCLR一个下降沿就可以了。这个下降沿同时清空移位寄存器和前置锁存器。但并不立即生效!只有产生下一个SCK时,才生效。

所以,SCLR时,前置锁存器和Q0-Q7锁存器依然锁定的是原来的数据,直到下一个SCK之前,不会改变输出内容。

而等我们下一次再传送一个新的8位数据时,在第一个SCK的时候,SCLR生效之后才接收新数据,因为不会影响接收新数据。

这个过程我称之为“收口操作“。


//74HC595驱动LED点阵或数码管的正确用法
#include 
   
   
    
    
#include 
    
    
     
     

#define uchar unsigned char
#define SDI_595 P2_0		 //	串口
#define SCK_595 P2_1		 // 移位
#define LCK_595 P2_2	     // 锁存
#define SCLR_595 P2_7	     // 清空移位寄存器
#define lednumber 8 	     //点阵数目
//const关键字定义的内容写在RAM中,code关键定义的内容写在ROM区。
//函数内部局部变量的声明,要放在函数开头。

void delay1000000us()
{
  unsigned char i,j,k;
  for(k=8;k>0;k--)
    for(j=244;j>0;j--)
      for(i=254;i>0;i--);
  for(k=1;k>0;k--)
    for(j=5;j>0;j--)
      for(i=247;i>0;i--);
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  _nop_();
}


void init_595()	 //595上电后Q0-Q7都是低电平,LED全亮。所以需要初始化(灭LED)。
{
    uchar i;
    SDI_595=1; 
    for(i=0;i
     
     
      
      >1;	
       delay1000000us();//观察效果		 
   }
   complete_receive_595();	//接收完毕执行收口。如果去掉这行,最后一位数据将不会锁存到Q0。
   while(1);
}


void main()
{
   init_595();
   delay1000000us();//观察初始化效果

   showled();
}



     
     
    
    
   
   


  • 20
    点赞
  • 117
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值