FPGA驱动74HC595实现数码管显示的SPI通信实践

1. 项目概述

SPI驱动HC595点亮数码管是一个典型的数字电路与FPGA结合的实践项目。通过这个项目,我们能够掌握SPI通信协议的应用、74HC595芯片的驱动方法以及数码管的显示原理。这个项目虽然看起来简单,但涉及到的知识点非常丰富,包括时序分析、状态机设计、硬件接口控制等核心内容。

在实际工程应用中,这种通过串行接口扩展IO并驱动显示设备的方案非常常见。比如在工业控制面板、仪器仪表显示、消费电子产品等领域都有广泛应用。掌握这个项目,就等于掌握了一类嵌入式显示系统的通用解决方案。

2. 硬件设计分析

2.1 数码管显示原理

数码管分为共阳极和共阴极两种类型。本项目使用的是8位共阳极7段数码管。共阳极数码管的特点是所有LED的阳极连接在一起,通过控制阴极来点亮各个段。当74HC595的输出引脚为低电平时,对应的数码管段就会被点亮。

数码管的abcdefgdp分别对应数码管的7个段和小数点。通过不同的段组合,可以显示0-9的数字以及部分字母。例如:

  • 数字"0":a、b、c、d、e、f段亮
  • 数字"1":b、c段亮
  • 字母"A":a、b、c、e、f、g段亮

2.2 74HC595芯片特性

74HC595是一款8位串行输入、并行输出的移位寄存器,具有以下特点:

  1. 串行输入,并行输出
  2. 支持级联扩展
  3. 输出寄存器可以直接控制输出引脚
  4. 工作电压范围:2V-6V
  5. 最高时钟频率:25MHz@4.5V

芯片主要引脚功能:

  • SER:串行数据输入
  • SRCLK:移位寄存器时钟
  • RCLK:存储寄存器时钟
  • OE:输出使能(低电平有效)
  • SRCLR:移位寄存器清零(低电平有效)
  • QA-QH:并行输出

2.3 系统硬件连接

在本项目中,使用了两片74HC595芯片级联:

  • 第一片74HC595控制数码管的段选(显示内容)
  • 第二片74HC595控制数码管的位选(选择哪个数码管显示)

FPGA通过SPI接口(实际使用3线SPI)与74HC595通信:

  • MOSI:连接第一片74HC595的SER
  • SCLK:连接两片74HC595的SRCLK
  • 另外单独控制RCLK信号

3. 时序设计与分析

3.1 SPI通信时序

本项目采用SPI模式0(CPOL=0,CPHA=0):

  • 时钟空闲时为低电平
  • 数据在时钟上升沿采样
  • 数据在时钟下降沿变化

SPI时钟频率设计为250kHz,远低于74HC595的最高工作频率,确保稳定可靠。

3.2 74HC595驱动时序

74HC595的驱动需要满足以下时序要求:

  1. 数据建立时间(tsu):最小50ns
  2. 数据保持时间(th):最小5ns
  3. 时钟高电平时间(tWH):最小50ns
  4. 时钟低电平时间(tWL):最小50ns

在FPGA设计中,我们采用25MHz系统时钟,SPI时钟分频100倍得到250kHz:

  • 时钟周期:4μs
  • 高/低电平时间:2μs
  • 数据建立/保持时间:远大于规格要求

3.3 锁存信号时序

在发送完16位数据后,需要产生一个RCLK信号将数据从移位寄存器传输到输出寄存器。RCLK信号需要:

  1. 上升沿建立时间:最小70ns
  2. 脉冲宽度:最小50ns

在FPGA代码中,我们保持RCLK高电平10个系统时钟周期(400ns),完全满足时序要求。

4. FPGA程序设计

4.1 顶层模块设计

顶层模块主要功能:

  1. 数码管显示内容编码
  2. 动态扫描控制
  3. SPI数据传输控制
  4. 74HC595驱动信号生成
module ui_displed # ( parameter CLK_DIV = 100 ) ( input I_clk, //系统时钟 input I_rstn, //复位 output O_spi_sclk, //hc595移位时钟 output O_spi_mosi, //hc595串行数据 output O_hc595_lach, //hc595数据加载到输出寄存器 input [3:0]I_disp_led0, //Display LED0 //...其他数码管输入 );

