数码管学习之路(静动态数码管源码及学习理解)

1,了解数码管分类及结构

       数码管是一种半导体发光器件,其基本单元是发光二极管。数码管按段数一般分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管(多一个小数点显示)。当然也还有一些其他类型的数码管如“N”形管、“米”字管以及工业科研领域用的 16 段管、24 段管等。如下图1:

图1 常见数码管

                        

           以八段数码管为例,我们来看一下数码管的结构图,如下图2:

图2 八段数码管结构图​​​​​

        有图2可以知道八段数码管分为八段,a、b、c、d 、e、 f 、g 、dp,其中dp为小数点位,每一段都是一个发光二极管。数码管有共阳极和共阴极之分,实际就是把数码管的阳极或阴极连在同一个引脚上面,区别在于公共端是高电平合适低电平,共阳极需要给低电平才能点亮,共阴极则反之。

        以共阳极数码管为例,0~f显示,如图3:

图3 数码管编码译码表

2,知道静动态数码管的区别及工作原理

       以六位八段数码管为例进行介绍:

六位数码管等效电路

        静态数码管:位选信号,高电平有效,六个数码管显示一样的数字,则称为静态数码管。

        动态数码管:简单点,就是不同管可以同时显示不同的数字,其利用了人眼视觉暂留和数码管的余晖效应,人眼暂留:人眼在观察事物时,光信号传入大脑神经,需要经过一段短暂的时间,光的作用结束后,视觉影像并不会立即消失,这种残留的视觉称为“后像”,这个现象被称为“视觉暂留”。数码管的余晖效应:当停止向发光二极管供电时发光二极管仍能维持一段时间。人眼分辨有限,大概40ms以内的闪烁人眼不会观察到它的闪烁,由此可以实现动态数码管显示。

        不管是静态数码管还是动态数码管,其都需要驱动,这里我使用的是74hc595驱动模块,它是一个8位串行输入、并行输出的位移缓存器。内部具有8位移位寄存器和一个存储器,具有三态输出功能,这里我们用到了两片74hc595,级联使用,完成数码管驱动。

3,源码

//hc595驱动
module  hc595_ctrl(

    input   wire    clk,
    input   wire    rst_n,
    input   wire    [5:0]   sel,
    input   wire    [7:0]   seg,
    
    output  reg     ds,
    output  wire    oe,
    output  reg     shcp,
    output  reg     stcp

);

wire   [13:0]   data;
reg    [1:0]    cnt;
reg    [3:0]    cnt_bit;

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

