一、新建一个工程
1.打开Quarteus,直接点击New Project izard.
2.选择存放路径和工程名后一直Next,直到出现芯片选择页面(这里需要特别注意,这个软件不支持中文,所以工程存放路径一定不能含有中文,否则会报错)
3.选择对应的芯片,我这里选择EP4CE40F23C8,然后Next,最后Finish
4.完成工程的创建后,界面如图所示
5.我们点击File->New,出现如下图所示页面,再点击VHDL File并确定
6.至此,完成了VHDL工程文件的创建
二、矩阵键盘
矩阵键盘只有8个端口[KR0…KR3]和[KC0…KC3],,即对应四输入和四输出,如下图所示
所以,我们需要让行/列做输入口,列/行做输出口,再读取输出口的状态,结合输入即可得出按下的是哪个按键具体实现在代码部分
三、代码部分
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY leds7 IS
PORT(clk,RST,EN:IN STD_LOGIC;
KR:OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --行
KC:IN STD_LOGIC_VECTOR(3 DOWNTO 0); --列
ledg:OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --数码管
SEL:OUT STD_LOGIC_VECTOR(2 DOWNTO 0)); --数码管位选
END leds7;
ARCHITECTURE bhv OF leds7 IS
BEGIN
PROCESS(clk,RST,EN)
VARIABLE RC:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE K:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE ROW:STD_LOGIC_VECTOR(3 DOWNTO 0);
VARIABLE Q:STD_LOGIC_VECTOR(1 DOWNTO 0);
--定义八个变量用于存储对应数码管的值
VARIABLE Q1:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE Q2:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE Q3:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE Q4:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE Q5:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE Q6:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE Q7:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE Q8:STD_LOGIC_VECTOR(7 DOWNTO 0);
VARIABLE count:STD_LOGIC_VECTOR(2 DOWNTO 0);
VARIABLE SELG:STD_LOGIC_VECTOR(2 DOWNTO 0);
VARIABLE T:STD_LOGIC_VECTOR(9 DOWNTO 0);
VARIABLE FLAG:STD_LOGIC;
BEGIN
IF RST = '0'THEN --当复位信号为低电平时,清空八个数码管对应存储的值,即复位
Q8:="00000000";Q7:="00000000";Q6:="00000000";Q5:="00000000";
Q4:="00000000";Q3:="00000000";Q2:="00000000";Q1:="00000000";
count := "000";
SELG := "000";
ELSIF clk'EVENT AND clk = '1'THEN --获取时钟上升沿信号
Q:=Q+1;
CASE Q IS
WHEN "00"=>ROW:="1110";KR<=ROW; --扫描第一列
WHEN "01"=>ROW:="1101";KR<=ROW; --扫描第二列
WHEN "10"=>ROW:="1011";KR<=ROW; --扫描第三列
WHEN "11"=>ROW:="0111";KR<=ROW; --扫描第四列
WHEN OTHERS=>NULL;
END CASE;
IF EN = '1' THEN
CASE ROW IS
WHEN "1110" =>
CASE KC IS
WHEN "0111" =>RC:= "11101110"; --扫描第一行,按键按下则为1
WHEN "1011" =>RC:= "11101101"; --扫描第二行,按键按下则为4
WHEN "1101" =>RC:= "11101011"; --扫描第三行,按键按下则为7
WHEN "1110" =>RC:= "11100111"; --扫描第四行,按键按下则为E
WHEN OTHERS => NULL;
END CASE;
WHEN "1101" =>
CASE KC IS
WHEN "0111" =>RC:= "01111110"; --扫描第一行,按键按下则为A
WHEN "1011" =>RC:= "01111101"; --扫描第二行,按键按下则为B
WHEN "1101" =>RC:= "01111011"; --扫描第三行,按键按下则为C
WHEN "1110" =>RC:= "01110111"; --扫描第四行,按键按下则为D
WHEN OTHERS =>NULL;
END CASE;
WHEN "1011" =>
CASE KC IS
WHEN "0111" =>RC:= "10111110"; --扫描第一行,按键按下则为3
WHEN "1011" =>RC:= "10111101"; --扫描第二行,按键按下则为6
WHEN "1101" =>RC:= "10111011"; --扫描第三行,按键按下则为9
WHEN "1110" =>RC:= "01111011"; --扫描第四行,按键按下则为C
WHEN OTHERS =>NULL;
END CASE;
WHEN "0111" =>
CASE KC IS
WHEN "0111" =>RC:= "11011110"; --扫描第一行,按键按下则为2
WHEN "1011" =>RC:= "11011101"; --扫描第二行,按键按下则为5
WHEN "1101" =>RC:= "11011011"; --扫描第三行,按键按下则为8
WHEN "1110" =>RC:= "11010111"; --扫描第四行,按键按下则为0
WHEN OTHERS =>NULL;
END CASE;
WHEN OTHERS =>NULL;
END CASE;
END IF;
T:=T+1; --每次时钟上升沿T自增1
IF T = "0011101101"THEN --当T满足0011101101时
FLAG := '1'; --标志位FLAG为1,即允许按键输入
T := T-T; --可以适当修改T的值,使得按键灵敏度达到最佳
END IF;
SELG:=SELG-1; --数码管位选自减1
IF(RC /= "11111111")AND(FLAG = '1') THEN --按键输入一个值时数码管对应值向左移
Q8:=Q7;Q7:=Q6;Q6:=Q5;Q5:=Q4;
Q4:=Q3;Q3:=Q2;Q2:=Q1;Q1:=RC;
FLAG := '0'; --标志位返回0,目的是避免按键按下一次输入多个值
T := T-T; --计数器T清零
IF Q8 = "00000000" THEN --每有一个按键值输入时
count := count-1; --count自减1,目的是存储位选值循环的条件
ELSE --当Q8的值不为零时,说明有八个数输入了,位选信号可以从111自减到000
count := "000";
END IF;
END IF;
IF FLAG = '0'THEN --在标志位FLAG为0的时候
RC:="11111111"; --RC始终为11111111,避免一次键入多个值
END IF;
IF (SELG < count) OR (Q1 = "00000000")THEN
SELG := "111"; --每当数码管位选达到最后一位要显示的位置时,位选重新回归111
END IF;
SEL <= SELG; --把位选信号传递给位选引脚
--数码管与对应存储数据的配对关系
CASE SELG IS
WHEN "000" =>K:= Q8;
WHEN "001" =>K:= Q7;
WHEN "010" =>K:= Q6;
WHEN "011" =>K:= Q5;
WHEN "100" =>K:= Q4;
WHEN "101" =>K:= Q3;
WHEN "110" =>K:= Q2;
WHEN "111" =>K:= Q1;
WHEN OTHERS => NULL;
END CASE;
--数码管显示译码部分
CASE K IS
WHEN "11010111" =>ledg <= "00111111"; --0
WHEN "11101110" =>ledg <= "00000110"; --1
WHEN "11011110" =>ledg <= "01011011"; --2
WHEN "10111110" =>ledg <= "01001111"; --3
WHEN "11101101" =>ledg <= "01100110"; --4
WHEN "11011101" =>ledg <= "01101101"; --5
WHEN "10111101" =>ledg <= "01111101"; --6
WHEN "11101011" =>ledg <= "00000111"; --7
WHEN "11011011" =>ledg <= "01111111"; --8
WHEN "10111011" =>ledg <= "01101111"; --9
WHEN "01111110" =>ledg <= "01110111"; --A
WHEN "01111101" =>ledg <= "01111100"; --B
WHEN "01111011" =>ledg <= "00111001"; --C
WHEN "01110111" =>ledg <= "01011110"; --D
WHEN "11100111" =>ledg <= "01111001"; --E
WHEN "10110111" =>ledg <= "01110001"; --F
WHEN OTHERS => ledg <= "00000000";
END CASE;
END IF;
END PROCESS;
END bhv;
我们分四步对矩阵键盘进行扫描,我们首先给第一行赋值1,其他行赋值0,即KR=“0001”,当第一个的按键按下时,列输出KC将得到“0001”,第二个按键按下时,KC= “0010”,依次类推,再给第二行赋值“0010”,列值得到不同的输出,一共有16种情况,对应4X4矩阵键盘的16个按键,当满足不同条件时将相应数码管的值赋给SEG7,最终再赋给SEG7S。文章来源:https://www.toymoban.com/news/detail-423839.html
四、仿真结果
从仿真结果中可以看出,当只键入一个值时,数码管显示一个值,同时数码管位选也只有一个值“111”,逐个输入后,位选相应增加,数码管显示对应的值。文章来源地址https://www.toymoban.com/news/detail-423839.html
到了这里,关于VHDL矩阵键盘扫描数码管显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!