栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

数码管动态显示

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数码管动态显示

文章目录
  • 前言
  • 一、数码管驱动
  • 二、数码管原理图
  • 三、实验任务
    • 3.1 任务描述
    • 3.2 系统框图
    • 3.3 模块原理图
    • 3.4 模块代码
    • 3.5 测试代码
    • 3.6 功能仿真
  • 四、引脚分配
  • 五、运行效果
  • 总结


前言

  上期课程中,我们学习了数码管,并通过代码实现了数码管静态显示。本期课程将延续上节课的内容,讲解数码管动态显示。


  提示:上节课已经学习了数码管,所以跳过数码管的讲解,直接从数码管驱动开始讲解。

一、数码管驱动

  由于段选信号共用,如图2所示,所以在同一时刻只能选择一个数码管,具体选择十位还是个位由位选信号决定。
  问:采用此种方式一次只能选择一种数码管,如何能够同时选择多种数码管?
  答:视觉暂留现象:物体快速移动时,在大脑中残留的影响会暂留一段时间。

图1. 数码管静态显示

图2. 数码管动态显示
二、数码管原理图

  原理图中除了数码管的段选信号,还有数码管未选信号。数码管位选和段选信号都是低电平有效。

图3. 数码管原理图

三、实验任务 3.1 任务描述

  通过使用6位数码管动态显示,实现一个计时器,每0.5秒变化一次,显示数字123456。模块设计如图4所示,一个顶层模块调用两个子模块,time_count是计时模块,sel_led_dynamic是数码管动态显示模块,top_sel_led_dynamic是顶层模块。

图4. 模块关系示意图
3.2 系统框图

图5. 系统框图
3.3 模块原理图

图6. 模块原理图
3.4 模块代码
  1. 创建time_count文件,并编写 time_count模块代码。
module time_count(
	input 	clk,//时钟频率,50MHz
	input	 	rst_n,//复位信号,下降沿有效
	
	output reg	flag//一个时钟周期的脉冲信号 	

);

parameter 	MAX_NUM = 25'd25_000_000;//0.5s时钟
reg [24:0]	cnt							;//时钟计数器

//计时器对时钟计数,每0.5s输出一个时钟周期脉冲信号
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin//按下复位信号时
		cnt <= 25'd0;//计数器设置位0
		flag <= 1'b0;//周期脉冲信号设置位0
	end 
	else if(cnt == MAX_NUM - 1'd1)begin//如果时间到
		cnt <= 25'd0;//计数器清零
		flag <= 1'b1;//周期脉冲信号输出为1,表示记慢一个周期
	end 
	else begin//如果时间没有到
		cnt <= cnt + 1'd1;//计数器不停计数
		flag <= 1'b0;//周期脉冲信号不变
	end 
end 


endmodule 
  1. 创建sel_led_dynamic文件,并编写 sel_led_dynamic模块代码。
module sel_led_dynamic(
	input 				clk  ,//时钟,50MHz
	input 				rst_n,//复位信号,下降沿有效
	input 				flag ,//周期信号
	
	output reg [5:0]	sel  ,//位选信号,六个数码管
	output reg [7:0]	seg  //段选信号,八段led

);

reg [2:0]	cstat ;//当前状态
reg [2:0]	nstat ;//下一个状态

//状态跳转
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin//下降沿有效
		cstat <= 3'd0;//当前状态置0
	end 
	else begin
		cstat <= nstat;//状态跳转
	end 
end 

//下一个状态判断(组合逻辑)
always@(*)begin

	case(cstat)
		3'd0:	if(flag)begin
					nstat = 3'd1;
				end 
				else begin
					nstat = 3'd0;
				end 
		3'd1: if(flag)begin
					nstat = 3'd2;
				end 
				else begin
					nstat = 3'd1;
				end 
		3'd2: if(flag)begin
					nstat = 3'd3;
				end 
				else begin
					nstat = 3'd2;
				end 
		3'd3: if(flag)begin
					nstat = 3'd4;
				end 
				else begin
					nstat = 3'd3;
				end 
		3'd4: if(flag)begin
					nstat = 3'd5;
				end 
				else begin
					nstat = 3'd4;
				end 
		3'd5: if(flag)begin
					nstat = 3'd0;
				end 
				else begin
					nstat = 3'd5;
				end 
	default:	nstat= 3'd1;
	endcase 
end 

reg [2:0] value;

//各个状态下的动作(可以组合也可以时序)
always@(*)begin
	if(!rst_n)begin
		value = 3'd0;
	end 
	else begin
		case(cstat)
			3'd0:   begin
							 sel = 6'b111_110;//选择最右边数码管。 sel低有效
							 value = 3'd1;
					end
			3'd1:   begin
							 sel = 6'b111_101;
							 value = 3'd2;
					end
			3'd2:   begin
							 sel = 6'b111_011;
							 value = 3'd3;
					end
			3'd3:   begin
							 sel = 6'b110_111;
							 value = 3'd4;
					end
			3'd4:   begin
							 sel = 6'b101_111;
							 value = 3'd5;
					end
			3'd5:   begin
							 sel = 6'b011_111;
							 value = 3'd6;
					end
		   default:		begin//默认就第1种情况
							 sel = 6'b111_110;
							 value = 3'd1;
					  	end
		endcase
	end 
end 

//数码管seg的输出
always@(*)begin
	if(!rst_n)begin
		 seg = 8'b00000000;
	end 
	else begin
		case(value)
			 3'd1:   seg = 8'b11111001;//根据数码管真值表查找
			 3'd2:   seg = 8'b10100100;
			 3'd3:   seg = 8'b10110000;
			 3'd4:   seg = 8'b10011001;
			 3'd5:   seg = 8'b10010010;
			 3'd6:   seg = 8'b10000010;
			 default :   seg = 8'b00000000;
		endcase
	end 
end 

endmodule 
  1. 创建top_sel_led_dynamic文件,并编写 top_sel_led_dynamic模块代码。
module top_sel_led_dynamic(
	input 			clk  ,//时钟信号,50MHz
	input 			rst_n,//复位信号,下降沿有效
	
	output [5:0]	sel  ,//位选信号
	output [7:0]	seg   //段选信号
);
wire flag;//wire连接两个模块
parameter	MAX_NUM = 25'd25_000_000;
time_count #(.MAX_NUM(MAX_NUM))	u_time_count(//实例化计时器模块
.clk		(clk)  ,//时钟频率,50MHz
.rst_n		(rst_n),//复位信号,下降沿有效

.flag		(flag)  //一个时钟周期的脉冲信号 	

);

