74HC595工作原理及FPGA实现数码管驱动方法

 74HC595,移位寄存器,串行输入,8位并行输出,一般用于数码管电路以减少使用的IO口数量。


管脚介绍:

Q0~Q7 :八位并行输出位

Q7'       :  级联位,若输入位数大于8位,先进入的位会从此口连续输出,用于多片之间的级联

VCC GND 不多介绍

Ds        :  串行数据输入位

OE       : 输出使能位,低有效,一般直接全程给低电平就行

SHcp   :  移位寄存器时钟输入,后文详述

STcp    :  存储寄存器时钟输入,同上

MR      : 主复位,低有效,一般直接接到VCC拉高


       上图为74HC595内部结构,一个8位的移位寄存器,一个8位的存储寄存器,再有一个8位的并行输出。

      为讲明Q7'的级联作用,此处应用场景选择为:6位8段数码管,驱动此数码管共需要8位段选端和6位位选端,共14位串行数据输入。

       Ds数据输入端串行输入时,在SHcp的上升沿将数据移入移位寄存器内,每个SHcp上升沿移入一位单bit数据,最先输入的一直向后移直到8个SHcp上升沿后,移位寄存器填满,此时若数据输入端还有数据输入,下一个SHcp上升沿到来时,最先输入的1bit数据就会从Q7'输出(此处可理解为队列,先进先出)。在STcp的上升沿,数据会从移位寄存器进入存储寄存器中,当OE低有效时,存储寄存器中的值从Q0~Q7并行输出。

 

       上述应用场景下,将第一片74HC595的Q7‘串行输出端接到第二片的数据输入端Ds,实现级联功能。经过14个时钟SHcp上升沿后,数据已经全部移位进入移位寄存器,一次共输入14位数据,那么第一位输入的串行数据会在第二片74HC595芯片的Q5输出,此时给一个上升沿的STcp信号就可以将信号移入存储寄存器,OE信号持续给低, 即可输出。

上述过程中还存在一个问题,SHCP频率给多少合适?它是有限制的

        我实验板子的电压为3.3V,取图中2V的亦可,采用50MHZ的四分频12.5MHZ作为SHCP时钟,计数SHCP时钟上升沿,14个上升沿给出一个STCP的上升沿作为STCP时钟,相当于STCP时钟是SHCP时钟的14分频。

主要难点就在于SHCP和STCP时钟的获得,其他的按步骤来即可。

代码如下,需者自取(静态数码管)

`timescale 1ns/1ns


module seg_static(
    input sys_clk,
    input sys_rst_n,
    output reg [7:0]seg,
    output reg [5:0]sel
);

parameter seg_0 = 8'hc0,
          seg_1 = 8'hf9,
          seg_2 = 8'ha4,
          seg_3 = 8'hb0,
          seg_4 = 8'h99,
          seg_5 = 8'h92,
          seg_6 = 8'h82,
          seg_7 = 8'hf8,
          seg_8 = 8'h80,
          seg_9 = 8'h90,
          seg_a = 8'h88,
          seg_b = 8'h83,
          seg_c = 8'hc6,
          seg_d = 8'ha1,
          seg_e = 8'h86,
          seg_f = 8'h8e;
          
parameter cnt_500ms = 25'd24_999_999 ;
//parameter cnt_500ms = 25'd32_999_999 ;      

reg [24:0]cnt;   
reg [3:0]num;
          
always@(posedge sys_clk or negedge sys_rst_n)          
        if(sys_rst_n==1'b0)  
          cnt <= 25'd0;
          else if(cnt==cnt_500ms)
           cnt <= 25'd0;
           else 
           cnt <= cnt + 1'b1;
           
           
always@(posedge sys_clk or negedge sys_rst_n)          
        if(sys_rst_n==1'b0)  
          num <= 4'd0;
          else if(num==4'd15 && cnt==cnt_500ms)
           num <= 4'd0;
           else if(cnt==cnt_500ms)
           num <= num + 1'b1; 
            else 
           num <= num;
           
always@(posedge sys_clk or negedge sys_rst_n)          
        if(sys_rst_n==1'b0)  
          seg <= 8'b1111_1111;
          else
           case(num)          
          0 : seg <= seg_0;
          1 : seg <= seg_1;
          2 : seg <= seg_2;
          3 : seg <= seg_3;
          4 : seg <= seg_4;
          5 : seg <= seg_5;
          6 : seg <= seg_6;
          7 : seg <= seg_7;
          8 : seg <= seg_8;
          9 : seg <= seg_9;
         10 : seg <= seg_a;
         11 : seg <= seg_b;
         12 : seg <= seg_c;
         13 : seg <= seg_d; 
         14 : seg <= seg_e; 
         15 : seg <= seg_f; 
      default : seg <= 8'b1111_1111;   
      endcase
      
always@(posedge sys_clk or negedge sys_rst_n)          
        if(sys_rst_n==1'b0)  
          sel <= 6'b0;
          else 
          sel <= 6'b111_111;         
         
          
endmodule
`timescale  1ns/1ns


module hc595_ctrl(
    input sys_clk,
    input sys_rst_n,
    input wire [7:0]seg,
    input wire [5:0]sel,
    output reg shcp,
    output reg stcp,
    output reg ds,
    output wire oe
);

reg [1:0]cnt_4;
reg [3:0]cnt_14;

wire [13:0]data;

assign data = {seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel};

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        cnt_4 <= 2'b0;
        else if(cnt_4==2'd3)
        cnt_4 <= 2'b0;
        else 
        cnt_4 <= cnt_4 + 1'b1;


//sys_clk的四分频当作shcp时钟
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        shcp <= 1'b0;
        else if(cnt_4 <= 2'd1)
        shcp <= 1'b0;
        else  
        shcp <= 1'b1;
        
        
//产生stcp时钟
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        cnt_14 <= 4'b0;
        else if(cnt_14==4'd13 && cnt_4==2'd3)
        cnt_14 <= 4'b0;
        else if(cnt_4==2'd3)
         cnt_14 <= cnt_14 + 1'b1;
        else 
        cnt_14 <= cnt_14;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        stcp <= 1'b0;
        else if(cnt_14==4'd13 && cnt_4==2'd3)
        stcp <= 1'b1;
        else 
        stcp <= 1'b0;


//产生ds信号

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==1'b0)
        ds <= 1'b0;
        else if(cnt_4==2'd0)
        ds <= data[cnt_14];
        else 
        ds <= ds;


//产生oe信号

assign oe = ~sys_rst_n;



endmodule
`timescale  1ns/1ns

module smg_static(
    input  sys_clk,
    input  sys_rst_n,
    output shcp,
    output stcp,
    output oe,
    output ds
);

wire [7:0]seg;
wire [5:0]sel;

seg_static seg_static_inst(
   .sys_clk(sys_clk),
   .sys_rst_n(sys_rst_n),
   .seg(seg),
   .sel(sel)

);

hc595_ctrl hc595_ctrl_inst(
    .sys_clk(sys_clk),
    .sys_rst_n(sys_rst_n),
    .seg(seg),
    .sel(sel),
    .shcp(shcp),
    .stcp(stcp),
    .ds(ds),
    .oe(oe)
);

endmodule

动态数码管随缘更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值