**这是本文档旧的修订版!**

STEP FPGA驱动基于74HC595的数码管模块

本节将和大家一起使用FPGA驱动底板上的6位数码管实现动态显示。

====硬件说明====

在前面之前的入门教程中 数码管独立显示 章节已为大家介绍了数码管独立显示的相关内容,关于独立显示这里就不在赘述。我们的底板上有6位数码管,根据驱动方法不同,有以下比较:
独立显示:控制每个数码管至少需要8个I/O口控制,6位数码管就需要6*8 = 48根信号线才能分别显示。独立显示实现简单,但是需要大量的信号线。
扫描显示:将每位数码管的同一段选信号连接在一起,这样我们就只需要8根段选信号和6根位选信号,共计14根信号。扫描显示可以有效节约I/O口资源,实现起来稍显复杂。
我们小脚丫底板上使用的6位共阴极数码管,分析扫描显示的原理如下:
当某一时刻,FPGA控制8根公共的段选接口输出数字1对应的数码管字库数据8'h06(DP=0、G=0、F=0、E=0、D=0、C=1、B=1、A=0)时,同时控制6位数码管只有第1位使能(DIG1=0、DIG2=1、DIG3=1、DIG4=1、DIG5=1、DIG6=1)这样我们会看到第1位数码管显示数字1,其余5位数码管不显示,如果不明白可以参考入门教程中实验四: 数码管独立显示 章节
按照扫描的方式,一共分为6个时刻,段选端口分别对应输出6位数码管需要显示的字库数据,位选端口保持每个时刻只有1位数码管处于使能状态,6个时刻依次循环,当扫描频率足够高(例如当扫描频率等于100Hz)时,则在人眼看到的数码管显示就是连续的,我们看到的就是6个不同的数字。
上面为大家介绍了数码管的独立显示和扫描显示两种方法,扫描显示的方式使用了14个I/O口控制,相对于简单的处理器来讲14个I/O口也是非常多了,这里我们又使用了一款常见的驱动芯片74HC595,下面我们一起了解一下:
74HC595是较为常用的串行转并行的芯片,内部集成了一个8位移位寄存器、一个存储器和8个三态缓冲输出。在最简单的情况下我们只需要控制3根引脚输入得到8根引脚并行输出信号,而且可以级联使用,我们使用3个I/O口控制两个级联的74HC595芯片,产生16路并行输出,连接到扫描显示的6位数码管上,可以轻松完成数码管驱动任务。

不同的IC厂家都可以生产74HC595芯片,功能都是一样的,然而不同厂家的芯片手册对于管脚的命名会存在差异,管脚顺序相同,大家可以对应识别 上图是本设计中74HC595芯片的硬件电路连接,参考74HC595数据手册了解其具体用法,下图中我们了解到OE#(G#)和MR#(SCLR#)信号分别为输出使能(低电平输出)和复位管脚(低电平复位),OE#(G#)我们接GND让芯片输出使能,MR#(SCLR#)我们接VCC让芯片的移位寄存器永远不复位,如此FPGA只需要控制SHCP(SCK)、STCP(RCK)和DS(SER)即可。
74hc595引脚功能
74hc595逻辑图
74hc595时序图
数码管驱动程序框图

====Verilog代码====

// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Module: Array_KeyBoard
// 
// Author: Step
// 
// Description: Array_KeyBoard
// 
// Web: www.stepfapga.com
//
// --------------------------------------------------------------------
// Code Revision History :
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.0     |2015/11/11   |Initial ver
// --------------------------------------------------------------------
module Array_KeyBoard #
(
	parameter			NUM_FOR_200HZ = 60000	//定义计数器cnt的计数范围,例化时可更改
)
(
	input					clk_in,			//系统时钟
	input					rst_n_in,		//系统复位,低有效
	input			[3:0]	col,			//矩阵按键列接口
	output	reg		[3:0]	row,			//矩阵按键行接口
	output	reg		[15:0]	key_out			//消抖后的信号
);
/*
因使用4x4矩阵按键,通过扫描方法实现,所以这里使用状态机实现,共分为4种状态
在其中的某一状态时间里,对应的4个按键相当于独立按键,可按独立按键的周期采样法采样
周期采样时每隔20ms采样一次,对应这里状态机每隔20ms循环一次,每个状态对应5ms时间
对矩阵按键实现原理不明白的,请去了解矩阵按键实现原理
*/	
	localparam			STATE0 = 2'b00;
	localparam			STATE1 = 2'b01;
	localparam			STATE2 = 2'b10;
	localparam			STATE3 = 2'b11;
 
	//计数器计数分频实现5ms周期信号clk_200hz
	reg		[15:0]		cnt;
	reg					clk_200hz;
	always@(posedge clk_in or negedge rst_n_in) begin
		if(!rst_n_in) begin		//复位时计数器cnt清零,clk_200hz信号起始电平为低电平
			cnt <= 16'd0;
			clk_200hz <= 1'b0;
		end else begin
			if(cnt >= ((NUM_FOR_200HZ>>1) - 1)) begin	//数字逻辑中右移1位相当于除2
				cnt <= 16'd0;
				clk_200hz <= ~clk_200hz;	//clk_200hz信号取反
			end else begin
				cnt <= cnt + 1'b1;
				clk_200hz <= clk_200hz;
			end
		end
	end
 
	reg		[1:0]		c_state;
	//状态机根据clk_200hz信号在4个状态间循环,每个状态对矩阵按键的行接口单行有效
	always@(posedge clk_200hz or negedge rst_n_in) begin
		if(!rst_n_in) begin
			c_state <= STATE0;
			row <= 4'b1110;
		end else begin
			case(c_state)
				STATE0: begin c_state <= STATE1; row <= 4'b1101; end	//状态c_state跳转及对应状态下矩阵按键的row输出
				STATE1: begin c_state <= STATE2; row <= 4'b1011; end
				STATE2: begin c_state <= STATE3; row <= 4'b0111; end
				STATE3: begin c_state <= STATE0; row <= 4'b1110; end
				default:begin c_state <= STATE0; row <= 4'b1110; end
			endcase
		end
	end
 
	//因为每个状态中单行有效,通过对列接口的电平状态采样得到对应4个按键的状态,依次循环
	always@(negedge clk_200hz or negedge rst_n_in) begin
		if(!rst_n_in) begin
			key_out <= 16'hffff;
		end else begin
			case(c_state)
				STATE0:key_out[3:0] <= col;		//采集当前状态的列数据赋值给对应的寄存器位
				STATE1:key_out[7:4] <= col;
				STATE2:key_out[11:8] <= col;
				STATE3:key_out[15:12] <= col;
				default:key_out <= 16'hffff;
			endcase
		end
	end
 
endmodule



引脚分配


综合(synthesize)完成之后一定要配置FPGA的引脚到相应的外设,这样下载FPGA程序后才能达到我们想要的效果。
我们使用PCLK充当程序中的clkin,使用按键KEY1充当rstnin,col和row的引脚按照高低顺序分频,keyout可以分配给LED灯、三色灯、PMOD等FPGA控制输出的引脚上,通过观察或示波器测量检验设计

====小结====

本节主要为大家讲解了矩阵按键的工作原理及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。
如果你对Diamond软件的使用不了解,请参考这里:Diamond的使用

====相关资料====

后期会有链接到云盘