AC620V2三线数码管动态显示(74HC595)使用Verilog实现数码管动态显示 ——学习笔记

文章详细介绍了如何利用74HC595移位寄存器驱动数码管进行动态显示,包括译码功能的实现、位选信号的生成以及16位移位寄存器的设计,展示了如何通过较少的IO控制多个数码管,适合IT技术爱好者学习嵌入式开发中的硬件设计。
摘要由CSDN通过智能技术生成

        首先数码管的动态显示原理我们应该是稍微比较熟悉的,他主要是利用人眼的视觉残留效应来进行数码管动态扫描,实现数码管的显示的。一般我们动态扫描的频率分到1khz的频率就可以了。小梅哥AC620这块板子采用的是共阳的数码管,对应显示数字的断码控制值我贴在下面。

整个工程主要分为两个模块:

                                        (这个是整个工程的RTL逻辑视图)

        第一个就是正常的译码功能,第二个就是我们这个工程的难点,也就是外接了由两片874HC595移位寄存器级联后构成16位移位寄存器并将级联后的输出连接到位选及段选口,可以直接通过三个IO即可控制88段数码管,这样做大大节省了芯片引脚。这里放一张三线八位数码管的电路逻辑图。

代码讲解部分:

1. 译码模块

        这里主要是一个动态扫描的问题,需要我们根据系统设置分出一个1khz的频率用作位选信号移位功能的实现,还有就是要区分数码管是共阴还是共阳的,用来写显示数据的断码控制值。

