id="c_n9"width="1920"height="990"style="position: fixed; top: 0px; left: 0px; z-index: -1; opacity: 0.5;">

数码管的动态扫描+计数器

数码管的动态扫描+计数器

对于数码管的扫描这个东西,我实现的确实比较困难,主要是大一的时候数电学的很烂,对于这些逻辑都不是很清楚,然后就看的很吃力。然后学校给的电路板是哪些引脚都是连在一起的,所以就只能用动态扫描来实现了,当然有人可能会说“这个东西在网上多的是”,呃,我这能说确实很多,但是对于动态扫描的东西都讲的比较一般,找了几天也就这找到一两篇还算可以的(对于动态扫描描述的比较详细的),然后就跟着上面的描述来实现,确实还是比较困难的(个人感觉),所以谨以此文记录我的实现过程。

关于七段译码器

这个其实不太想太多赘述,比较简单。我直接给出源码

LIBRARY IEEE;

USE IEEE.STD_LOGIC_1164.ALL;

Entity seg7_4 is --工程名为seg7_4

​       PORT ( BCD_in  : IN  STD_LOGIC_VECTOR(3 DOWNTO 0);   --输入四位BCD码

​               SG_out  : OUT STD_LOGIC_VECTOR(6 DOWNTO 0));  --输出七位字形码

 END;

ARCHITECTURE one OF seg7_4 IS

​       BEGIN

​        PROCESS(BCD_in)

​          BEGIN

​           CASE  BCD_in  IS

​            WHEN "0000"  => SG_out <= "0111111";  

​            WHEN "0001"  => SG_out <= "0000110"; 

​            WHEN "0010"  => SG_out <= "1011011"; 

​            WHEN "0011"  => SG_out <= "1001111"; 

​            WHEN "0100"  => SG_out <= "1100110";  

​            WHEN "0101"  => SG_out <= "1101101"; 

​            WHEN "0110"  => SG_out <= "1111101"; 

​            WHEN "0111"  => SG_out <= "0000111";

​            WHEN "1000"  => SG_out <= "1111111";  

​            WHEN "1001"  => SG_out <= "1101111"; 

​            WHEN "1010" => SG_out <= "1110111";  

​            WHEN "1011" => SG_out <= "1111100";

​            WHEN "1100" => SG_out <= "0111001"; 

​            WHEN "1101" => SG_out <= "1011110"; 

​            WHEN "1110" => SG_out <= "1111001";  

​            WHEN "1111" => SG_out <= "1110001";

​            WHEN OTHERS =>  NULL ;

​           END CASE ;

​          END PROCESS;    

END;

嗯,就是这样。 然后你导入到板子上去时你会发现管子上的数字是一起显示的,所以想实现显示不同的数字就得使用动态扫描的技术。

数码管的动态扫描实现

何为动态扫描

因为当多个数码管的引脚都绑定在一起时,所有东西都是一起显示的。想要实现不同数码管显示不同的数,就得用到动态扫描这个技术,对于实现的话也主要是通过不同的频率来进行控制数码管的刷新,然后通过人眼的余晖效应来实现看起来数码管上显示的是不同的数字。

实现

相关变量定义及说明

首先实现的话就得使用一个时钟信号,来控制数码管的选择;然后实现显示两个不同的数字的话还得用到分频这个东西,用来完成两个不同数码管的时钟信号(因为得实现计数器的功能嘛,然后又有两位,所以就得用两个时钟信号来完成),然后对于分频,个人理解就是来实现两个数码管的显示,必须使用不同的频率才行,然后高位就得使用高刷新率才能让看起来只有一个数显示(仅为个人理解)。然后分频公式:f=你选的频率*你的计时器是多少秒变一次(譬如说1s,2s,3s…)(这个主要是来实现数码管计数的快慢的,所以看你想把数码管显示的时间快慢调成多少,那就调成多少)。然后通过两个不同时钟信号来控制来实现对两个数码管的显示控制。我以两位数码管的为例,第一个数码管的时钟频率是在0到f之间,然后第二个数码管的时钟频率实在0到10*f之间。这里我假定q,p来表示这两个时钟信号。然后对于两个数码管上显示两个不同的数字,那么就需要一个变量来统计这个位数来实现对数码管的位选,这里我用num这个参数来表示,其范围是0----2因为是两位嘛,与你选的位数有关)。还有就是你需要用两个变量来实现存储十进制的数,这里定义为bcd,bcd1;对于这两个数码管的输出,写一个简单的译码器就可以了,注意:需要注意进位,以及逢十置0

