VHDL实现动态数码管驱动-FPGA常见问题论坛-FPGA CPLD-ChipDebug

VHDL实现动态数码管驱动

 

目录

简介:

程序设计:

下载验证:


简介:

由于一般的静态驱动操作虽然方便,但占用的 I/0 口较多,例如要驱动6 位 8 段数码管,以静态驱动方式让数码管各个位显示不同的数值,如“123456”,需要占用6 × 8 = 48个I/O 口,虽然对于 FPGA 这种 I/O 口较多的芯片而言,在资源允许的情况下可以使用,但一般不建议浪费宝贵的 I/O 口资源,尤其在 I/O 口资源紧张的情况下,所以对于多位数码管一般采用动态驱动方式使数码管显示数字。

为了更好的理解数码管动态驱动,我们首先了解下市面上常见的多位数码管的内部连接。以两位数码管为例,其内部连接如下图。由此图可知,两位 8 段数码管共 10 个引脚,每位数码管的阳极连接在一起,为共阳极数码管,每位数码管相同段的 led 的阴极连接在一起,这样当给第 10 和第 5 脚高电平,给第 3 脚低电平时,两个数码管的发光二极管 A 都点亮,对于此种数码管以静态方式驱动显然不可能显示像“18”这种个位与十位不同的数字。那么该如何显示数字“18”呢?

图片[1]-VHDL实现动态数码管驱动-FPGA常见问题论坛-FPGA CPLD-ChipDebug

既然同时给第 10 和第 5 脚高电平不可行,那么是不是可以先给第 5 脚高电平,第 10 脚低电平,此时,让其显示数字“8”时,左边的数码管不显示,右边的数码管显示数字“8”;然后给第 10 脚高电平,第 5脚低电平,此时,让其显示数字“1”时,左边的数码管显示数字“1”,右边的数码管不显示,这样就可以显示数字“18”了。但有一个问题,多长时间切换显示的数码管呢,时间如果太长就只能看到数字―8”或数字“1”了,时间太短呢,结果是显示不清晰而且显示亮度不够。由于人眼的视觉暂留(人眼在观察景物时,光信号传人大脑神经,需经过一段短暂的时间,光的作用结束后,视觉形象并不立即消失,这种残留的视觉称“后像”,视觉的这一现象则被称为“视觉暂留”)及发光二极管的余辉效应(当停止向发光二极管供电时,发光二极管亮度仍能维持一段时间),每位数码管的点亮时间为 1~2ms 时,显示效果能满足使用需要。数码管的这种驱动方式称为数码管的动态驱动,实际上就是分时轮流控制不同数码管的显示。


程序设计:

图片[2]-VHDL实现动态数码管驱动-FPGA常见问题论坛-FPGA CPLD-ChipDebug

library ieee;use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity seg is 
port(
 clk: in std_logic;
 rst_n:in std_logic;
 ids_data: in std_logic_vector (15 downto 0);
 seg_duan: out std_logic_vector (7 downto 0);
 seg_wei: out std_logic_vector (5 downto 0)
);
end seg;
architecture behav of seg is
 constant num0:std_logic_vector(7 downto 0) := x"c0";
 constant num1:std_logic_vector(7 downto 0) := x"f9";
 constant num2:std_logic_vector(7 downto 0) := x"a4";
 constant num3:std_logic_vector(7 downto 0):= x"b0";
 constant num4:std_logic_vector(7 downto 0) := x"99";
 constant num5:std_logic_vector(7 downto 0) := x"92";
 constant num6:std_logic_vector(7 downto 0):= x"82";
 constant num7:std_logic_vector(7 downto 0) := x"f8";
 constant num8:std_logic_vector(7 downto 0) := x"80";
 constant num9:std_logic_vector(7 downto 0) := x"90";
 
