FPGA学习—矩阵键盘数码管显示

hu07020506   2012-7-3 22:04 楼主
控制单个数码管显示按键的键值,

在设计中,利用VHDL硬件描述语言在FPGA芯片上实现键盘接口设计并利用仿真FPGA软件进行仿真,主要解决了三个问题:一是如何检测是否有按键按下并防止采集到干扰信号;二是在按键闭合时如何防止抖动;三是如何判断为哪一个按键位动作,并对其进行译码。

分为四个模块,分频模块,译码模块,键盘扫描模块,键值确定模块,

分频模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;

USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY FENPING IS
PORT(
CLK:IN STD_LOGIC;
CLK_200:OUT STD_LOGIC;
CLK_1K:OUT STD_LOGIC;
CLK_40K:OUT STD_LOGIC
);
END ENTITY;

ARCHITECTURE ART OF FENPING IS
SIGNAL COUNT0:INTEGER RANGE 0 TO 1249;
SIGNAL COUNT1:INTEGER RANGE 0 TO 49999;
SIGNAL COUNT2:INTEGER RANGE 0 TO 249999;
BEGIN

PROCESS(CLK)IS
BEGIN
IF(CLK'EVENT AND CLK='1')THEN
   IF(COUNT0=1249)THEN COUNT0<=0;
    ELSE COUNT0<=COUNT0+1;
    END IF;
   IF(COUNT1=49999)THEN COUNT1<=0;
      ELSE COUNT1<=COUNT1+1;
      END IF;
    IF(COUNT2=249999)THEN COUNT2<=0;
     ELSE COUNT2<=COUNT2+1;
     END IF;
END IF;
END PROCESS;

PROCESS(COUNT0)IS
BEGIN
IF(COUNT0>=625)THEN CLK_40K<='1';
ELSE CLK_40K<='0';
END IF;
END PROCESS;

PROCESS(COUNT1)IS
BEGIN
IF(COUNT1>=25000)THEN CLK_1K<='1';
ELSE CLK_1K<='0';
END IF;
END PROCESS;

PROCESS(COUNT2)IS
BEGIN
IF(COUNT2>=125000)THEN CLK_200<='1';
ELSE CLK_200<='0';
END IF;
END PROCESS;

END ARCHITECTURE;
产生200HZ,1KHZ,40KHZ三中频率

译码模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY YIMA IS

PORT(
TMP:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
DIS:OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END ENTITY;

ARCHITECTURE ART OF YIMA IS
BEGIN
PROCESS(TMP)IS
BEGIN
CASE(TMP)IS
 WHEN"0000"=>DIS<="00111111";
       WHEN"0001"=>DIS<="00000110";
       WHEN"0010"=>DIS<="01011011";
       WHEN"0011"=>DIS<="01001111";
       WHEN"0100"=>DIS<="01100110";
       WHEN"0101"=>DIS<="01101101";
       WHEN"0110"=>DIS<="01111101";
       WHEN"0111"=>DIS<="00000111";
       WHEN"1000"=>DIS<="01111111";
       WHEN"1001"=>DIS<="01101111";
       WHEN"1010"=>DIS<="01110111";
       WHEN"1011"=>DIS<="01111100";
       WHEN"1100"=>DIS<="00111001";
       WHEN"1101"=>DIS<="01011110";
       WHEN"1110"=>DIS<="01111001";
       WHEN"1111"=>DIS<="01110001";
       WHEN OTHERS=>DIS<="00000000";
 END CASE;
 END PROCESS;
 END ARCHITECTURE;

得到键值后,译成数码管显示的键值,由于只有一个数码管,所以不存在位扫描。

键盘扫描模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY KEY_SCAN IS
PORT(
CLK_200:IN STD_LOGIC;
KEY_LIE:OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END ENTITY;

ARCHITECTURE ART OF KEY_SCAN IS

SIGNAL CURRENT_STATE,NEXT_STATE:STD_LOGIC_VECTOR(3 DOWNTO 0);

BEGIN
PROCESS(CLK_200)IS
BEGIN
IF(CLK_200'EVENT AND CLK_200='1')THEN
 CURRENT_STATE<=NEXT_STATE;
 END IF;
END PROCESS;

PROCESS(CURRENT_STATE)IS
BEGIN
CASE CURRENT_STATE IS
WHEN"1110"=>NEXT_STATE<="1101";
WHEN"1101"=>NEXT_STATE<="1011";
WHEN"1011"=>NEXT_STATE<="0111";
WHEN"0111"=>NEXT_STATE<="1110";
WHEN OTHERS=>NEXT_STATE<="1110";
END CASE;
END PROCESS;
KEY_LIE<=CURRENT_STATE;
END ARCHITECTURE;

键盘扫描的思路是对输出列信号四位轮流输出低电平,检测输入行信号四位是否有低电平,有低电平说明有键码按下,再根据行列的矢量值,判断到底是哪一位按下。

键值确定模块

LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY JIANPAN1 IS
PORT(
CLK:IN STD_LOGIC;

KEY_HANG:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
KEY_LIE:BUFFER STD_LOGIC_VECTOR(3 DOWNTO 0);
DIS:OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END ENTITY;

ARCHITECTURE ART OF JIANPAN1 IS

COMPONENT FENPING IS
PORT(
CLK:IN STD_LOGIC;
CLK_200:OUT STD_LOGIC;
CLK_1K:OUT STD_LOGIC;
CLK_40K:OUT STD_LOGIC
);
END COMPONENT;
COMPONENT YIMA IS

PORT(
TMP:IN STD_LOGIC_VECTOR(3 DOWNTO 0);
DIS:OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
COMPONENT KEY_SCAN IS
PORT(
CLK_200:IN STD_LOGIC;
KEY_LIE:OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END COMPONENT;
SIGNAL keyvalue:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL KEY_CODE:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL TMP:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL CLK_200,CLK_1K,CLK_40K,INT,temp_pressed:STD_LOGIC;
BEGIN
U1:FENPING PORT MAP(CLK,CLK_200,CLK_1K,CLK_40K);
U2:KEY_SCAN PORT MAP(CLK_200,KEY_LIE);
U3:YIMA PORT MAP(TMP,DIS);
INT<=NOT(KEY_HANG(0)AND KEY_HANG(1)AND KEY_HANG(2)AND KEY_HANG(3));
KEY_CODE<=KEY_HANG&KEY_LIE;
PROCESS(CLK_40K)IS
 BEGIN
 IF(INT='1')THEN
IF(CLK_40K'EVENT AND CLK_40K='1')THEN
 IF(INT='1')THEN
  CASE KEY_CODE IS
  WHEN"11101110"=>keyvalue<=CONV_STD_LOGIC_VECTOR(0,4);
                                   temp_pressed<='1';
                             
               WHEN"11101101" =>keyvalue<=CONV_STD_LOGIC_VECTOR(1,4);
                                  temp_pressed<='1';        
                              
               WHEN"11101011" =>keyvalue<=CONV_STD_LOGIC_VECTOR(2,4);
                                   temp_pressed<='1';
                             
               WHEN"11100111" =>keyvalue<=CONV_STD_LOGIC_VECTOR(3,4);
                                   temp_pressed<='1';
                               
               WHEN"11011110" =>keyvalue<=CONV_STD_LOGIC_VECTOR(4,4);
                                   temp_pressed<='1';
                                  
               WHEN"11011101" =>keyvalue<=CONV_STD_LOGIC_VECTOR(5,4);
                                     temp_pressed<='1';
                               
               WHEN"11011011" =>keyvalue<=CONV_STD_LOGIC_VECTOR(6,4);
                                   temp_pressed<='1';
                               
               WHEN"11010111" =>keyvalue<=CONV_STD_LOGIC_VECTOR(7,4);
                                   temp_pressed<='1';
                               
               WHEN"10111110" =>keyvalue<=CONV_STD_LOGIC_VECTOR(8,4);
                                   temp_pressed<='1';
                              
               WHEN"10111101" =>keyvalue<=CONV_STD_LOGIC_VECTOR(9,4);
                                temp_pressed<='1';
                                       
               WHEN"10111011" =>keyvalue<=CONV_STD_LOGIC_VECTOR(10,4);
                                  temp_pressed<='1';
                              
               WHEN"10110111" =>keyvalue<=CONV_STD_LOGIC_VECTOR(11,4);
                             temp_pressed<='1';
                        
               WHEN"01111110" =>keyvalue<=CONV_STD_LOGIC_VECTOR(12,4);
                                    temp_pressed<='1';
                          
               WHEN"01111101" =>keyvalue<=CONV_STD_LOGIC_VECTOR(13,4);
                                  temp_pressed<='1';
                            
               WHEN"01111011" =>keyvalue<=CONV_STD_LOGIC_VECTOR(14,4);
                                   temp_pressed<='1';
                             
               WHEN"01110111" =>keyvalue<=CONV_STD_LOGIC_VECTOR(15,4);
                                    temp_pressed<='1';
                             
              WHEN OTHERS  =>
                                 temp_pressed<='0';
           END CASE;
           END IF;
           END IF;
           END IF;
 END PROCESS;
 
 PROCESS(CLK_1K)IS
BEGIN
IF(temp_pressed='1')THEN
 IF(CLK_1K'EVENT AND CLK_1K='1')THEN
   TMP<=keyvalue;
   END IF;
 END IF;
 END PROCESS;
 END ARCHITECTURE;

在动态输入列信号,扫描行信号,得到键值。

本实验的关键在于键盘检测的思想,对行赋值,检测列值,关于消抖程序,不太明白,好像也没涉及到。

回复评论 (2)

支持楼主。如果楼主能对程序进行理解和评价,那就更好了

一个为理想不懈前进的人,一个永不言败人! http://shop57496282.taobao.com/ 欢迎光临网上店铺!
点赞  2012-7-8 22:46

干货

支持一下

点赞  2021-5-5 17:39
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复