4 位数码管显示控制器设计

数码管动态扫描显示

  • 数码管是最直观的数字显示设备, 几乎每个嵌入式开发板上都有.
  • 本实验我们设计一个 4 位数码管控制器, CPU 只需要写入要显示的数值, 硬件自动完成扫描显示.

七段数码管原理

数码管长什么样?

     ──a──
    │     │
    f     b
    │     │
     ──g──
    │     │
    e     c
    │     │
     ──d──   ● dp

7 个笔段 (a-g) 加 1 个小数点 (dp), 通过组合可以显示 0-9 和 A-F.

共阴极 vs 共阳极

类型 公共端 点亮方式
共阴极 接地 GND 笔段输出高电平点亮
共阳极 接电源 VCC 笔段输出低电平点亮

本实验假设使用共阴极数码管.

字形编码表

共阴极数码管的字形编码表如下所示。举个简单的例子,如果我们要显示数字 "5", 就需要点亮 a, c, d, f, g 五个笔段:

数字 g f e d c b a 十六进制
0 0 1 1 1 1 1 1 0x3F
1 0 0 0 0 1 1 0 0x06
2 1 0 1 1 0 1 1 0x5B
3 1 0 0 1 1 1 1 0x4F
4 1 1 0 0 1 1 0 0x66
5 1 1 0 1 1 0 1 0x6D
6 1 1 1 1 1 0 1 0x7D
7 0 0 0 0 1 1 1 0x07
8 1 1 1 1 1 1 1 0x7F
9 1 1 0 1 1 1 1 0x6F
A 1 1 1 0 1 1 1 0x77
b 1 1 1 1 1 0 0 0x7C
C 0 1 1 1 0 0 1 0x39
d 1 0 1 1 1 1 0 0x5E
E 1 1 1 1 0 0 1 0x79
F 1 1 1 0 0 0 1 0x71

动态扫描原理

为什么不能静态显示?

如果 4 位数码管都用静态显示:

  • 每位需要 8 根线 (7 段 + 1 小数点)
  • 4 位就需要 32 根线!
  • IO 资源浪费太严重

动态扫描的思路

利用人眼的"视觉暂留"效应:

  1. 第 1ms: 只点亮第 1 位, 显示它的内容
  2. 第 2ms: 只点亮第 2 位, 显示它的内容
  3. 第 3ms: 只点亮第 3 位, 显示它的内容
  4. 第 4ms: 只点亮第 4 位, 显示它的内容
  5. 循环往复...

只要扫描够快 (>50Hz), 人眼就感觉 4 位同时亮着!

时间轴 ──────────────────────────────────────►

位选:   DIG0    DIG1    DIG2    DIG3    DIG0 ...
        ┌──┐    ┌──┐    ┌──┐    ┌──┐    ┌──┐
        │  │    │  │    │  │    │  │    │  │
      ──┘  └────┘  └────┘  └────┘  └────┘  └──

段选:   显示0   显示1   显示2   显示3   显示0 ...

        ├─2ms─┤
        ├──────────── 8ms 一个周期 ────────────┤

硬件模块设计

数码管硬件代码组成

AHBlite_Segdisp.v

  • 功能: 数码管控制器的 AHB 接口包装器,负责接收总线上写入的数据并传给显示核心。

Segdisp.v

  • 功能: 数码管动态扫描控制器。
  • 子模块:
    • clk_division.v: 分频产生扫描时钟 (约 1ms)。
    • counter.v: 位选循环计数器。
    • Mux.v: 多路复用器,根据当前位选择显示数据。
    • seg_sel_decoder.v: 位选译码器。
    • seg_led_decoder.v: 段选译码器(7 段编码和小数点)。

必读通知

在数码管显示设计部分,我们同样延续前面实验的练习方式,请动手补全以下 Verilog 文件:

  1. clk_division.v

    • 任务: 实现扫描时钟分频逻辑。
    • 说明: 定义计数器与输出寄存器,按参数 DIVCLK_CNTMAX(24_999)分频,产生约 1 ms 的扫描时钟。
  2. Segdisp.v

    • 任务: 实例化关键子模块。
      • 说明: 在提示位置实例化 clk_divisioncounter,并确保扫描位选、数据移位等路径连通。
  3. seg_led_decoder.v

    • 任务: 完成 4-bit 到 7 段 + dp 的译码表。
    • 说明: 根据本章节中的字形编码表,补齐 case 语句的所有分支,default 建议输出 8'h00 防止乱码。

仿真与调试

由于本节没有配套的自动化 Testbench 激励文件,建议同学亲自编写简单的激励波形,尝试在仿真环境里对 Segdisp 模块进行功能验证,有助于理解动态扫描的节奏与时序细节。

仿真要点

  1. 观察 dig_sel 是否在 0-1-2-3 之间循环
  2. 观察 dig_out 是否正确输出位选信号
  3. 观察 seg_out 是否正确输出对应的字形码
  4. 测量扫描周期是否约为 8ms (4 位 × 2ms)

在实际下板测试时:

  • 如果数码管闪烁, 说明扫描频率太低
  • 如果某一位特别亮, 说明那一位的点亮时间比其他位长
  • 如果显示乱码, 检查字形编码是否正确

思考题

  1. 如何实现数码管亮度调节? (提示: PWM)
  2. 如果要显示 "HELP" 这样的字母, 译码表需要怎么扩展?
  3. 扫描频率设为多少比较合适? 太高会有什么问题?

results matching ""

    No results matching ""