sel_led_dynamic	u_sel_led_dynamic(//实例化数码管动态显示模块
.clk  	(clk)  ,//时钟信号
.rst_n	(rst_n),//复位信号,下降沿有效
.flag 	(flag) ,//周期信号

.sel  	(sel)  ,//位选信号,六个数码管
.seg  	(seg)   //段选信号,八段led

);
	
endmodule

3.5 测试代码

  创建top_sel_led_dynamic_tb测试文件,并编写 top_sel_led_dynamic_tb测试模块代码。

`timescale 1ns/1ns//单位1ns/精度1ns
module top_sel_led_dynamic_tb();

reg 			clk  ;
reg 			rst_n;
wire [5:0]		sel  ;
wire [7:0]		seg  ;

parameter CYCLE = 5'd20   ;//20ns
parameter MAX_NUM = 7'd100;//计时100x20ns

always #(CYCLE/2) clk = ~clk;//10ns翻转时钟

initial begin
	clk = 1'b0			  ;//时钟置0
	rst_n = 1'b0		  ;//复位信号置0
	#(CYCLE)			  ;//延迟20ns
	rst_n = 1'b1		  ;//复位信号置1
	#(MAX_NUM * CYCLE * 6);//观看六个数码管的情况
	$stop				  ;//停止
end 
top_sel_led_dynamic	#(.MAX_NUM(MAX_NUM)) u_top_sel_led_dynamic(
.clk  	(clk)  ,//时钟信号,50MHz
.rst_n	(rst_n),//复位信号,下降沿有效

.sel  	(sel)  ,//位选信号
.seg   	(seg)//段选信号
);
endmodule 
3.6 功能仿真

  在功能仿真中,与数码管静态显示不同的地方就是sel位选信号不停改变。seg是段选信号,不同的段选信号对应1—6个数字。

图7. 数码管动态显示仿真

四、引脚分配

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

五、运行效果

数码管动态显示


总结

  本期课程中,我们讲解了数码管动态显示的原理是改变数码管的位选信号。下期课程中将基于数码管动态显示,制作一个数字时钟。敬请期待!谢谢你的观看!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/698342.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号