constant num00:std_logic_vector(7 downto 0) := x"40";
constant num11:std_logic_vector(7 downto 0) := x"79";
constant num22:std_logic_vector(7 downto 0) := x"24";
constant num33:std_logic_vector(7 downto 0) := x"30";
constant num44:std_logic_vector(7 downto 0) := x"19";
constant num55:std_logic_vector(7 downto 0) := x"12";
constant num66:std_logic_vector(7 downto 0) := x"02";
constant num77:std_logic_vector(7 downto 0) := x"78";
constant num88:std_logic_vector(7 downto 0) := x"00"; 
constant num99:std_logic_vector(7 downto 0) := x"10";
    
 constant numa:std_logic_vector(7 downto 0) := x"88";
 constant numb:std_logic_vector(7 downto 0) := x"83";
 constant numc:std_logic_vector(7 downto 0):= x"c6";
 constant numd:std_logic_vector(7 downto 0) := x"a1";
 constant nume:std_logic_vector(7 downto 0) := x"86";
 constant numf:std_logic_vector(7 downto 0) := x"8e";
 constant we0:std_logic_vector(5 downto 0) := "111110";
 constant we1:std_logic_vector(5 downto 0) := "111101";
 constant we2:std_logic_vector(5 downto 0) := "111011";
 constant we3:std_logic_vector(5 downto 0) := "011111";
 constant we:std_logic_vector(5 downto 0) := "111111";
 
 signal a:integer range 0 to 100 :=0;
  signal b:integer range 0 to 100 :=0;
   signal c:integer range 0 to 100 :=0;
 begin
process(rst_n,clk,ids_data)
variable cnt_4 : std_logic_vector (9 downto 0);
 variable seg_num : std_logic_vector (3 downto 0);
begin
if (rst_n = '0') then cnt_4:="0000000000";
 elsif(rising_edge(clk)) then cnt_4:= cnt_4+1;
end if;
if (rst_n= '0') then seg_num:= "0000";
elsif(rising_edge(clk)) then
 case (cnt_4 (9 downto 8)) is
  when "00" => seg_num:=ids_data (3 downto 0);
  when "01" => seg_num:=ids_data (7 downto 4);
  when "10" =>seg_num:=ids_data (11 downto 8) ;
  when "11" => seg_num:=ids_data (15 downto 12);
  when others=>NULL;
 end case;
end if;
 
if (rst_n='0') then seg_wei<= "000000";
elsif (rising_edge(clk)) then 
if(cnt_4(7 downto 0) <="11100011")then
  
 case cnt_4 (9 downto 8) is
  when "00"=>
  seg_wei<=we0; 
  when "01"=>
  seg_wei<=we1;  
  when "10"=>
  seg_wei<=we2;  
  when "11"=>
  seg_wei<=we3; 
  when others=>
  seg_wei<=we;
 end case;
 else seg_wei<=we;
 end if;
 end if;
 
 if (rst_n='0') then seg_duan<= "00000000";
elsif (rising_edge(clk)) then 
 
  
 
if(cnt_4(9 downto 8)="01")then
 case seg_num is
  when "0000"=>seg_duan<=num00;
  when "0001"=>seg_duan<=num11;
  when "0010"=>seg_duan<=num22;
  when "0011"=>seg_duan<=num33;
  when "0100"=>seg_duan<=num44;
  when "0101"=>seg_duan<=num55;
  when "0110"=>seg_duan<=num66;
  when "0111"=>seg_duan<=num77;
  when "1000"=>seg_duan<=num88;
  when "1001"=>seg_duan<=num99;
  when others=>NULL;
 end case; 
 else
  case seg_num is
  when "0000"=>seg_duan<=num0;
  when "0001"=>seg_duan<=num1;
  when "0010"=>seg_duan<=num2;
  when "0011"=>seg_duan<=num3;
  when "0100"=>seg_duan<=num4;
  when "0101"=>seg_duan<=num5;
  when "0110"=>seg_duan<=num6;
  when "0111"=>seg_duan<=num7;
  when "1000"=>seg_duan<=num8;
  when "1001"=>seg_duan<=num9;
  when others=>NULL;
 end case;   
end if;
end if;
 
end process;
end behav;

 

下载验证:

具体效果可参考:

VHDL实现正计时器_Vizio__的博客-CSDN博客

大家如果仅仅拿来用的话,只需要注意传入的数据 ids_data 的数据类型及位宽即可

请登录后发表评论

    没有回复内容