文章目录
前言
数码管是一种现代常用的数码显示器件,其内部主要是由多个LED灯组构成,点亮相应的LED灯,就会呈现出不同的显示效果。数码管具有发光显示清晰,响应速度快、功耗低、体积小、寿命长、易于控制等一系列优点而被广泛应用与数显仪器仪表,数字控制设备等方面,例如我们常见的红绿灯倒计时装置就是利用数码管显示进行的。
数码管的学习非常的简单,我们常用的主要是8段数码管,其中7段数字显示和1段小数点显示,就可以基本满足我们日常显示的东西了。至于其他类型的数码管,大多用在专用设备上,在现实生活中并不常见。
一、数码管简介
数码管也叫做半导体数码管,它是将若干发光二极管按照一定图形排列并封装在一起的一种数码显示设备。数码管在我们日常生活中还是很常见的,但日常生活中常见的一般都是8段数码管,除此之外,还有±1型数码管,N型数码管以及米字型数码管等。
数码管可分为共阴极数码管和共阳极数码管,共阴极数码管就是将内部发光二极管的阴极全部连接在一起,共阳极数码管就是将内部发光二极管的阳极全部连接在一起。我们本次实验采用的是共阳极数码管,低电平有效。
二、程序设计
1、设计要求
① 根据FPGA开发板上的6位数码管以静态方式依次显示000000~FFFFFF,结束后循环显示,并让每个字符显示时间为0.5s。
② 修改上面的代码,让数码管轮流显示0、1、2、3、4、5,每个数字显示时间为0.5s。
2、程序代码
① 数码管全部显示000000~FFFFFF,间隔1.5s
/*========================================*
filename : seg_driver.v
description : 数码管显示实验
time : 2022-11-11
author : 卡夫卡与海
*========================================*/
module seg_driver(
input clk ,
input rst_n ,
output [5:0] sel ,//数码管位选(6位数码管)
output [7:0] seg_led //数码管段选(8段数码管)
);
//参数定义
parameter TIME_SHOW = 26'd25_000_000;//每个数字显示的时间 500ms
//parameter TIME_SHOW = 26'd25;//500ns (仿真用)
//根据数码管结构来写,0表示亮,1表示灭(共阳极数码管)
parameter ZERO = 8'b1100_0000,//最高位表示小数点Dp
ONE = 8'b1111_1001,
TWO = 8'b1010_0100,
THREE = 8'b1011_0000,
FOUR = 8'b1001_1001,
FIVE = 8'b1001_0010,
SIX = 8'b1000_0010,
SEVEN = 8'b1111_1000,
EIGHT = 8'b1000_0000,
NINE = 8'b1001_0000,
A = 8'b1000_1000,
B = 8'b1000_0011,
C = 8'b1100_0110,
D = 8'b1010_0001,
E = 8'b1000_0110,
F = 8'b1000_1110;
//信号定义
reg [25:0] cnt_500ms ;//每个数字显示500ms
wire add_cnt_500ms ;
wire end_cnt_500ms ;
reg [3:0] num ;//数码管显示的16进制数
reg [5:0] seg_sel ;//数码管位选
reg [7:0] seg_dig ;//数码管段选
//cnt_500ms
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_500ms <= 0;
end
else if(add_cnt_500ms)begin
if(end_cnt_500ms)begin
cnt_500ms <= 0;
end
else begin
cnt_500ms <= cnt_500ms + 1'b1;
end
end
end
assign add_cnt_500ms = 1'b1;
assign end_cnt_500ms = add_cnt_500ms && cnt_500ms == (TIME_SHOW - 1);
//num
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
num <= 0;
end
else if(end_cnt_500ms)begin
if(num < 4'hf)begin
num <= num + 1'b1;
end
else begin
num <= 4'h0;
end
end
else begin
num <= num;
end
end
//seg_sel 数码管位选,低电平有效,上电全部选通
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
seg_sel <= 6'b111111;
end
else begin
seg_sel <= 6'b000000;
end
end
//seg_dig
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
seg_dig <= 8'b0;
end
else begin
case(num)
4'h0 : seg_dig <= ZERO ;
4'h1 : seg_dig <= ONE ;
4'h2 : seg_dig <= TWO ;
4'h3 : seg_dig <= THREE;
4'h4 : seg_dig <= FOUR ;
4'h5 : seg_dig <= FIVE ;
4'h6 : seg_dig <= SIX ;
4'h7 : seg_dig <= SEVEN;
4'h8 : seg_dig <= EIGHT;
4'h9 : seg_dig <= NINE ;
4'ha : seg_dig <= A ;
4'hb : seg_dig <= B ;
4'hc : seg_dig <= C ;
4'hd : seg_dig <= D ;
4'he : seg_dig <= E ;
4'hf : seg_dig <= F ;
default : seg_dig <= ZERO;
endcase
end
end
//输出
assign sel = seg_sel;
assign seg_led = seg_dig;
endmodule
② 数码管依次显示0、1、2、3、4、5,显示时间0.5s
/*========================================*
filename : seg_driver.v
description : 数码管显示实验
time : 2022-11-11
author : 卡夫卡与海
*========================================*/
module seg_driver(
input clk ,
input rst_n ,
output [5:0] sel ,//数码管位选(6位数码管)
output [7:0] seg_led //数码管段选(8段数码管)
);
//参数定义
parameter TIME_SHOW = 26'd25_000_000;//每个数字显示的时间 500ms
//parameter TIME_SHOW = 26'd25;//500ns (仿真用)
//根据数码管结构来写,0表示亮,1表示灭(共阳极数码管)
parameter ZERO = 8'b1100_0000,//最高位表示小数点Dp
ONE = 8'b1111_1001,
TWO = 8'b1010_0100,
THREE = 8'b1011_0000,
FOUR = 8'b1001_1001,
FIVE = 8'b1001_0010,
SIX = 8'b1000_0010,
SEVEN = 8'b1111_1000,
EIGHT = 8'b1000_0000,
NINE = 8'b1001_0000,
A = 8'b1000_1000,
B = 8'b1000_0011,
C = 8'b1100_0110,
D = 8'b1010_0001,
E = 8'b1000_0110,
F = 8'b1000_1110;
//信号定义
reg [25:0] cnt_500ms ;//每个数字显示500ms
wire add_cnt_500ms ;
wire end_cnt_500ms ;
reg [3:0] num ;//数码管显示的16进制数
reg [5:0] seg_sel ;//数码管位选
reg [7:0] seg_dig ;//数码管段选
//cnt_500ms
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_500ms <= 0;
end
else if(add_cnt_500ms)begin
if(end_cnt_500ms)begin
cnt_500ms <= 0;
end
else begin
cnt_500ms <= cnt_500ms + 1'b1;
end
end
end
assign add_cnt_500ms = 1'b1;
assign end_cnt_500ms = add_cnt_500ms && cnt_500ms == (TIME_SHOW - 1);
//num
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
num <= 0;
end
else if(end_cnt_500ms)begin
if(num < 4'h6)begin
num <= num + 1'b1;
end
else begin
num <= 4'h0;
end
end
else begin
num <= num;
end
end
//seg_sel 数码管位选,低电平有效
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
seg_sel <= 6'b111110;
end
else if(end_cnt_500ms)begin
seg_sel <= {seg_sel[4:0],seg_sel[5]};
end
else begin
seg_sel <= seg_sel;
end
end
//seg_dig
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
seg_dig <= 8'b0;
end
else begin
case(num)
4'h0 : seg_dig <= ZERO ;
4'h1 : seg_dig <= ONE ;
4'h2 : seg_dig <= TWO ;
4'h3 : seg_dig <= THREE;
4'h4 : seg_dig <= FOUR ;
4'h5 : seg_dig <= FIVE ;
4'h6 : seg_dig <= SIX ;
4'h7 : seg_dig <= SEVEN;
4'h8 : seg_dig <= EIGHT;
4'h9 : seg_dig <= NINE ;
4'ha : seg_dig <= A ;
4'hb : seg_dig <= B ;
4'hc : seg_dig <= C ;
4'hd : seg_dig <= D ;
4'he : seg_dig <= E ;
4'hf : seg_dig <= F ;
default : seg_dig <= ZERO;
endcase
end
end
//输出
assign sel = seg_sel;
assign seg_led = seg_dig;
endmodule
总结
利用数码管还可以设计很多东西,比如计时器显示,数据显示等等。数码管设计首先需要清楚它的显示原理,这对编码顺序很重要,如果进行时间显示,还需要考虑小数点的位置,以及时间的时分秒的排列,达到多少需要进位操作等等。