当前位置:   article > 正文

FPGA驱动74HC595实现数码管动态显示_74hc595驱动数码管

74hc595驱动数码管

数码管原理

图片来源于网络
图a为单个数码管的原理图,实际上和点灯差不多,不过这8个灯按照数字8的形状进行排布。
数码管分共阴极和共阳极两种,图b左边是共阴极数码管,需要给对应的引脚高电平以点亮,右边是共阳极数码管,需要给低电平点亮。

驱动方式分类

1. 引脚直连

以6个8段数码管为例,每个数码管占用8个引脚,6个数码管就要占用48个引脚。
该方式对于fpga来说占用引脚过多,但这种方式使用起来最简单,比如友晶DE2开发板。

2. 位选+段选方式

将每个数码管的段选信号都连在一起,然后用6bit位选信号来选择数码管进行显示,引脚占用就减少到14个了,如下图:
图片来源于网络
在这种方式下,不管位选信号是多少,同一时刻只能显示一个数字,为了让不同的数码管显示不同的数字,需要进行动态显示。
动态显示下,任意时刻只选中1个数码管进行显示,6个数码管轮流点亮,由于余晖效应,只要刷新够快,就能让所有数码管同时显示。

3. 使用移位寄存器芯片74hc595

为了进一步减少数码管的引脚占用,使用74hc595芯片,其内部结构非常简单,就是一个8位的移位寄存器和一个8位的存储寄存器:
图片来源于网络
74hc595常用于串并转换,2片74HC595级联就能实现16位串转并,舍弃掉最后两位,就能实现14位串转并功能。
FPGA内部的14位的位选段选信号是并行的,我们需要先将其转化为串行数据输入74hc595,然后控制该芯片将串行数据转化为并行数据输出,只需控制DS、SHCP、STCP、OE四个引脚即可,这样FPGA的引脚占用就从14减小到4了。
其中,DS为串行数据,SHCP为移位时钟,STCP为锁存时钟,在两片74hc595级联的情况下,先将串行数据移位进两个8bit移位寄存器,再并行输出,即每16个SHCP上升沿对应1个STCP上升沿
此处我们需要自己写一个74hc595的驱动,将14位并行信号转化为串行信号,系统时钟50M,SHCP时钟选择系统时钟四分频,STCP选择系统时钟64分频,即SHCP的16分频,代码如下:

module hc595(
    input clk,
    input rst_n,
    // input
    input [7:0] seg,
    input [5:0] sel,
    // output
    output  ds,
    output  shcp,
    output  stcp,
    output  oe
);
//------------signals--------------
// oe低电平有效
assign oe = 1'b0;
// 分频计数器
reg [5:0] cnt;
// 并行数据,末尾两位舍弃不用
wire [15:0] out_data = {seg, sel, 2'b00};
//------------function-------------
// 分频计数器
always @(posedge clk, negedge rst_n) begin
    if(!rst_n)
        cnt <= 0;
    else
        cnt <= cnt + 6'd1;
end
// shcp选择4分频,即12.5M
assign shcp = cnt[1];
// stcp选择64分频,即shcp的16分频,保证16个shcp上升沿对应1个stcp上升沿
assign stcp = cnt[5:2] == 4'b0000;
// 输出串行ds,保证ds在shcp的下降沿变化
assign ds = out_data[cnt[5:2]];
endmodule
  • 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

BCD码转位选+段选信号

有了74hc595模块,FPGA就可以使用14位的位选+段选信号来驱动数码管了,但FPGA内一般用4位BCD码表示1个数字,则6个数字需要24位BCD码,需要再写一个驱动,将24位BCD码转化为14位位选+段选信号,按照1khz的频率进行扫描,快速的扫描加上数码管的余晖效应,人眼看起来6个数码管是同时点亮的,该驱动模块RTL图如下:
在这里插入图片描述
verilog代码如下:

module BCD2seg_sel(
    // input
    input               clk,
    input               rst_n,
    input       [23:0]  BCD_data,
    // output
    output reg  [7:0]   seg,
    output reg  [5:0]   sel
);
//------------signals--------------
    // 计数器,用于产生约1khz扫描信号,达到动态显示效果
    reg [15:0] cnt;
    wire       cnt_max = &cnt;
    // 被选中的BCD码
    reg [3:0]  BCD_out;
//------------function-------------
    // 计数器
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n)
            cnt <= 0;
        else
            cnt <= cnt + 16'd1;
    end

    // 循环移位寄存器,生成sel
    always @(posedge clk, negedge rst_n) begin
        if(!rst_n)
            sel <= 6'b000001;
        else if(cnt_max)
            sel <= {sel[4:0], sel[5]};
    end

    // 根据sel选择一个BCD码
    always @(*) begin
        case(sel)
            6'b000001: BCD_out = BCD_data[3:0];
            6'b000010: BCD_out = BCD_data[7:4];
            6'b000100: BCD_out = BCD_data[11:8];
            6'b001000: BCD_out = BCD_data[15:12];
            6'b010000: BCD_out = BCD_data[19:16];
            6'b100000: BCD_out = BCD_data[23:20];
              default: BCD_out = 4'h0;// 默认0
        endcase
    end

    // 根据BCD_out进行数码管译码
    always @(*) begin
        case(BCD_out)
            4'h0   : seg = 8'h03;
            4'h1   : seg = 8'h9f;
            4'h2   : seg = 8'h25;
            4'h3   : seg = 8'h0d;
            4'h4   : seg = 8'h99;
            4'h5   : seg = 8'h49;
            4'h6   : seg = 8'h41;
            4'h7   : seg = 8'h1f;
            4'h8   : seg = 8'h01;
            4'h9   : seg = 8'h09;
            default: seg = 8'h03;// 默认0
        endcase
    end
endmodule
  • 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

上板验证

用这个驱动显示一下012345,顶层模块代码如下,即实例化上述两个模块,并传入24位bcd码:

module HEX6(
    input   clk,
    input   rst_n,
    // 74HC595 side
    output  ds,
    output  shcp,
    output  stcp,
    output  oe
);
//------------signals--------------
wire    [23:0]  BCD_DATA = {4'h0, 4'h1, 4'h2, 4'h3, 4'h4, 4'h5};
wire    [7:0]   seg;
wire    [5:0]   sel;

//------------function-------------
BCD2seg_sel inst_BCD2seg_sel(
    .clk      (clk),
    .rst_n    (rst_n),
    .BCD_data (BCD_DATA),
    .seg      (seg),
    .sel      (sel)
);
hc595 inst_hc595(
    .clk   (clk),
    .rst_n (rst_n),
    .seg   (seg),
    .sel   (sel),
    .ds    (ds),
    .shcp  (shcp),
    .stcp  (stcp),
    .oe    (oe)
);
  • 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

上板验证结果如下:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/801802
推荐阅读
相关标签
  

闽ICP备14008679号