always @(posedge  clk or negedge rst_n )
    if(rst_n==1'b0)
        cnt <= 2'd0;
    else    if(cnt==2'd3)
        cnt <= 2'd0;
    else
        cnt <= cnt +1'b1;

always @(posedge  clk or negedge rst_n )
    if(rst_n==1'b0)
        cnt_bit <= 4'd0;
    else    if((cnt_bit==4'd13)&&(cnt==2'd3))
        cnt_bit <= 4'd0;
    else    if(cnt==2'd3)
        cnt_bit <= cnt_bit +1'b1;
    else 
        cnt_bit <= cnt_bit;

always @(posedge  clk or negedge rst_n )
    if(rst_n==1'b0)
        ds <= 1'b0;
    else
        ds <= data[cnt_bit];
        
always @(posedge  clk or negedge rst_n )
    if(rst_n==1'b0)
        shcp <= 1'b0;
    else    if(cnt==2'd2)
        shcp <= 1'b1;
     else    if(cnt==2'd0)
        shcp <= 1'b0;
    else
        shcp <= shcp;
        
always @(posedge  clk or negedge rst_n )
    if(rst_n==1'b0)
        stcp <= 1'b0;
    else    if((cnt==2'd0)&&(cnt_bit==4'd0))
        stcp <= 1'b1;
    else    if((cnt==2'd2)&&(cnt_bit==4'd0))
        stcp <= 1'b0;
    else
        stcp <= stcp;
        
assign  oe = 1'b0;        
        



endmodule
//静态数码管控制
module  seg_static
#(      parameter  CNT_MAX = 25'd24_999_999
)
(

    input   wire    clk,
    input   wire    rst_n,

    output  reg     [5:0]   sel,
    output  reg     [7:0]   seg
);

reg     [24:0]  cnt;
reg     [3:0]   data;
reg             cnt_flag;

always @ (posedge   clk or  negedge rst_n)
    if(rst_n==1'b0)
        cnt <= 25'd0;
    else    if(cnt==CNT_MAX)
        cnt <= 25'd0;
    else
        cnt <= cnt + 1'b1;
        
always @ (posedge   clk or  negedge rst_n)
    if(rst_n==1'b0)
        data <= 4'd0;
    else    if((cnt_flag==1'b1)&&(data==4'd15))
        data <= 4'd0;
    else    if(cnt_flag==1'b1)
        data <= data + 1'b1;
    else 
        data <= data;
        
always @ (posedge   clk or  negedge rst_n)
    if(rst_n==1'b0)
        cnt_flag <= 1'b0;
    else    if(cnt==CNT_MAX-1)
        cnt_flag <= 1'b1;
    else
        cnt_flag <= 1'b0;
        
always @ (posedge   clk or  negedge rst_n)
    if(rst_n==1'b0)
        sel <= 6'b000_000;
    else
        sel <= 6'b111_111;

always @ (posedge   clk or  negedge rst_n)
    if(rst_n==1'b0)
        seg <= 8'hff;
    else 
        case(data)
            4'd0   :   seg <= 8'hc0;
            4'd1   :   seg <= 8'hf9;
            4'd2   :   seg <= 8'ha4;
            4'd3   :   seg <= 8'hb0;
            4'd4   :   seg <= 8'h99;
            4'd5   :   seg <= 8'h92;
            4'd6   :   seg <= 8'h82;
            4'd7   :   seg <= 8'hf8;
            4'd8   :   seg <= 8'h80;
            4'd9   :   seg <= 8'h90;
            4'd10   :  seg <= 8'h88;
            4'd11   :  seg <= 8'h83;
            4'd12   :  seg <= 8'hc6;
            4'd13   :  seg <= 8'ha1;
            4'd14   :  seg <= 8'h86;
            4'd15   :  seg <= 8'h8e;
            default :  seg <= 8'hff;
        endcase
        

endmodule
//动态数码管数据产生
module  seg_en(

    input   wire    clk,
    input   wire    rst_n,
    
    output  reg     [5:0]   sel,
    output  reg     [7:0]   seg

);

parameter   CNT1_MAX = 23'd4_999_999;

wire   [7:0] seg_data[0:9];

assign       seg_data[0] = 8'hc0;
assign       seg_data[1] = 8'hf9;
assign       seg_data[2] = 8'ha4;
assign       seg_data[3] = 8'hb0;
assign       seg_data[4] = 8'h99;
assign       seg_data[5] = 8'h92;
assign       seg_data[6] = 8'h82;
assign       seg_data[7] = 8'hf8;
assign       seg_data[8] = 8'h80;
assign       seg_data[9] = 8'h90;
parameter   CNT_MAX = 26'd49_999_999;

reg     [22:0]  cnt1;
reg     [25:0]  cnt;
reg     [16:0]  cnt2;
reg     [3:0]   unit;
reg     [3:0]   ten;
reg     [3:0]   hund;
reg     [3:0]   thod;
reg     [3:0]   t_thod;
reg     [3:0]   h_thod;


always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)
        cnt1 <= 23'd0;
    else    if(cnt1==CNT1_MAX)
        cnt1 <= 23'd0;
    else    
        cnt1 <= cnt1 +1'b1;

always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)
        cnt <= 26'd0;
    else    if(cnt==CNT_MAX)
        cnt <= 26'd0;
    else    
        cnt <= cnt +1'b1;   
        
always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)
        cnt2 <= 17'd0;
    else    if((cnt==CNT_MAX)&&(cnt2==17'd99999))
        cnt2 <= 17'd0;
    else    if(cnt==CNT_MAX)
        cnt2 <= cnt2 +1'b1;  
    else    
        cnt2 <= cnt2;
        
        
        
always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)        
        unit <= 4'd0;
    else    if((cnt1==CNT1_MAX)&&(unit==4'd9))
        unit <= 4'd0;
    else    if(cnt1==CNT1_MAX)
        unit <= unit +1'b1;
    else    
        unit <= unit;
        
always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)        
        ten <= 4'd0;
    else    if((cnt1==CNT1_MAX)&&(unit==4'd9)&&(ten==4'd9))
        ten <= 4'd0;
    else    if((cnt1==CNT1_MAX)&&(unit==4'd9))
        ten <= ten +1'b1;
    else    
        ten <= ten;
        
always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)        
        hund <= 4'd0;
    else    if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(cnt1==CNT1_MAX))
        hund <= 4'd0;
    else    if((unit==4'd9)&&(ten==4'd9)&&(cnt1==CNT1_MAX))
        hund <= hund +1'b1;
    else    
        hund <= hund;
        
always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)        
        thod <= 4'd0;
    else    if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(cnt1==CNT1_MAX))
        thod <= 4'd0;
    else    if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(cnt1==CNT1_MAX))
        thod <= thod +1'b1;
    else    
        thod <= thod;        
 
always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)        
        t_thod <= 4'd0;
    else    if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(t_thod==4'd9)&&(cnt1==CNT1_MAX))
        t_thod <= 4'd0;
    else    if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(cnt1==CNT1_MAX))
        t_thod <= t_thod +1'b1;
    else    
        t_thod <= t_thod;        

 
always @(posedge clk or negedge rst_n)
    if(rst_n==1'b0)        
        h_thod <= 4'd0;
    else    if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(h_thod==4'd9)&&(t_thod==4'd9)&&(cnt1==CNT1_MAX))
        h_thod <= 4'd0;
    else    if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(t_thod==4'd9)&&(cnt1==CNT1_MAX))
        h_thod <= h_thod +1'b1;
    else    
        h_thod <= h_thod;        
        


always @(posedge clk or negedge rst_n)
    if (rst_n == 1'b0)
        sel <= 6'b000_000;
    else 
    case (cnt_n)    
        3'd0  : sel <= 6'b000_001;
        3'd1  : sel <= 6'b000_010;
        3'd2  : sel <= 6'b000_100;
        3'd3  : sel <= 6'b001_000;
        3'd4  : sel <= 6'b010_000;
        3'd5  : sel <= 6'b100_000;
        default: sel <= 6'b000_000; 
    endcase    
        


parameter   CNT_SEL = 16'd49_999;

reg     [2:0]   cnt_n;
reg     [15:0]  cnt_sel;

always @(posedge clk or negedge rst_n)
    if (rst_n == 1'b0)
        cnt_sel <= 3'd0;
    else    if(cnt_sel==CNT_SEL)
        cnt_sel <= 3'd0;
    else
        cnt_sel <= cnt_sel +1'b1;

always @(posedge clk or negedge rst_n)
    if (rst_n == 1'b0)
        cnt_n <= 3'd0;
    else    if((cnt_n==3'd5)&&(cnt_sel==CNT_SEL))
        cnt_n <= 3'd0;
    else    if(cnt_sel==CNT_SEL)
        cnt_n <= cnt_n +1'b1;
    else    
        cnt_n <= cnt_n;
    
    
always @(posedge clk or negedge rst_n)
    if (rst_n == 1'b0) 
        seg <= 8'hff;
    else    if(cnt_n==3'd0)
        seg <= seg_data[unit];
    else    if(cnt_n==3'd1)
            begin
                if(cnt2<17'd1)
                    seg <=  8'hff;
                else
                    seg <= seg_data[ten];    
            end 
    else    if(cnt_n==3'd2)
            begin
                if(cnt2<17'd10)
                    seg <=  8'hff;
                else
                    seg <= seg_data[hund];    
            end 
    else    if(cnt_n==3'd3)
            begin
                if(cnt2<17'd100)
                    seg <=  8'hff;
                else
                    seg <= seg_data[thod];    
            end 
    else    if(cnt_n==3'd4)
            begin
                if(cnt2<17'd1000)
                    seg <=  8'hff;
                else
                    seg <= seg_data[t_thod];    
            end 
    else    if(cnt_n==3'd5)
            begin
                if(cnt2<17'd10000)
                    seg <=  8'hff;
                else
                    seg <= seg_data[h_thod];    
            end 
    else
        seg <= 8'hff;
 
endmodule
//动态数码管数据控制0~9999999显示
module hc595_t(
    input wire clk,
    input wire rst_n,
    output reg [5:0] sel,
    output reg [7:0] seg
);

parameter CNT1_MAX = 23'd4_999_999;
parameter CNT_MAX = 26'd49_999_999;

wire [7:0] seg_data[0:9];
assign seg_data[0] = 8'hc0;
assign seg_data[1] = 8'hf9;
assign seg_data[2] = 8'ha4;
assign seg_data[3] = 8'hb0;
assign seg_data[4] = 8'h99;
assign seg_data[5] = 8'h92;
assign seg_data[6] = 8'h82;
assign seg_data[7] = 8'hf8;
assign seg_data[8] = 8'h80;
assign seg_data[9] = 8'h90;

reg [22:0] cnt1;
reg [25:0] cnt;
reg [16:0] cnt2;
reg [3:0] unit, ten, hund, thod, t_thod, h_hund;

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) cnt1 <= 0;
    else if (cnt1 == CNT1_MAX) cnt1 <= 0;
    else cnt1 <= cnt1 + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) cnt <= 0;
    else if (cnt == CNT_MAX) cnt <= 0;
    else cnt <= cnt + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) cnt2 <= 0;
    else if (cnt == CNT_MAX && cnt2 == 17'd99999) cnt2 <= 0;
    else if (cnt == CNT_MAX) cnt2 <= cnt2 + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) unit <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9) unit <= 0;
    else if (cnt1 == CNT1_MAX) unit <= unit + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) ten <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9) ten <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9) ten <= ten + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) hund <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9) hund <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9) hund <= hund + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) thod <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9) thod <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9) thod <= thod + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) t_thod <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9 && t_thod == 4'd9) t_thod <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9) t_thod <= t_thod + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) h_hund <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9 && t_thod == 4'd9 && h_hund == 4'd9) h_hund <= 0;
    else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9 && t_thod == 4'd9) h_hund <= h_hund + 1;
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) sel <= 6'b000001;
    else case (cnt2)
        17'd0: sel <= 6'b000001;
        17'd1: sel <= 6'b000011;
        17'd10: sel <= 6'b000111;
        17'd100: sel <= 6'b001111;
        17'd1000: sel <= 6'b011111;
        17'd10000: sel <= 6'b111111;
        default: sel <= sel;
    endcase
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) seg <= 8'hff;
    else case (1'b1)
        sel[0]: seg <= (unit <= 4'd9) ? 8'hff : seg_data[unit];
        sel[1]: seg <= (ten <= 4'd9) ? 8'hff : seg_data[ten];
        sel[2]: seg <= (hund <= 4'd9) ? 8'hff : seg_data[hund];
        sel[3]: seg <= (thod <= 4'd9) ? 8'hff : seg_data[thod];
        sel[4]: seg <= (h_hund <= 4'd9) ? 8'hff : seg_data[h_hund];
        sel[5]: seg <= (t_thod <= 4'd9) ? 8'hff : seg_data[t_thod];
        default: seg <= 8'hff;
    endcase
end

endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早点实现人生价值

创作不易,希望多多支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值