数码管显示(静态与动态)

news2024/11/25 0:51:36

文章目录

  • 一、数码管简介
  • 二、数码管连接方式
    • 2.1 共阴极
    • 2.2 共阳极
    • 2.3 数码管真值表
  • 三、数码管驱动方式
    • 3.1 静态显示
    • 3.2 动态显示
    • 四、Cyclone IV数码管原理图
  • 五、模块代码
  • 六、引脚分配
  • 七、动态显示
  • 八、引脚分配


一、数码管简介

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

二、数码管连接方式

在这里插入图片描述
图4. 数码管连接方式

2.1 共阴极

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

2.2 共阳极

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

2.3 数码管真值表

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

在这里插入图片描述

三、数码管驱动方式

3.1 静态显示

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

3.2 动态显示

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

四、Cyclone IV数码管原理图

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

五、模块代码

创建time_count文件,并编写 time_count模块代码。

module time_count(
	input	     clk  ,//50MHz时钟信号
	input		 rst_n,//复位信号
	output	reg  flag//一个时钟周期的脉冲信号
);
parameter	 MAX_NUM = 25'd25_000_000;//计数器最大计数值
reg  [24:0]	 cnt                     ; //时钟分频计数器

//计数器对时钟计数,每0.5s,输出一个时钟周期脉冲信号
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin//按复位时
		flag <= 1'b0;//信号为0
		cnt <= 25'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 <= 25'd0;
	end
end
endmodule 

创建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 

创建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 

六、引脚分配

在这里插入图片描述

七、动态显示

计数器模块

module counter(
	input wire 		  clk  ,//时钟
	input wire 		  rst_n,//复位信号
	
	output reg [4:0] hour  ,//小时
	output reg [5:0] min   ,//分钟
	output reg [5:0] sec//秒
	
);

parameter MAX_NUM = 26'd49_999_999;//1s
parameter TOTAL_SEC = 17'd86399   ;//24x60x60s
reg [25:0] cnt_sec ;//秒计数器
reg [16:0] cnt_time;//计时器

//计时1s秒钟模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_sec <= 26'd0;
	end 
	else if(cnt_sec == MAX_NUM)begin
		cnt_sec <= 26'd0;
	end 
	else begin
		cnt_sec <= cnt_sec + 1'd1;
	end 
end 

//时间模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_time <= 17'd0;
	end 
	else if(cnt_time == TOTAL_SEC && cnt_sec == MAX_NUM)begin
		cnt_time <= 17'd0;
	end 
	else if(cnt_sec == MAX_NUM)begin
		cnt_time <= cnt_time + 1'd1;
	end 
	else begin
		cnt_time <= cnt_time;
	end 
end 

