74HC595功能介绍及代码驱动
摘要:74HC595是一款8位移位寄存器,具有串行输入、并行输出功能。其核心功能是通过移位寄存器接收串行数据,再通过存储寄存器输出到8个并行引脚。使用时需依次完成数据输入(通过SER引脚和SRCK时钟)、寄存器传输(RCK上升沿)和输出使能(G引脚低电平)三个步骤。支持多芯片级联扩展输出位数,但级联越多数据传输时间越长。文中详细介绍了引脚定义、工作原理、级联方法和GD32芯片的驱动代码实现。该芯片
一、引脚描述
QA~QH(15,1~7脚):数据输出引脚
QH1(9脚):移位寄存器串行数据输出脚,当移位寄存器中的数据多余8位时,最先进入的那位被挤出去,一般级联使用,接下一个74HC595
G(13脚):输出使能引脚,低电平使能
RCK(12脚):存储寄存器输入数据使能引脚,上升沿时,移位寄存器的数据输入到存储寄存器
SRCLR(10脚):移位寄存器清空引脚,低电平清空,一般不用,接高电平
SRCK(11脚):移位寄存器时钟引脚,上升沿时,移位寄存器的数据整体往后移动一位,并接受新的一位数据,来自SER(14脚)
SER(14脚):移位寄存器数据输入引脚
二、功能描述
这块芯片有两个寄存器:移位寄存器,存储寄存器
移位寄存器可以传值给存储寄存器,存储寄存器中的值决定QA~QH端口输出高低电平
移位寄存器的数据通过SRCK这个引脚上升沿采集,一个上升沿采集一位数据,存储方式类似流水线,最先进入的数据最先出去(先传输QH位)
当8个数据都存放进移位寄存器的时候,RCK产生一个上升沿,移位寄存器的数据就会传输到存储寄存器中,8个相对应的IO口就会输出相对应的高低电平
三、使用这块芯片分四个步骤
例如我们需要在端口QA~QH上输出 1 0 1 0 1 0 1 0
1、首先在SER引脚准备QH位,也就是 0 (低电平)
2、SRCK产生一个上升沿,0 就会被写入到移位寄存器的最上面
在SER引脚准备QG位,也就是 1 (高电平)
SRCK产生一个上升沿,1 就会被写入到移位寄存器的最上面,之前被写入的 0 就会往后移动一位
在SER引脚准备QF位,也就是 0 (高电平)
SRCK产生一个上升沿,1 就会被写入到移位寄存器的最上面,之前被写入的两位 1 0 就会往后移动一位
重复上面两个步骤8次,移位寄存器就会填满,移位寄存器随着上升沿的变化如下图
3、输出端口的高低电平是由存储寄存器决定的。移位寄存器填满之后,由RCK产生一个上升沿,移位寄存器的数据会传输到存储寄存器
4、拉低G引脚,输出存储寄存器的值到端口上,此时端口值为1010 1010
四、单个74HC595的使用
其中74HC595的RCK(12脚),SCK(11脚),SCLR(10脚),SER(14脚)接主控芯片的任意GPIO引脚。
OE(13脚)直接接地的,一直保持存储寄存器输出就好。可能会有疑问:当数据一位一位输入移位寄存器的时候,端口的值不会随着移位寄存器数据移动变化吗?
首先移位寄存器和存储寄存器的值是互不干扰的,我们要改变数据时,当数据一位一位压进移位寄存器中,再RCK(12脚)产生上升沿,把移位寄存器的值传输到存储寄存器中,端口才会输出存储寄存器的值,在此之前端口一直保持存储器的值。
五、74HC595的级联
级联实现:上一块移位寄存器的输出 接 下一块移位寄存器的输入,即U1-9接U2-14,
多块74HC595共用主控芯片的RCK(12脚),SCK(11脚),SCLR(10脚),第一块74HC595接主控芯片的移位寄存器输入引脚,
多块74HC595级联,要先发送最后一位,例如两块芯片级联则需要最先发送Q15位,然后依次发送Q14~Q0;
六、注意事项
是否可以无限级联?
理论上可以无限级联,最多占用4个IO口。
但是有个问题,级联越多,改变数据需要的时间越长,确切得说,是改变Q15需要的时间越长。
例如我2块芯片级联,我需要改变16位数据(Q0~Q15),它的数据是一位一位挤下去的,假设每发送一位数据需要的时间是1,就需要16个单位的时间。
同理我4块芯片级联,我需要改变32位数据(Q0~Q31),它的数据是一位一位挤下去的,假设每发送一位数据需要的时间是1,就需要32个单位的时间.
所以实际应用中很少无限级联
七、代码实现
我用的芯片是GD32F103VET6,两块74HC595级联
宏定义引脚拉高拉低,方便后面修改时序使用
74hc595.h
#ifndef __74HC595_H
#define __74HC595_H
#include "gd32f10x.h"
#define HC595_DIN(n) ((n)?gpio_bit_write(GPIOA, GPIO_PIN_8, SET) : gpio_bit_write(GPIOA, GPIO_PIN_8, RESET))
#define HC595_RCK(n) ((n)?gpio_bit_write(GPIOA, GPIO_PIN_9, SET) : gpio_bit_write(GPIOA, GPIO_PIN_9, RESET))
#define HC595_SCK(n) ((n)?gpio_bit_write(GPIOA, GPIO_PIN_10, SET) : gpio_bit_write(GPIOA, GPIO_PIN_10, RESET))
#define HC595_CLR(n) ((n)?gpio_bit_write(GPIOA, GPIO_PIN_11, SET) : gpio_bit_write(GPIOA, GPIO_PIN_11, RESET))
void hc595_init(void);
void hc595_send(uint16_t data);
#endif
74hc595.c
#include "74hc595.h"
//初始化
uint16_t hc595_data;
void hc595_init(void)
{
rcu_periph_clock_enable(RCU_GPIOA);//使能GPIOB外设时钟
gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11);
HC595_DIN(1);
HC595_RCK(1);
HC595_SCK(1);
HC595_CLR(1);
}
//发送数据
/*
0x55AA 0101 0101 1010 1010
Q0 Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 Q12 Q13 Q14 Q15
0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0
*/
void hc595_send(uint16_t data)
{
int i=0;
HC595_DIN(1);
HC595_RCK(1);
HC595_SCK(1);
HC595_CLR(1);
for(i =0;i<16;i++)
{
HC595_SCK(0);
if( data & (0x0001<<i) )
HC595_DIN(1);
else
HC595_DIN(0);
HC595_SCK(1);
}
HC595_RCK(0);
HC595_RCK(1);
hc595_data = data;
}
有问题欢迎讨论
更多推荐
所有评论(0)