开发板上有六位一体的数码管,可以用数码管显示一些数据。
通过电阻直接与数字管有八个段选信号FPGA连接;三极管连接有六个供电端。三极管的控制端由三八翻译器的输出控制,三八翻译器的输入由三八翻译器控制FPGA控制输出。
数码管也称LED数码管,不同行业人士对数码管的称呼不一样,其实都是同样的产品。
数码管可分为七段数码管和八段数码管。八段数码管比七段数码管多一个发光二极管单元,即多一个小数点(DP)这个小数点可以更准确地表示数字管想要显示的内容;可分为1、2、3、4、5、6、7等数字管。
根据发光二极管单元的连接方式,可分为共阳极数码管和共阴极数码管。共阳数码管是指将所有发光二极管的阳极连接在一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到 5V,当一个字段发光二极管的阴极是低电平时,相应的字段被点亮,当一个字段的阴极是高电平时,相应的字段就不亮了。共阴数码管是指将所有发光二极管的阴极连接在一起形成公共阴极(COM)在应用数字管和共阴数字管时,应使用公共极端COM接到地线GND当一个字段发光二极管的阳极是高电平时,相应的字段就会被点亮,当一个字段的阳极是低电平时,相应的字段就不会被点亮。
例如,如果要显示数字1B、C段亮,其他段不亮就够了。
数字管动态显示接口是单片机中应用最广泛的显示方式之一。动态驱动是所有数字管的8个显示笔划"a,b,c,d,e,f,g,dp"同名端连接在一起,是每个数字管的公共极COM增加位选通控制电路,位选通独立I/O线控制,当FPGA输出字形码时,所有数字管都收到相同的字形码,但哪个数字管会显示字形取决于FPGA对位选通COM端电路的控制,所以只要打开需要显示的数码管的选通控制,这个位置就会显示字形,没有选通的数码管就不会亮。
开发板上的数字管是共阳极数字管,是动态显示接口COM端三极管是PNP三极管,所以输出低电时,三极管导通。
三八译码器的原理是C、B、A根据C、B、A输入值,相应选择Y(低电平选择)。
三八译码器的使能端已经通过电路固定,一直处于使能状态。FPGA只需要控制C、B、A然后选择相应的数码管。
通过分时轮流控制轮流控制COM端,使每个数字管轮流控制显示,这就是动态驱动。在轮流显示过程中,每个数字管的点亮时间为1~2ms,由于人类的视觉暂留现象和发光二极管的余辉效应,虽然数字管不同时点亮,但只要扫描速度足够快,印象是一组稳定的显示数据,没有闪烁感,动态显示效果和静态显示相同,可以节省很多I/O端口,功耗更低。
每个数字管都可以显示十进制0~9,或显示16进制0~9以及A~F。一个数字管可以显示任何四位二进制,六个数字管可以显示任何24位二进制。
24位二进制实际上分为6组四位二进制,分别显示在相应的数字管上。
设计时,首先设计1ms的计时器。1ms切换一次选定的管道;根据选定的管道,选择相应的四位二进制,然后将二进制翻译成相应的段选信号输出。
共阳极数码管段选信号码表为:
该模块命名为seven_tube_drive。
编写代码时,将data信号作为端口信号,由于下板时没有外界提供,下板时会从端口省略信号,直接在内部产生固定值。
设计一个1ms计数器,每1ms切换要点亮的数码管。根据要点亮的位置,从data在24位中选择相应的四位,然后将四位数据翻译成段选信号。
设计代码为:
module seven_tube_drive ( input wire clk, input wire rst_n, input wire [23:0] data, output reg [7:0] seven_tube_seg_n, output reg [2:0] seven_tube_sel ); localparam T_1ms = 50_000; reg [15:0] cnt; reg [2:0] sel; reg [3:0] show_data; always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) cnt <= 16'd0; else if (cnt < T_1ms - 1'b1) cnt <= cnt 1'b1; else cnt <= 16'd0; end always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) sel <= 3'd0; else if (cnt == T_1ms - 1'b1) if (sel < 3'd5) sel <= sel 1'b1; else sel <= 3'd0; else sel <= sel; end always @ (posedge clk) seven_tube_sel <= sel; always @ * begin case (sel) 3'd0 : show_data = data[23:20]; 3'd1 : show_data = data[19:16]; 3'd2 : show_data = data[15:12]; 3'd3 : show_data = data[11:8]; 3'd4 : show_data = data[7:4]; 3'd5 : show_data = data[3:0]; default : show_data = 4'd0; endcase end always @ (posedge clk, negedge rst_n) begin if (rst_n == 1'b0) seven_tube_seg_n <= 8'hff; else case (show_data) 4'd0 : seven_tube_seg_n <= 8'b1100_0000; 4'd1 : seven_tube_seg_n <= 8'b1111_1001; 4'd2 : seven_tube_seg_n <= 8'ha4; 4'd3 : seven_tube_seg_n <= 8'hb0; 4'd4 : seven_tube_seg_n <= 8'h99; 4'd5 : seven_tube_seg_n <= 8'h92; 4'd6 : seven_tube_seg_n <= 8'h82; 4'd7 : seven_tube_seg_n <= 8'hf8; 4'd8 : seven_tube_seg_n <= 8'h80; 4'd9 : seven_tube_seg_n <= 8'h90; 4'd10 : seven_tube_seg_n <= 8'h88; 4'd11 : seven_tube_seg_n <= 8'h83; 4'd12 : seven_tube_seg_n <= 8'hc6; 4'd13 : seven_tube_seg_n <= 8'ha1; 4'd14 : seven_tube_seg_n <= 8'h86; 4'd15 : seven_tube_seg_n <= 8'h8e; default : seven_tube_seg_n <= 8'hff; endcase end endmodule
在设计中,定义了一个sel寄存器,端口seven_tube_sel为sel寄存器的寄存信号在时间顺序上会比较sel晚一拍。show_data信号的产生是利用sel寄存器和外部data时序上和sel同步;端口seven_tube_seg_n为show_data信号的寄存信号在时间顺序上会比较show_data晚一拍信号。因此seven_tube_seg_n和seven_tube_sel信号是同步的,都比sel晚一拍信号。此时数码管不会出现鬼影。
当数码管的seven_tube_sel和seven_tube_seg_n当不同步时,选定的管道和要显示的数字将不完全同步。由于不同步时间相对较少,错误数字显示时间较短,照明程度较小,称为鬼影。
模拟时,将T_1ms将参数修改为10。
data按照16进制的方式赋值数据,赋值后不要更改,否则不利于仿真图的查看。
仿真代码为:
`timescale 1ns/1ps module seven_tube_drive_t;
reg clk;
reg rst_n;
reg [23:0] data;
wire [7:0] seven_tube_seg_n;
wire [2:0] seven_tube_sel;
seven_tube_drive seven_tube_drive_inst(
.clk (clk),
.rst_n (rst_n),
.data (data),
.seven_tube_seg_n (seven_tube_seg_n),
.seven_tube_sel (seven_tube_sel)
);
initial clk = 1'b0;
always # 10 clk = ~clk;
initial begin
rst_n = 1'b0;
data = 24'h123456;
# 201
rst_n = 1'b1;
# 5000
$stop;
end
endmodule
在仿真图中,将cnt、sel、show_data信号调出;将data信号设置为十六进制显示,cnt设置为无符号位显示,sel设置为无符号位显示,show_data设置为十六进制显示。
可以从图中看出,设计符合我们的设计要求。
下板时,将T_1ms修改为50_000。并且将部分设计代码修改为下列格式:
module seven_tube_drive (
input wire clk,
input wire rst_n,
// input wire [23:0] data,
output reg [7:0] seven_tube_seg_n,
output reg [2:0] seven_tube_sel
);
wire [23:0] data;
assign data = 24'h123456;
localparam T_1ms = 50_000;
reg [15:0] cnt;
reg [2:0] sel;
reg [3:0] show_data;
······
进行分析综合后,进行分配管脚。下板后,就可以看到数码管上显示123456。
设计者可以修改data的赋值,再次综合后,观测数码管显示数据是否正确。
测试完成后,在后续使用过程中,还是需要将data设置为端口,以供给其他模块进行驱动。
大家好,我是【FPGA功夫熊猫】精益求精,不断推荐好文章。