4.2 数码管编码表

数码管显示需要将数字转换为对应的段码,使用查找表实现:

localparam DS_0 = 8'hC0, //数码管显示0 DS_1 = 8'hF9, //数码管显示1 //...其他数字和字母编码 DS_F = 8'h8E; //数码管显示F

4.3 动态扫描控制

动态扫描通过轮流点亮每个数码管实现,关键代码:

always @(posedge I_clk or negedge I_rstn) begin if(!I_rstn) disp_num <= 3'd0; else if(disp_en) disp_num <= disp_num + 1'b1; end always @(*) begin case(disp_num) 0: begin disp_led <= I_disp_led0; disp_led_n <= 8'b00001000; end //...其他数码管选择 7: begin disp_led <= I_disp_led7; disp_led_n <= 8'b00010000; end endcase end

4.4 SPI传输状态机

SPI传输采用状态机控制,确保正确的时序:

always @(posedge I_clk or negedge I_rstn) begin if(!I_rstn) begin spi_tx_req <= 1'b0; spi_tx_data <= 8'd0; lach595 <= 1'b0; M_S <= 4'd0; end else begin case(M_S) 0: if(!spi_busy) begin spi_tx_req <= 1'b1; spi_tx_data <= disp_led_n; M_S <= 4'd1; end //...其他状态 15: begin lach595 <= 1'b0; M_S <= 4'd0; end endcase end end

5. 关键问题与解决方案

5.1 数码管闪烁问题

现象:数码管显示不稳定,有闪烁感 原因:刷新频率过低 解决方案:

  1. 提高动态扫描频率(>50Hz)
  2. 确保每个数码管的点亮时间均匀
  3. 调整状态机时序,减少不必要的延迟

5.2 显示内容错乱

现象:显示的数字或字母不正确 可能原因:

  1. 段码表定义错误
  2. 数码管共阳/共阴配置错误
  3. 74HC595输出极性错误 排查步骤:
  4. 检查数码管类型(共阳/共阴)
  5. 验证段码表是否正确
  6. 用逻辑分析仪抓取SPI数据

5.3 级联芯片工作异常

现象:第二片74HC595无输出 可能原因:

  1. 级联连接错误
  2. 数据位数不足
  3. 锁存信号时序问题 解决方案:
  4. 检查SER到QH'的连接
  5. 确保发送足够的数据位(16位)
  6. 验证锁存信号时序

6. 性能优化建议

6.1 降低功耗设计

  1. 调整数码管亮度:
    • 减小点亮时间
    • 增加限流电阻
  2. 优化扫描频率:
    • 根据实际需要选择最低可用频率
  3. 使用PWM控制亮度

6.2 提高刷新速率

  1. 提高SPI时钟频率
  2. 优化状态机设计
  3. 使用硬件SPI控制器

6.3 扩展功能

  1. 增加数码管数量:
    • 通过级联更多74HC595实现
  2. 支持更多显示模式:
    • 滚动显示
    • 动画效果
  3. 添加亮度调节功能

7. 实际应用案例

7.1 工业计数器

使用6位数码管显示计数值:

  1. 通过3片74HC595驱动
  2. 支持0-999999计数
  3. 具有清零和保持功能

7.2 温度控制器

显示当前温度和设定值:

  1. 4位数码管显示
  2. 交替显示当前温度和设定值
  3. 支持小数点显示

7.3 电子时钟

实现时分秒显示:

  1. 6位数码管显示
  2. 冒号闪烁指示秒信号
  3. 支持12/24小时制切换

8. 进阶学习方向

  1. 多路复用优化:
    • 使用更少的IO驱动更多数码管
  2. 灰度控制:
    • 实现多级亮度显示
  3. 自定义字符:
    • 设计非标准字符显示
  4. 与其他接口整合:
    • 结合I2C、UART等接口
  5. 低功耗设计:
    • 休眠模式下的显示控制

这个项目虽然基础,但涉及的知识点非常丰富。通过深入理解每个环节的工作原理,可以掌握数字电路设计的核心思想。在实际开发中,建议先用仿真验证设计,再上板测试,这样可以大大提高开发效率。