74HC595移位寄存器
74HC595是一款高速硅栅极CMOS 器件,与低功耗肖基特TTL (LSTTL)引脚兼容。
74HC595具有存储寄存器和8位三态输出串行移位寄存器。寄存器具有单独的时钟。
数据在移位寄存器时钟输入 (SHCP) 的正向跳变时移位。移位寄存器中的数据在存储寄存器时钟输入 (STCP) 的正向跳变时传输到存储寄存器。如果两个时钟连接在一起,移位寄存器将始终比存储寄存器早一个时钟脉冲。
移位寄存器有一个串行输入(DS)和一个串行标准输出(Q7S)用于级联。它还为所有 8个移位寄存器级提供异步复位(低电平有效)。存储寄存器有 8 个并行三态总线驱动器输出。只要输出使能输入 (OE) 为低电平,存储寄存器中的数据就会出现在输出端。
管脚排列
引脚描述
时序图
驱动代码(C语言)
74HC595的使用需要产生STCP、SHCP、DS、OE四个信号对74HC595进行控制 。
DS(串行数据)是输入的数码管位选信号和段选信号;
SHCP(移位寄存器时钟),是DS数据进入移位寄存器的时钟。
STCP(存储寄存器时钟),是移位寄存器的数据进入存储寄存器的时钟。
OE(输出使能输入),当为低电平时,存储寄存器中的数据就会出现在输出端。
/*================================================================
*
* 函 数 名:HC595_ctrl()
*
* 参 数: bit --- 串行数据的输入位数(一片74HC595Z最大位数8位,两片级联最大位数16位)
* Data --- 串行数据 DS(14号引脚),数据串行输入口
*
* 功能描述: 74HC595驱动
*
* 返 回 值:无
*
* 说明:
*
* 作 者:你我山巅自相逢 2021/3/23
*
================================================================*/
void HC595_ctrl(unsigned char Bit,unsigned char Data)
{
unsigned char i=0;
DS = Data ; //串行数据输入
STCP=0 ; //输入存储器锁存时钟
SHCP=0 ; //数据输入时钟
for(i = 0; i < Bit; i++)
{
if(DS & 0x01)
DS = 1 ;
else
DS = 0 ;
DS = DS >>1 ;
SHCP=1; //上升沿,数据移位
SHCP=0; //拉低,等待下次上升沿使用
}
STCP=1 ; //上升沿8位数据并行输出
OE_LOW ; //输出使能输入 (OE)拉低, 输出存储寄存器中的数据
}
驱动代码(verilog)
module HC595_ctrl(Clk, Rst_, Sel, Seg, STCP, SHCP, DS, OE);
/********************参数定义********************/
parameter Divider_NUM = 3'd4 ; //分频系数
parameter Data_NUM = 4'd14 ; //传输位数
/*********************IO 说明********************/
input wire Clk ; //全局时钟
input wire Rst_ ; //异步复位,低电平有效
input wire [5:0] Sel ; //数码管位选信号
input wire [7:0] Seg ; //数码管段选信号
output reg STCP ; //存储寄存器时钟
output reg SHCP ; //移位寄存器时钟
output reg DS ; //串行数据
output wire OE ; //输出使能,低有效
/*******************内部信号声明*****************/
reg [1 :0] cnt_4 ; //分频计数寄存器
reg [3 :0] cnt_bit ; //传输位数计数寄存器
wire [Data_NUM-1:0] data ; //数码管信号寄存器
/******************** 功能定义*******************/
//数码管信号存储 (A,B,C,D,E,F,G,DP,DIG)
assign data = {Seg[0],Seg[1],Seg[2],Seg[3],Seg[4],Seg[5],Seg[6],Seg[7], Sel[5:0]} ;
//存储寄存器数据输出使能(OE)信号
assign OE = ~Rst_ ;
//四分频,产生移位寄存器(SHCP)信号
always@(posedge Clk or negedge Rst_)
if(!Rst_)
cnt_4 <= 2'd0 ;
else if(cnt_4 == Divider_NUM - 1'd1)
cnt_4 <= 2'd0 ;
else
cnt_4 <= cnt_4 + 1'd1 ;
always@(posedge Clk or negedge Rst_)
if(!Rst_)
SHCP <= 1'b0 ;
else if(cnt_4 < Divider_NUM/2)
SHCP <= 1'b0 ;
else
SHCP <= 1'b1 ;
//传输位数计数寄存器
always@(posedge Clk or negedge Rst_)
if(!Rst_)
cnt_bit <= 4'd0 ;
else if((cnt_bit == Data_NUM - 1'd1) && (cnt_4 == Divider_NUM - 1'd1))
cnt_bit <= 4'd0 ;
else if(cnt_4 == Divider_NUM - 1'd1)
cnt_bit <= cnt_bit +1'd1 ;
else
cnt_bit <= cnt_bit ;
//存储寄存器时钟(STCP) 在串行输入 “Data_NUM” 位数据后拉高
always@(posedge Clk or negedge Rst_)
if(!Rst_)
STCP <= 1'b0 ;
else if((cnt_bit == Data_NUM - 1'd1) && (cnt_4 == Divider_NUM - 1'd1))
STCP <= 1'b1 ;
else
STCP <= 1'b0 ;
//串行数据输出(DS)
always@(posedge Clk or negedge Rst_)
if(!Rst_)
DS <= 1'b0 ;
else if(cnt_4 == 2'd0)
DS <= data[cnt_bit] ;
else
DS <= DS ;
endmodule