74HC595芯片介绍

  74HC595是一个8位串行输入、并行输出的位移缓存器,其中并行输出为三态输出(即高电平、低电平和高阻抗)。芯片管脚及功能说明如下:

  引脚功能:

  • 15和1到7QA-QH:并行数据输出
  • 9脚QH非:串行数据输出
  • 10脚SCLK非(MR):低电平复位引脚
  • 11脚SCK(SHCP): 移位寄存器时钟输入
  • 12脚RCK(STCP): 存储寄存器时钟输入
  • 13脚G非(OE): 输出有效
  • 14脚SER(DS) : 串行数据输入

  74HC595是具有8位移位寄存器和一个存储器,三态输出功能。移位寄存器和存储器是单独的时钟。数据在SCK的上升沿输入,在RCK的上升沿进入到存储器中。如果两个时钟连在一起,则移位寄存器总是比存储器早一个脉冲。移位寄存器有一个串行输入(DS),和一个串行输出(Q7非),和一个异步的低电平复位,存储寄存器有一个并行8位的,具有三态的总线输出,当MR为高电平,OE为低电平时,数据在SHCP上升沿进入移位寄存器,在STCP上升沿输出到并行端口。

硬件设计

  本实验使用到硬件资源如下:

  1. 16*16LED点阵模块
  2. 74HC595模块

  从上图中可以看出,该电路是独立的,74HC595模块内使用了4块74HC595芯片,它们采用了级联方式,即RCLK和SRCLK管脚并联在一起,并且74HC595(A)的输出QH非连接到74HC595(B)的串行输入口SER,而74HC595(B)的输出QH非又连接到74HC595(C)的串行输入口SER,依次类推。并且每块芯片的输出端都连接到对应的端子上,74HC595(A)的输出连接到J27端子,74HC595(B)的输出连接到J32端子,74HC595(C)的输出连接到LED点阵前8列,74HC595(D)的输出连接到LED点阵后8列。图上的NEGx是网络标号,与LED点阵列相连。74HC595 需要用到的控制管脚RCLK、SRCLK、SER并未直接连接到51单片机的IO上,而是连接到J24端子上

  要想控制LED点阵,可以将单片机管脚按照74HC595芯片的通信时序要求来传输数据,因为使用了4片74HC595芯片,A/B两块控制点阵行POS1-POS16,C/D两块控制点阵列NEG1-NEG16。这样即可控制LED点阵。根据LED发光二极管导通原理,当阳极为高电平,阴极为低电平则点亮,否则熄灭。因此通过单片机发送4组数据,通过595将这四组数据分配到对应输出从而控制LED点阵。

软件设计

  本实验要实现的功能是:通过74HC595模块控制LED点阵以一行循环滚动显示

实物接线图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include "reg52.h"

// 对系统默认数据类型进行重命名
typedef unsigned int u16;
typedef unsigned char u8;

// 定义74HC595控制管脚
sbit SRCLK = P3^6; // 移位寄存器时钟输入
sbit RC = P3^5; // 存储寄存器时钟输入
sbit SER = P3^4; // 串行数据输入

u8 ghc595_buf[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

/********************************************************************
*函数名: delay_10us
*函数功能:延时函数,ten_us=1时,大约延时10us
*输入: ten_us
*输出:无
*********************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}

/********************************************************************
*函数名: delay_ms
*函数功能: ms延时函数,ms=1时,大约延时1ms
*输入: ten_us
*输出:无
*********************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i = ms;i > 0;i--)
for(j = 110;j > 0;j--);
}

/********************************************************************
*函数名: hc595_write_data(u8 dat)
*函数功能:向74HC595写入4个字节的数据
*输入: dat1:对应74HC595(A)输出第1行-第8行
dat2:对应74HC595(B)输出第9行-第16行
dat3:对应74HC595(C)输出第1列-第8列
dat4:对应74HC595(D)输出第9列-第16列
*输出:无
*********************************************************************/
void hc595_write_data(u8 dat1,u8 dat2,u8 dat3,u8 dat4)
{
u8 i = 0;

for(i = 0;i < 8;i++) // 循环8次即可将一个字节写入寄存器中
{
SER = dat4 >> 7; // 优先传输一个字节中的高位
dat4 <<= 1; // 将低位移动到高位

// 移位寄存器时钟上升沿将端口数据送入寄存器中
SRCLK = 0;
delay_10us(1);
SRCLK = 1;
delay_10us(1);
}

for(i = 0;i < 8;i++)
{
SER = dat3 >> 7;
dat3 <<= 1;

SRCLK = 0;
delay_10us(1);
SRCLK = 1;
delay_10us(1);
}

for(i = 0;i < 8;i++)
{
SER = dat2 >> 7;
dat2 <<= 1;

SRCLK = 0;
delay_10us(1);
SRCLK = 1;
delay_10us(1);
}

for(i = 0;i < 8;i++)
{
SER = dat1 >> 7;
dat1 <<= 1;

SRCLK = 0;
delay_10us(1);
SRCLK = 1;
delay_10us(1);
}

// 存储寄存器时钟上升沿将前面写入到寄存器的数据输出
RC = 0;
delay_10us(1);
RC = 1;
}

void main()
{
u8 i = 0;

while(1)
{
for(i = 0;i < 8;i++)
{
hc595_write_data(ghc595_buf[i],0,0,0); // 使74HC595(A)输出
delay_ms(500); // 延时500ms
}
for(i = 0;i < 8;i++)
{
hc595_write_data(0,ghc595_buf[i],0,0); // 使74HC595(B)输出
delay_ms(500); // 延时500ms
}
}
}