1,了解数码管分类及结构
数码管是一种半导体发光器件,其基本单元是发光二极管。数码管按段数一般分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管(多一个小数点显示)。当然也还有一些其他类型的数码管如“N”形管、“米”字管以及工业科研领域用的 16 段管、24 段管等。如下图1:
以八段数码管为例,我们来看一下数码管的结构图,如下图2:
有图2可以知道八段数码管分为八段,a、b、c、d 、e、 f 、g 、dp,其中dp为小数点位,每一段都是一个发光二极管。数码管有共阳极和共阴极之分,实际就是把数码管的阳极或阴极连在同一个引脚上面,区别在于公共端是高电平合适低电平,共阳极需要给低电平才能点亮,共阴极则反之。
以共阳极数码管为例,0~f显示,如图3:
2,知道静动态数码管的区别及工作原理
以六位八段数码管为例进行介绍:
静态数码管:位选信号,高电平有效,六个数码管显示一样的数字,则称为静态数码管。
动态数码管:简单点,就是不同管可以同时显示不同的数字,其利用了人眼视觉暂留和数码管的余晖效应,人眼暂留:人眼在观察事物时,光信号传入大脑神经,需要经过一段短暂的时间,光的作用结束后,视觉影像并不会立即消失,这种残留的视觉称为“后像”,这个现象被称为“视觉暂留”。数码管的余晖效应:当停止向发光二极管供电时发光二极管仍能维持一段时间。人眼分辨有限,大概40ms以内的闪烁人眼不会观察到它的闪烁,由此可以实现动态数码管显示。
不管是静态数码管还是动态数码管,其都需要驱动,这里我使用的是74hc595驱动模块,它是一个8位串行输入、并行输出的位移缓存器。内部具有8位移位寄存器和一个存储器,具有三态输出功能,这里我们用到了两片74hc595,级联使用,完成数码管驱动。
3,源码
//hc595驱动
module hc595_ctrl(
input wire clk,
input wire rst_n,
input wire [5:0] sel,
input wire [7:0] seg,
output reg ds,
output wire oe,
output reg shcp,
output reg stcp
);
wire [13:0] data;
reg [1:0] cnt;
reg [3:0] cnt_bit;
assign data = {seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel[5:0]};
always @(posedge clk or negedge rst_n )
if(rst_n==1'b0)
cnt <= 2'd0;
else if(cnt==2'd3)
cnt <= 2'd0;
else
cnt <= cnt +1'b1;
always @(posedge clk or negedge rst_n )
if(rst_n==1'b0)
cnt_bit <= 4'd0;
else if((cnt_bit==4'd13)&&(cnt==2'd3))
cnt_bit <= 4'd0;
else if(cnt==2'd3)
cnt_bit <= cnt_bit +1'b1;
else
cnt_bit <= cnt_bit;
always @(posedge clk or negedge rst_n )
if(rst_n==1'b0)
ds <= 1'b0;
else
ds <= data[cnt_bit];
always @(posedge clk or negedge rst_n )
if(rst_n==1'b0)
shcp <= 1'b0;
else if(cnt==2'd2)
shcp <= 1'b1;
else if(cnt==2'd0)
shcp <= 1'b0;
else
shcp <= shcp;
always @(posedge clk or negedge rst_n )
if(rst_n==1'b0)
stcp <= 1'b0;
else if((cnt==2'd0)&&(cnt_bit==4'd0))
stcp <= 1'b1;
else if((cnt==2'd2)&&(cnt_bit==4'd0))
stcp <= 1'b0;
else
stcp <= stcp;
assign oe = 1'b0;
endmodule
//静态数码管控制
module seg_static
#( parameter CNT_MAX = 25'd24_999_999
)
(
input wire clk,
input wire rst_n,
output reg [5:0] sel,
output reg [7:0] seg
);
reg [24:0] cnt;
reg [3:0] data;
reg cnt_flag;
always @ (posedge clk or negedge rst_n)
if(rst_n==1'b0)
cnt <= 25'd0;
else if(cnt==CNT_MAX)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
always @ (posedge clk or negedge rst_n)
if(rst_n==1'b0)
data <= 4'd0;
else if((cnt_flag==1'b1)&&(data==4'd15))
data <= 4'd0;
else if(cnt_flag==1'b1)
data <= data + 1'b1;
else
data <= data;
always @ (posedge clk or negedge rst_n)
if(rst_n==1'b0)
cnt_flag <= 1'b0;
else if(cnt==CNT_MAX-1)
cnt_flag <= 1'b1;
else
cnt_flag <= 1'b0;
always @ (posedge clk or negedge rst_n)
if(rst_n==1'b0)
sel <= 6'b000_000;
else
sel <= 6'b111_111;
always @ (posedge clk or negedge rst_n)
if(rst_n==1'b0)
seg <= 8'hff;
else
case(data)
4'd0 : seg <= 8'hc0;
4'd1 : seg <= 8'hf9;
4'd2 : seg <= 8'ha4;
4'd3 : seg <= 8'hb0;
4'd4 : seg <= 8'h99;
4'd5 : seg <= 8'h92;
4'd6 : seg <= 8'h82;
4'd7 : seg <= 8'hf8;
4'd8 : seg <= 8'h80;
4'd9 : seg <= 8'h90;
4'd10 : seg <= 8'h88;
4'd11 : seg <= 8'h83;
4'd12 : seg <= 8'hc6;
4'd13 : seg <= 8'ha1;
4'd14 : seg <= 8'h86;
4'd15 : seg <= 8'h8e;
default : seg <= 8'hff;
endcase
endmodule
//动态数码管数据产生
module seg_en(
input wire clk,
input wire rst_n,
output reg [5:0] sel,
output reg [7:0] seg
);
parameter CNT1_MAX = 23'd4_999_999;
wire [7:0] seg_data[0:9];
assign seg_data[0] = 8'hc0;
assign seg_data[1] = 8'hf9;
assign seg_data[2] = 8'ha4;
assign seg_data[3] = 8'hb0;
assign seg_data[4] = 8'h99;
assign seg_data[5] = 8'h92;
assign seg_data[6] = 8'h82;
assign seg_data[7] = 8'hf8;
assign seg_data[8] = 8'h80;
assign seg_data[9] = 8'h90;
parameter CNT_MAX = 26'd49_999_999;
reg [22:0] cnt1;
reg [25:0] cnt;
reg [16:0] cnt2;
reg [3:0] unit;
reg [3:0] ten;
reg [3:0] hund;
reg [3:0] thod;
reg [3:0] t_thod;
reg [3:0] h_thod;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
cnt1 <= 23'd0;
else if(cnt1==CNT1_MAX)
cnt1 <= 23'd0;
else
cnt1 <= cnt1 +1'b1;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
cnt <= 26'd0;
else if(cnt==CNT_MAX)
cnt <= 26'd0;
else
cnt <= cnt +1'b1;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
cnt2 <= 17'd0;
else if((cnt==CNT_MAX)&&(cnt2==17'd99999))
cnt2 <= 17'd0;
else if(cnt==CNT_MAX)
cnt2 <= cnt2 +1'b1;
else
cnt2 <= cnt2;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
unit <= 4'd0;
else if((cnt1==CNT1_MAX)&&(unit==4'd9))
unit <= 4'd0;
else if(cnt1==CNT1_MAX)
unit <= unit +1'b1;
else
unit <= unit;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
ten <= 4'd0;
else if((cnt1==CNT1_MAX)&&(unit==4'd9)&&(ten==4'd9))
ten <= 4'd0;
else if((cnt1==CNT1_MAX)&&(unit==4'd9))
ten <= ten +1'b1;
else
ten <= ten;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
hund <= 4'd0;
else if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(cnt1==CNT1_MAX))
hund <= 4'd0;
else if((unit==4'd9)&&(ten==4'd9)&&(cnt1==CNT1_MAX))
hund <= hund +1'b1;
else
hund <= hund;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
thod <= 4'd0;
else if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(cnt1==CNT1_MAX))
thod <= 4'd0;
else if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(cnt1==CNT1_MAX))
thod <= thod +1'b1;
else
thod <= thod;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
t_thod <= 4'd0;
else if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(t_thod==4'd9)&&(cnt1==CNT1_MAX))
t_thod <= 4'd0;
else if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(cnt1==CNT1_MAX))
t_thod <= t_thod +1'b1;
else
t_thod <= t_thod;
always @(posedge clk or negedge rst_n)
if(rst_n==1'b0)
h_thod <= 4'd0;
else if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(h_thod==4'd9)&&(t_thod==4'd9)&&(cnt1==CNT1_MAX))
h_thod <= 4'd0;
else if((unit==4'd9)&&(ten==4'd9)&&(hund==4'd9)&&(thod==4'd9)&&(t_thod==4'd9)&&(cnt1==CNT1_MAX))
h_thod <= h_thod +1'b1;
else
h_thod <= h_thod;
always @(posedge clk or negedge rst_n)
if (rst_n == 1'b0)
sel <= 6'b000_000;
else
case (cnt_n)
3'd0 : sel <= 6'b000_001;
3'd1 : sel <= 6'b000_010;
3'd2 : sel <= 6'b000_100;
3'd3 : sel <= 6'b001_000;
3'd4 : sel <= 6'b010_000;
3'd5 : sel <= 6'b100_000;
default: sel <= 6'b000_000;
endcase
parameter CNT_SEL = 16'd49_999;
reg [2:0] cnt_n;
reg [15:0] cnt_sel;
always @(posedge clk or negedge rst_n)
if (rst_n == 1'b0)
cnt_sel <= 3'd0;
else if(cnt_sel==CNT_SEL)
cnt_sel <= 3'd0;
else
cnt_sel <= cnt_sel +1'b1;
always @(posedge clk or negedge rst_n)
if (rst_n == 1'b0)
cnt_n <= 3'd0;
else if((cnt_n==3'd5)&&(cnt_sel==CNT_SEL))
cnt_n <= 3'd0;
else if(cnt_sel==CNT_SEL)
cnt_n <= cnt_n +1'b1;
else
cnt_n <= cnt_n;
always @(posedge clk or negedge rst_n)
if (rst_n == 1'b0)
seg <= 8'hff;
else if(cnt_n==3'd0)
seg <= seg_data[unit];
else if(cnt_n==3'd1)
begin
if(cnt2<17'd1)
seg <= 8'hff;
else
seg <= seg_data[ten];
end
else if(cnt_n==3'd2)
begin
if(cnt2<17'd10)
seg <= 8'hff;
else
seg <= seg_data[hund];
end
else if(cnt_n==3'd3)
begin
if(cnt2<17'd100)
seg <= 8'hff;
else
seg <= seg_data[thod];
end
else if(cnt_n==3'd4)
begin
if(cnt2<17'd1000)
seg <= 8'hff;
else
seg <= seg_data[t_thod];
end
else if(cnt_n==3'd5)
begin
if(cnt2<17'd10000)
seg <= 8'hff;
else
seg <= seg_data[h_thod];
end
else
seg <= 8'hff;
endmodule
//动态数码管数据控制0~9999999显示
module hc595_t(
input wire clk,
input wire rst_n,
output reg [5:0] sel,
output reg [7:0] seg
);
parameter CNT1_MAX = 23'd4_999_999;
parameter CNT_MAX = 26'd49_999_999;
wire [7:0] seg_data[0:9];
assign seg_data[0] = 8'hc0;
assign seg_data[1] = 8'hf9;
assign seg_data[2] = 8'ha4;
assign seg_data[3] = 8'hb0;
assign seg_data[4] = 8'h99;
assign seg_data[5] = 8'h92;
assign seg_data[6] = 8'h82;
assign seg_data[7] = 8'hf8;
assign seg_data[8] = 8'h80;
assign seg_data[9] = 8'h90;
reg [22:0] cnt1;
reg [25:0] cnt;
reg [16:0] cnt2;
reg [3:0] unit, ten, hund, thod, t_thod, h_hund;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) cnt1 <= 0;
else if (cnt1 == CNT1_MAX) cnt1 <= 0;
else cnt1 <= cnt1 + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) cnt <= 0;
else if (cnt == CNT_MAX) cnt <= 0;
else cnt <= cnt + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) cnt2 <= 0;
else if (cnt == CNT_MAX && cnt2 == 17'd99999) cnt2 <= 0;
else if (cnt == CNT_MAX) cnt2 <= cnt2 + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) unit <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9) unit <= 0;
else if (cnt1 == CNT1_MAX) unit <= unit + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) ten <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9) ten <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9) ten <= ten + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) hund <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9) hund <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9) hund <= hund + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) thod <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9) thod <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9) thod <= thod + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) t_thod <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9 && t_thod == 4'd9) t_thod <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9) t_thod <= t_thod + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) h_hund <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9 && t_thod == 4'd9 && h_hund == 4'd9) h_hund <= 0;
else if (cnt1 == CNT1_MAX && unit == 4'd9 && ten == 4'd9 && hund == 4'd9 && thod == 4'd9 && t_thod == 4'd9) h_hund <= h_hund + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) sel <= 6'b000001;
else case (cnt2)
17'd0: sel <= 6'b000001;
17'd1: sel <= 6'b000011;
17'd10: sel <= 6'b000111;
17'd100: sel <= 6'b001111;
17'd1000: sel <= 6'b011111;
17'd10000: sel <= 6'b111111;
default: sel <= sel;
endcase
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) seg <= 8'hff;
else case (1'b1)
sel[0]: seg <= (unit <= 4'd9) ? 8'hff : seg_data[unit];
sel[1]: seg <= (ten <= 4'd9) ? 8'hff : seg_data[ten];
sel[2]: seg <= (hund <= 4'd9) ? 8'hff : seg_data[hund];
sel[3]: seg <= (thod <= 4'd9) ? 8'hff : seg_data[thod];
sel[4]: seg <= (h_hund <= 4'd9) ? 8'hff : seg_data[h_hund];
sel[5]: seg <= (t_thod <= 4'd9) ? 8'hff : seg_data[t_thod];
default: seg <= 8'hff;
endcase
end
endmodule
标签:seg,wire,assign,学习,数码管,源码,data,reg
From: https://blog.csdn.net/m0_63173133/article/details/142108089