前言

  上期课程中,我们使用了按键控制蜂鸣器。本期课程中,我们将学习Cyclone IV开发板上新的器件—数码管,也称作辉光管,是一种可以显示数字和其他信息的电子设备。


一、数码管简介

  数码管分七段数码管和八段数码管。七段和八段的区别在于,是否包括小数点DP(Digital Point)。本实验中使用的是数码管是8段数码管,每段是由led组成。通过控制每段led的亮灭,来控制数码管显示不同的数字和字母。
在这里插入图片描述

图1. 基本的数码管

  使用基本的数码管,可以构成不同型号的数码管,如图2所示。

在这里插入图片描述

图2. 不同型号数码管

在这里插入图片描述

图3. 正负、N型、米子型数码管
  使用N型数码管可以显示N,但是图1中基本的数码管,是没有办法显示N。

二、数码管连接方式

在这里插入图片描述

图4. 数码管连接方式

2.1 共阴极

  如图4中(b)所示,a—dp为输入端,全部在二极管的正极,二极管的负极共同接地。只有当a—dp输入为高电平的时候,二极管才导通,然后对应的段发亮。

2.2 共阳极

  如图4中(c)所示,a—dp为输入端,全部在二极管的负极,二极管的正极极共同接+5v(高电平)。只有当a—dp输入为低电平的时候,二极管才导通,然后对应的段发亮。

2.3 数码管真值表

  要显示不同的数字或者字母,就要选择点亮对应的led段。图5中对应的是cyclone IV开发板上数码管的真值表,可以通过查找该表来显示我们想要的数字或者字母。
在这里插入图片描述

图5. 数码管真值表

三、数码管驱动方式

3.1 静态显示

  在静态显示中,只考虑段选信号。在不同的时刻,各个位选信号保持不变,并根据真值表,选择要显示的数字或者字母。
在这里插入图片描述

图6. 数码管静态显示

3.2 动态显示

  在动态显示中,需要将位选信号考虑进来。在不同的时刻,各个位的位选信号随时改变,并根据真值表,选择显示不同的数字或者字母。
在这里插入图片描述

图7. 数码管动态显示

四、Cyclone IV数码管原理图

  Cyclone IV开发板中的数码管是共阳极,所以数码管中需要给低电平,对应的led段才会亮。位选信号原理图如图8所示,位选信号也是需要低电平有效。

在这里插入图片描述

图8. 数码管原理图

五、试验任务

5.1 任务描述

  六个数码管同时间隔0.5s显示0-f。要求:使用一个顶层模块,调用计时器模块和数码管静态显示模块。
在这里插入图片描述

图9. 模块关系示意图

5.2 系统框图

在这里插入图片描述

图10. 系统框图

5.3 模块原理图

在这里插入图片描述

图11. 模块原理图

5.4 模块代码

  1. 创建time_count文件,并编写 time_count模块代码。
module time_count(
	input	     clk  ,//50MHz时钟信号
	input		 rst_n,//复位信号
	output	reg  flag//一个时钟周期的脉冲信号
);
parameter	 MAX_NUM = 26'd25_000_000;//计数器最大计数值
reg  [25:0]	 cnt                     ; //时钟分频计数器

//计数器对时钟计数,每0.5s,输出一个时钟周期脉冲信号
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin//按复位时
		flag <= 1'b0;//信号为0
		cnt <= 26'd0;//计数器清零
	end
	else if(cnt < MAX_NUM - 1'b1)begin//如果没到时间
		flag <= 1'b0;//信号为0
		cnt <= cnt + 1'b1;//计数器正常累计+1
	end
	else	begin //否则到时间
		flag <= 1'b1;//信号变为1
		cnt <= 26'd0;
	end
end
endmodule 
  1. 创建seg_led_static文件,并编写 seg_led_static模块代码。
module	seg_led_static(
	input		      clk     ,
	input		      rst_n   ,
	input		      flag    ,
	output	reg [5:0] sel     ,//数码管位选信号
	output	reg [7:0] seg  //数码管段选信号
);
reg [3:0]	num;//数码管显示十六进制数
//控制数码管位选信号(注:低电平有效),选中所有的数码管
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)//如果按复位键0
		sel <= 6'b111111;//则默认为高电平
	else 
		sel <= 6'b000000;//否则为低电平
