野火——数码管的静态显示学习笔记

        数码管是一种半导体发光器件,具有响应时间短、体积小、重量轻、寿命长等优点。本章节将介绍数码管的显示原理和驱动方式。

1. 理论学习

        数码管分为共阳极数码管共阴极数码管共阳极数码管就是把发光二极管的正极连接在一起作为一个引脚,负极分开。相反的,共阴极数码管就是把发光二极管的阴极连接在一起作为一个引脚,正极分开。这两者的区别在于,公共端是连接到地还是高电平,对于共阳极数码管需要给对应段低电平才会使其点亮,而对于共阴极数码管则需要给其高电平才会点亮。本次实验使用的是共阳极数码管,也就是说给对应段低电平才会被点亮。

 二进制段码右边为高位左边为低位。我们只要点亮相应的段码,就 能显示我们需要显示的内容。

        段式数码管工作方式有两种:静态显示动态显示。静态显示的特点是每个数码管的段选必须接一个 8 位数据线来显示字形,显示字形可一直保持,直到送入新字形码为止。 那么如果点亮 6 个码管是不是需要 48 位数据线去分别控制每一个码管的段选?当然这种方法也可以,但是其占用的 I/O 口较多,因此硬件电路比较复杂,成本较高,很少使用。

         由上图可以看到,我们将六个数码管的段选信号连接在一起,而位选(sel)独立控制,这样六个数码管接在一起就少了 8×5 个 I/O 口。这里对位选信号特别说明一下:由上图可以看到每一个数码管都有一个位选信号,而这个位选信号就控制着数码管的亮灭。这样我们就可以通过位选信号去控制数码管亮,而在同一时刻,位选选通的数码管上显示的字形是一样的,因为我们将 6 个数码管相对应的段选连在了一起,数码管的显示自然就相同了,数码管的这种显示方式即为静态显示。而如果要让每个数码管显示的值不同,我们要用到另外一种显示方式,即动态显示,将在下一章节给大家介绍。本章节先讲述 6 位共阳极数码管的静态显示,为下个章节的动态显示做准备。

2. 实验演练

2.1 实验目标

        设计一个这样的 6 位数码管静态显示:控制六位数码管让其以 000000、111111、222222 一直到 FFFFFF 循环显示。每个字符显示 0.5s 后变化。

图1 系统框图

2.2 波形图绘制

         cnt_wait:根据实验要求需要等待 0.5s 后显示的字符才发生变化。所以我们需要一个 0.5s 的循环计数器。我们输入的时钟频率是 50MHz,一个时钟周期的时间就是(1/50MHz)s , 也就是 20ns 。 所以我们计数器从0计到24_999_999即为0.5s (25000000*20ns)的时间。计到0.5s 后让其归0 开始下一个 0.5s 的计数。

        num:每个数码管显示的字符,初始显示为 0,六个就是 000000。当检测到跳转的标志信号为高时,让各个数码管显示的字符加 1。当加到 4’hF 时让其归 0 重新相加以此循环。

3. 代码编写

module seg_static
#(
    parameter CNT_WAIT_MAX = 25'd24_999_999   //计数器最大值(0.5s)
)
(
        input wire       sys_clk,
        input wire       sys_rst_n,
        
        output reg [5:0] sel,
        output reg [7:0] seg
);


//十六进制数显示编码
parameter SEG_0  = 8'b1100_0000,
          SEG_1  = 8'b1111_1001,
          SEG_2  = 8'b1010_0100,
          SEG_3  = 8'b1011_0000,
          SEG_4  = 8'b1001_1001,
          SEG_5  = 8'b1001_0010,
          SEG_6  = 8'b1000_0010,
          SEG_7  = 8'b1111_1000,
          SEG_8  = 8'b1000_0000,
          SEG_9  = 8'b1001_0000,
          SEG_A  = 8'b1000_1000,
          SEG_B  = 8'b1000_0011,
          SEG_C  = 8'b1100_0110,
          SEG_D  = 8'b1010_0001,
          SEG_E  = 8'b1000_0110,
          SEG_F  = 8'b1000_1110,
          IDLE = 8'b1111_1111;  //不显示状态
    
reg  [24:0] cnt;   //时钟分频计数器
reg         cnt_flag;   //数码管数值+1 标志信号
reg  [3:0]  data;        //数码管显示的十六进制数

//cnt_wait:0.5 秒计数
always @ (posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt <= 25'd0;
    else if (cnt == CNT_WAIT_MAX)
        cnt <= 25'd0;
    else 
        cnt <= cnt + 1'b1;
   
//add_flag:0.5s 拉高一个标志信号    
always @ (posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_flag <= 1'b0;
    else if (cnt == CNT_WAIT_MAX - 1)
        cnt_flag <= 1'b1;
    else 
        cnt_flag <= 1'b0;
    
//num:从 4'h0 加到 4'hf 循环    
always @ (posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        data <= 4'd0;
    else if ((cnt_flag == 1'b1)&&(data == 4'd15))
        data <= 4'd0;
    else if (cnt == CNT_WAIT_MAX)
        data <= data + 1'b1;
    else
        data <= data;

//sel:选中六个数码管
always @ (posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        sel <= 6'b000_000;
    else 
        sel <= 6'b111_111;

//给要显示的值编码
always @ (posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg <= SEG_0;
    else if (cnt_flag == 1'b1)  
        case(data)
           4'd0 :seg <= SEG_0 ;
           4'd1 :seg <= SEG_1 ;
           4'd2 :seg <= SEG_2 ;
           4'd3 :seg <= SEG_3 ;
           4'd4 :seg <= SEG_4 ;
           4'd5 :seg <= SEG_5 ;
           4'd6 :seg <= SEG_6 ;
           4'd7 :seg <= SEG_7 ;
           4'd8 :seg <= SEG_8 ;
           4'd9 :seg <= SEG_9 ;
           4'd10:seg <= SEG_A ;
           4'd11:seg <= SEG_B ;
           4'd12:seg <= SEG_C ;
           4'd13:seg <= SEG_D ;
           4'd14:seg <= SEG_E ;
           4'd15:seg <= SEG_F ;
        default:seg <= IDLE;
        endcase

endmodule

4. 仿真验证

`timescale 1ns / 1ns
module tb_seg_static();

reg     sys_clk;
reg     sys_rst_n;

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

initial 
        begin
            sys_clk = 1;
            sys_rst_n <= 0;
            #20
            sys_rst_n <= 1;
        end 

always #10 sys_clk = ~sys_clk;


seg_static 
#(
        .CNT_WAIT_MAX (25'd24)
)
seg_static_inst
(
        . sys_clk  (sys_clk  ),
        . sys_rst_n(sys_rst_n),
                    
        . sel      (sel      ),
        . seg      (seg      )
);

endmodule

5. 仿真波形分析

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值