//取出时分秒模块
always@(*)begin
	hour = cnt_time / 12'd3600          ;//小时
	min  = (cnt_time % 12'd3600) / 6'd60;//分钟
	sec  = (cnt_time % 12'd3600) % 6'd60;//秒
end 
endmodule 

数码管驱动模块

module seg_driver(
	input wire 			clk	 ,//时钟
	input wire 			rst_n,//复位信号
	input wire [4:0] 	hour ,//小时
	input wire [5:0] 	min	 ,//分钟
	input wire [5:0] 	sec	 ,//秒
	
	output reg [5:0]	seg_sel,
	output reg [7:0] 	seg_ment
);

parameter CNT_20US = 10'd999;//20微秒
wire [3:0] 	sec_low  ;//秒的低位
wire [2:0] 	sec_high ;//秒的高位
wire [3:0] 	min_low  ;//分钟的低位
wire [2:0] 	min_high ;//分钟的高位
wire [1:0] 	hour_low ;//小时的低位
wire [1:0] 	hour_high;//小时的高位
reg  [9:0]	cnt		 ;//计数器,计20us时间
reg  [3:0] 	number	 ;//显示时分秒寄存器

//计时模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt <= 10'd0; 	
	end 
	else if(cnt == CNT_20US)begin
		cnt <= 10'd0;
	end 
	else begin
		cnt <= cnt + 1'd1;
	end 
end 

//位选信号切换模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		seg_sel <= 6'b011111;//初始化第一个数码管亮
	end 
	else if(cnt == CNT_20US)begin
		seg_sel <= {seg_sel[0],seg_sel[5:1]};//每隔20us进行位移操作
	end 
	else begin
		seg_sel <= seg_sel;//其他时间保持不变
	end 
end 

//位选信号译码模块
always@(*)begin
	case(seg_sel)
		6'b011111: number = sec_low  ;//秒的低位给第一个数码管显示
		6'b101111: number = sec_high ;//秒的高位给第二个数码管显示
		6'b110111: number = min_low  ;//分钟的低位给第三个数码管显示
		6'b111011: number = min_high ;//分钟的高位给第四个数码管显示
		6'b111101: number = hour_low ;//小时的低位给第五个数码管显示
		6'b111110: number = hour_high;//小时的高位给第六个数码管显示
		default:   number = sec_low  ;
	endcase 
end 

//段选信号译码模块
always@(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		seg_ment <= 8'b1100_0000;//初始化显示0
	end
	else begin
		case(number)
			4'd0:		seg_ment <= 8'b1100_0000;//数码管显示0
			4'd1:		seg_ment <= 8'b1111_1001;//数码管显示1
			4'd2: 		seg_ment <= 8'b1010_0100;//数码管显示2
			4'd3: 		seg_ment <= 8'b1011_0000;//数码管显示3
			4'd4: 		seg_ment <= 8'b1001_1001;//数码管显示4
			4'd5: 		seg_ment <= 8'b1001_0010;//数码管显示5
			4'd6: 		seg_ment <= 8'b1000_0010;//数码管显示6
			4'd7: 		seg_ment <= 8'b1111_1000;//数码管显示7
			4'd8: 		seg_ment <= 8'b1000_0000;//数码管显示8
			4'd9:    	seg_ment <= 8'b1001_0000;//数码管显示9
			default:	seg_ment <= 8'b1100_0000;//数码管显示0
		endcase 
	end 
end 

assign sec_low   = sec % 4'd10 ;//秒的低位如59秒--->9
assign sec_high  = sec / 4'd10 ;//秒的高位如59秒--->5
assign min_low   = min % 4'd10 ;//分钟的低位如59--->9
assign min_high  = min / 4'd10 ;//分钟的高位如59--->5
assign hour_low  = hour % 4'd10;//小时的低位如23--->3
assign hour_high = hour / 4'd10;//小时的高位如23--->2
endmodule 

顶层模块

module digital_clock(
	input wire 			clk  ,//时钟
	input wire 			rst_n,//复位信号
	
	output wire [5:0] seg_sel,//数码管位选信号
	output wire [7:0] seg_ment//数码管段选信号

);
parameter MAX_NUM = 26'd49_999_999;//1s
parameter TOTAL_SEC = 17'd86399   ;//60x24x24s
parameter CNT_20US = 10'd999     ;//20us
wire [4:0] 	hour;//小时
wire [5:0] 	min ;//分钟
wire [5:0] 	sec ;//秒	

//实例化计数器模块
counter#(.MAX_NUM(MAX_NUM),
		.TOTAL_SEC(TOTAL_SEC)) u_counter(
.clk  	(clk)  ,
.rst_n	(rst_n),
          
.hour 	(hour) ,
.min	(min)  ,
.sec	(sec)
	
);

//实例化数码管驱动模块
seg_driver#(.CNT_20US(CNT_20US)) u_seg_driver(
.clk	 	(clk)    ,
.rst_n		(rst_n)  ,
.hour	 	(hour)   ,
.min	 	(min)    ,
.sec	 	(sec)    ,
          
.seg_sel	(seg_sel),
.seg_ment	(seg_ment)
);

endmodule 

八、引脚分配

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/760747.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么不推荐在头文件中直接定义函数?

1. 函数的分文件编写 在C中&#xff0c;函数的分文件编写是一种让代码结构更加清晰的方法&#xff0c;通常可以分为以下几个步骤&#xff1a; 创建后缀名为 .h 的头文件&#xff0c;在头文件中写函数的声明&#xff0c;以及可能用到的其他头文件或命名空间创建后缀名为 .cpp …

ES6迭代器、Set、Map集合和async异步函数

目录 迭代器 Iterator 的作用 Iterator 的遍历过程 Set Map集合 map和对象区别? async异步函数 迭代器 迭代器&#xff08;Iterator&#xff09;就是这样一种机制。它是一种接口&#xff0c;为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口&…

自动化运维工具——Ansible学习(二)

目录 一、handlers和notify结合使用触发条件 1.新建httpd.yml文件 2.复制配置文件到ansible的files目录中 3.卸载被控机已安装的httpd 4.执行httpd.yml脚本 5.更改httpd.conf配置文件 6.使用handlers 7.重新执行httpd.yml脚本 8.检查被控机的端口号是否改变 9.handle…

矩阵乘法的硬件加速

矩阵乘法的硬件加速 这里的硬件加速是指&#xff0c;如果依靠算法&#xff0c;可以通过减少访存次数来加速。可以将数据预取到cache来减少访存次数。 矩阵相乘最简单的实现 寄存器平铺矩阵乘法 将矩阵划分成多个小的矩阵块&#xff0c;小的矩阵块可以存放在寄存器中&#xff0…

QT开发技巧之嵌入式linux QT的QCombobox显示空白的问题

1.问题 开发平台&#xff1a;imx6ull qt版本&#xff1a;5.12.9 在嵌入式linux上运行的qt&#xff0c;QCombobox显示空白&#xff0c;不能显示其中的文本内容 2.解决办法 选中QCombobox&#xff0c;在属性栏中将foucsPolicy由WheelFocus改成NoFocus就好了

用户、角色、权限、菜单--数据库设计

用户角色关联表--user_role id-------------------主键 user_id------------用户ID role_id-------------角色ID create_time------创建时间 is_deleted--------状态&#xff08;0&#xff1a;未删除 1&#xff1a;删除&#xff09; 角色权限关联表--role_permission id------…

【PHP面试题50】Redis的主从复制实现原理是怎么样的?如何保证数据一致性?数据延迟又该如何处理?

文章目录 一、前言二、主从复制的基本原理三、数据一致性的保证四、数据延迟的处理四、总结 一、前言 本文已收录于PHP全栈系列专栏&#xff1a;PHP面试专区。 计划将全覆盖PHP开发领域所有的面试题&#xff0c;对标资深工程师/架构师序列&#xff0c;欢迎大家提前关注锁定。 R…

OpenCv算子

目录 一、索贝尔(sobel)算子 二、沙尔(Scharr)算子 三、拉普拉斯算子 一、索贝尔(sobel)算子 边缘的定义: 边缘是像素值发生跃迁的位置&#xff0c;是图像的显著特征之一&#xff0c;在图像特征提取、对象检测、模式识别等方面都有重要的作用。 sobel算子对图像求一阶导数。…

【V8】【1. 内存布局、隐藏类Hidden Class】

JavaScript 中的对象是由一组组属性和值的集合。JavaScript 对象像一个字典&#xff0c;字符串作为键名&#xff0c;任意对象可以作为键值&#xff0c;可以通过键名读写键值。 在 ECMAScript 规范中定义了数字属性应该按照索引值大小升序排列&#xff0c;字符串属性根据创建时…

python将dataframe数据导入MongoDB非关系型数据库

文章目录 pymongo连接新建数据库和集合pandas导入数据插入数据数据查看 pymongo连接 import pymongo client pymongo.MongoClient("mongodb://localhost:27017/") dblist client.list_database_names() for db in dblist:print(db) #查看已有数据库admin bilibil…

apply()函数--Pandas

1. DataFrame.apply()函数 1.1 函数功能 对DataFrame沿着指定轴运用函数。 函数接收到的对象是Series对象&#xff0c;它们的索引可以是DataFrame的行索引&#xff08;axis0&#xff09;或列索引&#xff08;axis1&#xff09;。结果为Series或DataFrame。 1.2 函数语法 Da…

java基础浮点类型

目录 1&#xff1a;float类型和double类型的定义 2&#xff1a;二者的范围和精度 3&#xff1a;float类型详解 3.1&#xff1a;整数位10进制转换为2进制 3.2&#xff1a;小数位10进制转换为2进制 3.3&#xff1a;把二进制放到浮点类型中 3.4&#xff1a;精度损失 4&…

手动下载composer项目放在vendor目录下并加载

比如添加easywechat。 说是手动&#xff0c;其实半手动。 到GitHub或gitee下载 1、下载后放在项目根目录下的vendor文件夹 2、在项目根目录的文件composer.json文件添加一段 "autoload": {"psr-4": {"EasyWeChat\\": "vendor/overtrue/wech…

9.带你入门matlab假设检验(matlab程序)

1.简述 函数 ztest 格式 h ztest(x,m,sigma) % x为正态总体的样本&#xff0c;m为均值μ0&#xff0c;sigma为标准差&#xff0c;显著性水平为0.05(默认值) h ztest(x,m,sigma,alpha) %显著性水平为alpha [h,sig,ci,zval] ztest(x,m,sigma,alpha,tail) %sig为观察…

3.5 Bootstrap 输入框组

文章目录 Bootstrap 输入框组基本的输入框组输入框组的大小复选框和单选插件按钮插件带有下拉菜单的按钮分割的下拉菜单按钮 Bootstrap 输入框组 本章将讲解 Bootstrap 支持的另一个特性&#xff0c;输入框组。输入框组扩展自 表单控件。使用输入框组&#xff0c;您可以很容易地…

SpringCloud Alibaba——Ribbon底层怎样实现不同服务的不同配置

目录 一、Ribbon底层怎样实现不同服务的不同配置二、源码角度分析 一、Ribbon底层怎样实现不同服务的不同配置 为不同服务创建不同的spring上下文&#xff0c;不同的spring上下文中存放对应这个服务所有的配置。 二、源码角度分析 SpringClientFactory中可以获取到所有ribbon…

自动化运维工具——Ansible学习(一)

目录 一、运维自动化发展历程及技术应用 (二)程序发布相关知识 (三)常用的自动化运维工具 二、Ansible入门 (一)Ansible发展史 (二)特点 (三)Ansible架构 (四)工作原理 (五)Ansible主要组成部分 (六) 安装步骤 1.各种安装方法与命令 (1)rpm包安装&#xff1a;EPEL源…

一篇文章让你学会Elasticsearch中的查询

还是惯例&#xff0c;开头先放章节目录&#xff0c;如果有帮到你的地方&#xff0c;欢迎点赞关注转发&#xff0c;如有错误&#xff0c;欢迎指出&#xff0c;不胜感激 一、环境初始化 version: 3.8 services:cerebro:image: lmenezes/cerebro:0.8.3container_name: cerebroport…

ylb-支付服务pay

总览&#xff1a; 在pay模块util包下&#xff0c;创建签名工具类Pkipair和http工具类HttpUtil&#xff1a; package com.bjpowernode.util;import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.securi…

centos7 docker 安装sql server 2019

contos7安装sql server docker最低1.8或更高 卸载旧的docker sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 装docker依赖包 #安装所需资源包 sudo yum install -…