end
//每次通知信号flag到达时,数码管计数加1
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)
		num <=	4'h0;
	else if(flag)begin
		if(num < 4'hf)
			num <= num + 1'h1;
		else 
			num <= 4'h0;
	end
	else begin
		num <= num;
	end
end
//根据数码管显示的数值,控制段选信号
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)
		seg <= 8'b0;
	else begin
		case(num)//匹配16进制数
			4'h0:    seg <= 8'b1100_0000;//匹配到后参考共阳极真值表
	        4'h1:    seg <= 8'b1111_1001;
	        4'h2:    seg <= 8'b1010_0100;
	        4'h3:    seg <= 8'b1011_0000;
	        4'h4:    seg <= 8'b1001_1001;
	        4'h5:    seg <= 8'b1001_0010;
	        4'h6:    seg <= 8'b1000_0010;
	        4'h7:    seg <= 8'b1111_1000;
	        4'h8:    seg <= 8'b1000_0000;
	        4'h9:    seg <= 8'b1001_0000;
	        4'ha:    seg <= 8'b1000_1000;
	        4'hb:    seg <= 8'b1000_0011;
	        4'hc:    seg <= 8'b1100_0110;
	        4'hd:    seg <= 8'b1010_0001;
	        4'he:    seg <= 8'b1000_0110;
	        4'hf:     seg <= 8'b1000_1110;
	      	default : seg <= 8'b1100_0000;
		endcase
	end
end
endmodule 
  1. 创建top_seg_led_static文件,并编写top_seg_led_static模块代码:
module  top_seg_led_static(
	input	 	         clk  ,//50MHz系统时钟
	input		         rst_n,//系统复位信号(低有效)
	output		[5:0]	 sel  ,//数码管位选
	output	    [7:0]	 seg//数码管段选
);
 
parameter	MAX_NUM = 25'd25_000_000;// 数码管变化的时间间隔0.5s
wire		add_flag				;// 数码管变化的通知信号
//每隔0.5s产生一个时钟周期的脉冲信号
time_count #(.MAX_NUM(MAX_NUM)) u_time_count(
	.clk		(clk)  ,//50MHz时钟信号
	.rst_n		(rst_n),//复位信号
	.flag		(add_flag)//一个时钟周期的脉冲信号
);
//每当脉冲信号到达时,使数码管显示的数值加1
seg_led_static u_seg_led_static(
	.clk		(clk)	  ,
	.rst_n		(rst_n)	  ,
	.flag	    (add_flag),
	.sel		(sel)	  ,
	.seg		(seg)
);
endmodule 

5.5 测试代码

  创建top_seg_led_static_tb文件,并编写top_seg_led_static_tb测试模块代码:

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

reg   		 	clk    ;
reg  		 	rst_n  ;
wire    [5:0]	sel	   ;
wire 	[7:0]  	seg    ;
parameter CYCLE = 5'd20;//周期20ns
parameter MAX_NUM = 8'd100;//调小间隔时间100*20ns
always #(CYCLE/2) clk = ~clk;//翻转时钟

initial begin
	clk   = 0		   ;//时钟初始为0
	rst_n = 0		   ;//复位初始为0
	#(CYCLE)		   ;//延迟20ns
	rst_n = 1		   ;//复位置1
	#(16*MAX_NUM*CYCLE);//显示0-f时间
	$stop			   ;//停止
	
	
end 
top_seg_led_static#(.MAX_NUM (MAX_NUM))	u_top_seg_led_static(
.clk  	(clk)  ,//50MHz系统时钟
.rst_n	(rst_n),//系统复位信号(低有效)
.sel  	(sel)  ,//数码管位选
.seg	(seg)	//数码管段选
);
endmodule 

  注意:在测试代码中减少MAX_NUM的值,是为了减少仿真时间。

5.6 功能仿真

在这里插入图片描述

图12. 数码管静态显示仿真

六、引脚分配

在这里插入图片描述

图13. pin planner

元件管脚
SEL0A4
SEL1B4
SEL2A3
SEL3B3
SEL4A2
SEL5B1
DIG0B7
DIG1A8
DIG2A6
DIG3B5
DIG4B6
DIG5A7
DIG6B8
DIG7A5
CLOCK(时钟)E1
KEY1E15
表1. 引脚信息表

七、运行效果

数码管静态显示


总结

  本文介绍了数码管显示原理,数码管驱动方式等等,并通过代码实现了数码管静态显示。后期的作品将推出数码管动态显示,敬请期待!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