过程简述

现在当时钟信号clk是上升沿的时候,这个num就得加一,然后当这个num大于2的时候,将其置为1;当这个bcd=10的时候,这个num得置为2(进位);然后就是开始输出的相关操作了:当num=1时,个位的时钟信号(q)进行加一,将输出的位选定下来**(以共阴极8个数码管的为例,sel<=“11111110”);然后就进行判断操作了,当这个q=f时,bcd就进行加一操作。然后就进行译码操作,(ps:当等于10的时候可以将其译为0,然后将bcd置为0)**,然后重置个位的时钟信号;对于十位的也上面的操作差不多,只是bcd1开始加一的条件会有一点变化,需要加上bcd=10这个条件,对于十位的时钟信号p需要等于f*10(实现分频),嗯,应该可以理解。然后就照葫芦画瓢,照着上面写就可以了。到这里了数码的动态扫描也就可以实现了。

源码

大家如果不是很理解的话就对照这代码来进行理解好吧

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity seg7_run is
port(
clk:in std_logic;
smg:out std_logic_vector(6 downto 0);--段选信号
sel:out std_logic_vector(7 downto 0)--位选信号
);
end;
architecture one of seg7_run is
signal x1:std_logic_vector(6 downto 0);--存储个位的数的数码显示的编码
signal x2:std_logic_vector(6 downto 0);--储存十位的
signal x:std_logic_vector(6 downto 0);--输出的一个中间变量,如果直接用上面的那个smg输出;就会导致同步显示
begin
process(clk)
variable bcd:integer range 0 to 10:=0;--个位计数
variable bcd1:integer range 0 to 10:=0;--十位计数
variable num:integer range 0 to 2:=0;--数码管的个数,也是计数器的位数
constant f:integer:=500;--分频
variable q:integer range 0 to f:=0;--个位的时钟信号
variable p:integer range 0 to f*10:=0;--十位的时钟信号
begin
if clk'event and clk='1' then
	num:=num+1;
	if num=3 then num:=1;
	end if;
	if bcd=10 then
	num:=2;
	end if;
	case num is
	when 1=>sel<="11111110";
		q:=q+1;
		if q=f then bcd:=bcd+1;
		case bcd is
		when 1=>x1<="0110000";
		when 2=>x1<="1101101";
		when 3=>x1<="1111001";
		when 4=>x1<="0110011";
		when 5=>x1<="1011011";
		when 6=>x1<="1011111";
		when 7=>x1<="1110000";
		when 8=>x1<="1111111";
		when 9=>x1<="1111011";
		when 10=>x1<="1111110";bcd:=0;--逢十进位
		when 0=>x1<="0000000";bcd:=0;--这个0不显示
	    end case;
	    q:=0;
	    end if;
	    x<=x1;
	when 2=>sel<="11111101";
	    p:=p+1;
	    if (p=10*f or bcd=10) then bcd1:=bcd1+1;
	     case bcd1 is
		 when 1=>x2<="0110000";
		 when 2=>x2<="1101101";
		 when 3=>x2<="1111001";
		 when 4=>x2<="0110011";
		 when 5=>x2<="1011011";
		 when 6=>x2<="1011111";
		 when 7=>x2<="1110000";
		 when 8=>x2<="1111111";
		 when 9=>x2<="1111011";
		 when 10=>x2<="1111110";bcd1:=0;--逢十进位
		 when 0=>x2<="0000000";bcd:=0;--这个0不显示
	     end case;
	     p:=0;
	    end if;
	  x<=x2;
	when others=>num:=num;
	end case;
	end if;
end process;
smg<=x;//输出在数码管上
end;

ps:本人对数电学的不是很好,可能有一些概念讲的有一些问题,请大家多担待一下,如果可以的话可以私信我,谢谢!

posted @ 2022-01-29 10:53  hellozmc  阅读(159)  评论(0编辑  收藏  举报