module hx8 (
clk,rst_n,sel_r,seg,disp_data

);
input clk,rst_n;
input  [31:0]  disp_data;
output   reg  [7:0] seg;
output  [7:0] sel_r;
   
     reg [14:0]divider_cnt;
     reg clk_1K;
     always@(posedge clk or negedge rst_n)//计数器
     begin
     if(!rst_n)
         divider_cnt <= 15'd0;
     else if(divider_cnt == 15'd24999)
         divider_cnt <= 15'd0;
     else
         divider_cnt <= divider_cnt + 1'b1;
     end    
     always@(posedge clk or negedge rst_n)//clk_1K
     begin
     if(!rst_n)
         clk_1K <= 1'b0;
     else if(divider_cnt == 15'd24999)
         clk_1K <= ~clk_1K;
     else
         clk_1K <= clk_1K;
     end  
 reg [7:0]sel_r;//第一到八个数码管    
     always@(posedge clk_1K or negedge rst_n)
     begin
     if(!rst_n)
         sel_r <= 8'b0000_0001;
     else if(sel_r == 8'b1000_0000)
         sel_r <= 8'b0000_0001;
     else
         sel_r <=  sel_r << 1;
     end    
         
     reg [3:0]data_tmp;   
    always@(*)
     begin
         case(sel_r)
             8'b0000_0001:data_tmp = disp_data[3:0];
             8'b0000_0010:data_tmp = disp_data[7:4];
             8'b0000_0100:data_tmp = disp_data[11:8];
             8'b0000_1000:data_tmp = disp_data[15:12];
             8'b0001_0000:data_tmp = disp_data[19:16];
             8'b0010_0000:data_tmp = disp_data[23:20];
             8'b0100_0000:data_tmp = disp_data[27:24];
             8'b1000_0000:data_tmp = disp_data[31:28];
             default:data_tmp = 4'b0000;
         endcase
     end
 always@(*)
 begin
         case(data_tmp)
             4'h0:seg = 7'b1000000;
             4'h1:seg = 7'b1111001;
             4'h2:seg = 7'b0100100;
             4'h3:seg = 7'b0110000;
             4'h4:seg = 7'b0011001;
             4'h5:seg = 7'b0010010;
             4'h6:seg = 7'b0000010;
             4'h7:seg = 7'b1111000;
             4'h8:seg = 7'b0000000;
             4'h9:seg = 7'b0010000;
             4'ha:seg = 7'b0001000;
             4'hb:seg = 7'b0000011;
             4'hc:seg = 7'b1000110;
             4'hd:seg = 7'b0100001;
             4'he:seg = 7'b0000110;
             4'hf:seg = 7'b0001110;
         endcase
end  
endmodule 

2. 74HC595驱动模块

        这个地方主要是看三线数码管显示的原理图,首先要清楚三个IO口的功能是什么,原理图我们可以看到SEG7_DIO,SEG7_RCLK,SEG7SCLK三个输入端口,经由两片74HC595芯片输出连接到数码管段选位选端口。这三个端口的功能分别是串行数据输出(DIO),移位寄存器的时钟输出(RCLK),存储寄存器的时钟输出(SCLK)。

代码中DIO==DS,RCLK==SH_CP,SCLK==ST_CP
module   hc59 (rst_n,clk, SH_CP,DS,ST_CP,sel_r,seg
); 
    input       rst_n;
    input       clk;
    input        [7:0]   seg;
    input        [7:0]   sel_r;    
    output  reg    DS;
    output  reg     SH_CP;
    output   reg   ST_CP;
  
     parameter CNT_MAX = 4; //分频数
     reg [15:0] divider_cnt;//分频计数器
     wire   [15:0]   r_data;
     assign r_data[15:8] = seg [7:0];
     assign r_data[7:0] = sel_r [7:0];

     always@(posedge clk or negedge rst_n)
     if(!rst_n)
         divider_cnt <= 16'd0;
     else if(divider_cnt == CNT_MAX)
         divider_cnt <= 16'd0;
     else
         divider_cnt <= divider_cnt + 1'b1;
     
     wire sck_pluse;
     assign sck_pluse = (divider_cnt == CNT_MAX);
     reg [4:0]SHCP_EDGE_CNT;//SH_CP EDGE counter
 
    always@(posedge clk or negedge rst_n)
     if(!rst_n)
         SHCP_EDGE_CNT <= 5'd0;
     else if(sck_pluse)begin
         if(SHCP_EDGE_CNT ==  5'd31)
             SHCP_EDGE_CNT <= 5'd0;
         else
             SHCP_EDGE_CNT <= SHCP_EDGE_CNT + 1'd1;
     end
     else
         SHCP_EDGE_CNT <= SHCP_EDGE_CNT;
 always@(posedge clk or negedge rst_n)
     if(!rst_n)begin
         SH_CP <= 1'b0;
         ST_CP <= 1'b0;
         DS <= 1'b0; 
     end
     else begin
         case(SHCP_EDGE_CNT)
             5'd0:begin SH_CP <= 1'b0; ST_CP <= 1'b1; DS <= r_data[15]; end
             5'd1:begin SH_CP <= 1'b1; ST_CP <= 1'b0;end
             5'd2:begin SH_CP <= 1'b0; DS <= r_data[14];end
             5'd3:begin SH_CP <= 1'b1; end
             5'd4:begin SH_CP <= 1'b0; DS <= r_data[13];end
             5'd5:begin SH_CP <= 1'b1; end
             5'd6:begin SH_CP <= 1'b0; DS <= r_data[12];end
             5'd7:begin SH_CP <= 1'b1; end
             5'd8:begin SH_CP <= 1'b0; DS <= r_data[11];end
             5'd9:begin SH_CP <= 1'b1; end
             5'd10:begin SH_CP <= 1'b0; DS <= r_data[10];end
             5'd11:begin SH_CP <= 1'b1; end
             5'd12:begin SH_CP <= 1'b0; DS <= r_data[9];end
             5'd13:begin SH_CP <= 1'b1; end
             5'd14:begin SH_CP <= 1'b0; DS <= r_data[8];end
             5'd15:begin SH_CP <= 1'b1; end
             5'd16:begin SH_CP <= 1'b0; DS <= r_data[7];end
             5'd17:begin SH_CP <= 1'b1; end
             5'd18:begin SH_CP <= 1'b0; DS <= r_data[6];end
             5'd19:begin SH_CP <= 1'b1; end
             5'd20:begin SH_CP <= 1'b0; DS <= r_data[5];end
             5'd21:begin SH_CP <= 1'b1; end
             5'd22:begin SH_CP <= 1'b0; DS <= r_data[4];end
             5'd23:begin SH_CP <= 1'b1; end
             5'd24:begin SH_CP <= 1'b0; DS <= r_data[3];end
             5'd25:begin SH_CP <= 1'b1; end
             5'd26:begin SH_CP <= 1'b0; DS <= r_data[2];end
             5'd27:begin SH_CP <= 1'b1; end
             5'd28:begin SH_CP <= 1'b0; DS <= r_data[1];end
             5'd29:begin SH_CP <= 1'b1; end
             5'd30:begin SH_CP <= 1'b0; DS <= r_data[0];end
             5'd31:begin SH_CP <= 1'b1; end
         endcase 
     end
 endmodule

3. 顶层文件代码

module   hx8_hc59 (rst_n,clk, SH_CP,DS,ST_CP
); 
    input       rst_n;
    input       clk;
    output      DS;
    output      SH_CP;
    output      ST_CP;
     wire   [7:0] seg ;
     wire   [7:0] sel_r;
     wire   [31:0]  disp_data;    
assign      disp_data= 32'h00000000;//需要显示的数字或字母
    hc59 hc59 (
    .clk            (clk),
    .rst_n          (rst_n),
    .DS             (DS),
    .sel_r          (sel_r),
    .seg            (seg),
    .SH_CP          (SH_CP),
    .ST_CP          (ST_CP)
    );
    
    hx8 hx8(
    .clk             (clk),
    .sel_r          (sel_r),
    .seg            (seg),
    .disp_data       (disp_data ),    
    .rst_n           (rst_n)    
    );
endmodule

以上就是整个工程的讲解过程及代码部分。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值