一 硬件

 

74HC595是一种8位串行输入,并行输出的寄存器芯片,一共有16个引脚,如下图。

        首先需要理解串行和并行的概念,这个比较容易,串行输入就是一个一个数地输入,并行输出就是8位一道输出,见下图【1】

其次需要明确芯片每个引脚的功能,见下表【2,3】

74HC595引脚功能
符号引脚功能
Q0~Q715,1~78位并行数据(parallel data)输出
GND8接地
Q7s9串行数据出口引脚,当移位寄存器中的数据多于8bit时,会把已有的bit“从此引脚挤出去”。可用于595的级联,这里将其空置
MR10清空移位寄存器中已有的bit数据(低电平有效),这里接VCC高电平即可
SHCP11移位寄存器时钟引脚,上升沿时,移位寄存器中的bit 数据整体后移,并接受新的bit
STCP12存储寄存器时钟输入引脚。上升沿时,数据从移位寄存器转存带存储寄存器
OE13输出使能控制脚(低电平有效),所以接GND
DS14串行数据输入引脚
VCC16电源

        这里面比较需要理解的是11、12引脚,对照功能描述,可以知道595芯片里面有2个8位寄存器:移位寄存器(Shift regisiter)、存储寄存器(Storage register)。这两个寄存器的讲解我觉得Vuko-wxh写的【3】里面非常清楚,移位就像压子弹入弹夹,当一个新的位数据要进来时,已经进入的位数据就在移位寄存器时钟脉冲的控制下(即11脚),整体后移,让出位置。数据从位移寄存器转移到存储寄存器,也是需要时钟脉冲驱动的,这就是12脚的作用。

最后是实际使用,1位数码管本来需要8个数字引脚控制,用595空置,只需占用3个数字引脚(如图,11、12、14接板上的数字引脚),硬件连接如下图:

    共阳数码管,一端阳极空置,另一端外接220欧姆再接VCC,Q0~Q7按照顺序依次接b->a->f->g->e->d->c->DP。另外接入按钮,配合下拉电阻使用。

 二 代码

功能:配合按钮+一位数码管,随机显示一个数字,效果是一位数码管一直随机显示数字,数字不断变换,当按下按钮,随机数会固定显示,松开后又恢复之前不断变换的状态。具体代码如下,参考了【1】

 //数字引脚
int latchPin = 8;//对接595芯片12引脚
int clockPin=3;//对接595芯片11引脚
int dataPin=9;//对接595芯片14引脚
int buttonPin=12;
//数字0~9
byte Tab[]={0x11,0x7D,0x23,0xb0,0x99,0x88,0x81,0x80,0x90};//0,1,2,6对,其他数字

int number;
long randNumber;

void setup() {
  pinMode(latchPin,OUTPUT);
  pinMode(dataPin,OUTPUT);
  pinMode(clockPin,OUTPUT);
  pinMode(buttonPin,INPUT);
  randomSeed(analogRead(0));//设置一个随机数产生源模拟口0
  
}

void loop() {
  boolean state = digitalRead(buttonPin);
  randNumber=random(10);//产生0~9之间随机数  
  //一旦按钮按下,显示该数,并保持到松开为止
  while(state == HIGH){
    delay(1000);
    state = digitalRead(buttonPin);
    }
}
//数码管显示数字
void showNumber(int number){
    digitalWrite(latchPin,LOW);
    shiftOut(dataPin,clockPin,LSBFIRST,Tab[number]);
    digitalWrite(latchPin,HIGH);
    delay(400);
  }

 知识点讨论:

1.关于对应数字的输入,这里没有用之前文章中数组的设计(因为是并行输出,不需要通过循环来显示一个数字),而是用十六进制直接代表,以0为例见下表

595输出引脚Q0Q1Q2Q3Q4Q5Q6Q7
对接的数码管引脚bafgedcDP

0

(数字)

00010001

0x11

(595输入数据,十六进制)

      后续语句中Tab[n]就可以把对应的数字代码导入到595中,再控制数码管显示对应数字了,因为偷懒,只验证了4个数字,其他就不对了。
2.关于74HCFC95的使用就是代码最后数码管显示数字部分,核心语句就是

shiftOut(dataPin,clockPin,bitOrder,value)

第三个参数bitOrder表示输出位的顺序,可选LSBFIRST(最低位优先)或MSBFIRST(最高位优先),试验了一下,发现用LSBFIRST时,完全符号我的预期,即Q0~Q7输出刚好对应b->DP的顺序(因为我就是这样对应接线的),但如果用MSBFIRST,则会把字节顺序反过来投射到b->DP上,还是上面0的例子,我导入字节是0x11(其实预期就是00010001对应到b->DP上),但实际效果确是{10001000}导入到b->DP上了,看来这里并没有真正搞懂,考虑到实际接线,我感觉要么是压入弹仓的顺序,要么是从移位寄存器到存储寄存器转移的顺序,这两个顺序有什么低位和高位变化吧。

3.关于按钮功能,这里用while函数实现,一开始自己写,漏了里面state=digitalRead(buttonPin)这句,导致一直在这个循环里出不来(按下后state变为1从而进入循环,按钮松开后,由于循环里没有再次读取buttonPin的状态,所以state一直是1),后来通过串口才发现,还是【1】里面写地好,直接while(digitalRead(buttonPin)==HIGH){}

4.关于随机数,之前红外遥控数码管的时候总是不成功,这回照抄【1】的,用了randomSeed()和random()两个函数,虽然还是有点懵,但好歹成功了。

【1】Arduino教程中级 项目十三 数字骰子 - DF创客社区 - 分享创造的喜悦

【2】74HC595_百度百科

【3】单片机芯片之——图解74HC595(第一部分)_Vuko_Coding Zone-CSDN博客_74hc595

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