FPGA学习心得——矩阵键盘
来源:互联网 发布:calibre软件 编辑:程序博客网 时间:2024/06/16 22:40
1、行列式键盘概述
为了减少键盘与单片机接口时所占用I/O口线的数目,在键数较多时,通常都将键盘排列成行列矩阵式,行列式键盘又叫矩阵式键盘。用带有I/O口的线组成行列结构,按键设置在行列的交点上。例如用2*2的行列结构可以构成4个键的键盘,4*4的行列结构可以构成有16个键的键盘。这样,当按键数量平方增长时,I/O口线只是线性增长,这样就可以节省I/O口线。
2、行列式键盘原理
教研室已有薄膜矩阵键盘,其实物图如图所示。
其电路原理图如下图所示。
按键设置在行列线交叉点,行、列线分别连接到按键开关的两端。列线通过上拉电阻接+5V的电压,即列线的输出被钳位到高电平状态。行线与按键的一个引脚相连,列线与按键的另一个引脚相连。判断键盘中有无按键按下是通过行线送入扫描信号,然后从列线读取状态得到的。其方法是依次给行线送低电平,检查列线的输入。如果列线信号全为高电平,则代表低电平信号所在的行中无按键按下;如果列线有输入为低电平,则低电平信号所在的行和出现低电平的列的交点处有按键按下。
设行扫描信号为keydrv3~keydrv0,列线按键输入信号keyin3~keyin0与按键位置的关系如下表所示。
由行列式键盘的原理可以知道,要正确地完成按键输入工作必须有按键扫描电路产生keydrv3~keydrv0信号。同时还必须有按键译码电路从keydrv3~keydrv0信号和keyin3~keyin0信号中译码出按键的键值。此外,一般还需要一个按键发生标志信号用于和其他模块接口,通知其它模块键盘上有按键动作发生,并可以从键盘模块中读取按键键值。由于各个模块需要的时钟频率是不一样的,因此时钟产生模块就是用于产生各个模块需要的时钟信号。因此得到键盘接口电路的结构如图2所示。
图2 键盘接口电路结构图
行列式键盘电路的FPGA实现主要解决三个问题,一是如何检测是否有按键按下并防止采集到干扰信号;二是在按键闭合时如何防止抖动;三是如何判断为哪一个按键位动作,并对其进行译码。因此,为了解决这些问题,程序中使用不同的进程分别实现键盘扫描信号的产生、键盘去抖以及键盘的译码。
3、源程序
------------------------------------------------------------------------------------ Company: -- Engineer: -- -- Create Date: 08:46:57 07/31/2012 -- Design Name: -- Module Name: MatrixKeyboard - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: ---- Dependencies: ---- Revision: -- Revision 0.01 - File Created-- Additional Comments: ------------------------------------------------------------------------------------library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;---- Uncomment the following library declaration if instantiating---- any Xilinx primitives in this code.--library UNISIM;--use UNISIM.VComponents.all;entity MatrixKeyboard is Port ( Clk : in STD_LOGIC; Reset: inSTD_LOGIC; KeyIn : in STD_LOGIC_VECTOR (3 downto 0); KeyScan : out STD_LOGIC_VECTOR (3 downto 0); LED : out STD_LOGIC_VECTOR (3 downto 0) );end MatrixKeyboard;architecture Behavioral of MatrixKeyboard isSignal Clk_scan:STD_LOGIC:='0';Signal Clk_5ms:STD_LOGIC:='0';Signal Clk_2ms:STD_LOGIC:='0';Signal Key_Scan: STD_LOGIC_VECTOR(3 downto 0);Signal Key_Decode: STD_LOGIC_VECTOR(7 downto 0);Type State_Key is(st_key1,st_key2,st_key3,st_key4);Signal Current_Key : State_Key := st_key1;Type State_Scan is(st_scan1,st_scan2,st_scan3,st_scan4);Signal Current_Scan : State_Scan := st_scan1;beginProc_Clk_5ms : process(Clk)variable cnt_clk : integer range 0 to 250000 := 0;beginif(rising_edge(Clk)) thenif(cnt_clk < 125000) thencnt_clk := cnt_clk + 1;Clk_scan<= '0';elsif(cnt_clk < 249999) thencnt_clk := cnt_clk + 1;Clk_scan<= '1';elsecnt_clk := 0;end if;Clk_5ms<= Clk_scan;end if;end process Proc_Clk_5ms;Proc_Clk_2ms : process(Clk)variable cnt_clk : integer range 0 to 100000 := 0;beginif(rising_edge(Clk)) thenif(cnt_clk < 50000) thencnt_clk := cnt_clk + 1;Clk_2ms<= '0';elsif(cnt_clk < 99999) thencnt_clk := cnt_clk + 1;Clk_2ms<= '1';elsecnt_clk := 0;end if;end if;end process Proc_Clk_2ms;Proc_Scan:process(Clk_5ms)beginif(rising_edge(Clk_5ms)) thencase Current_Scan iswhen st_scan1 =>Key_Scan <= "1110";Current_Scan <= st_scan2;when st_scan2 =>Key_Scan <= "1101";Current_Scan <= st_scan3;when st_scan3 =>Key_Scan <= "1011";Current_Scan <= st_scan4;when st_scan4 =>Key_Scan <= "0111";Current_Scan <= st_scan1;end case;end if;end process Proc_Scan;KeyScan <= Key_Scan;Key_Decode <= Key_Scan & Keyin;Proc_Keyboard:process(Clk_2ms,Reset)variable cnt_btn : integer range 0 to 50000 := 0;beginif(Reset = '1') thenLED<=x"1";Current_Key<= st_key1;elsif(falling_edge(Clk_2ms)) thencase Current_Key iswhen st_key1 =>--Check whether any keys are pressedif((Keyin and "1111") = "1111") then Current_Key <= st_key1;elseCurrent_Key <= st_key2;end if;when st_key2 =>--keys debouncingif((Keyin and "1111") = "1111") then Current_Key <= st_key1;elsecase Key_Decode iswhen "11101110" => LED <= "0001";when "11101101" => LED <= "0010";when "11101011" => LED <= "0011";when "11100111" => LED <= "1010";when "11011110" => LED <= "0100";when "11011101" => LED <= "0101";when "11011011" => LED <= "0110";when "11010111" => LED <= "1011";when "10111110" => LED <= "0111";when "10111101" => LED <= "1000";when "10111011" => LED <= "1001";when "10110111" => LED <= "1100";when "01111110" => LED <= "1110";when "01111101" => LED <= "0000";when "01111011" => LED <= "1111";when "01110111" => LED <= "1101"; when others => null; end case;end if;Current_Key <= st_key3;when st_key3 =>--Check whether the pressed keys are releasedif((Keyin and "1111") /= "1111") then Current_Key <= st_key3;elseCurrent_Key <= st_key4;end if;when st_key4 =>--keys debouncingif((Keyin and "1111") /= "1111") then Current_Key <= st_key3;elseLED<=x"0";Current_Key <= st_key1;end if;end case;end if;end process Proc_Keyboard;end Behavioral;
- FPGA学习心得——矩阵键盘
- FPGA学习心得——分频器
- FPGA矩阵键盘(三段式)
- nRF52832 — 矩阵键盘
- FPGA矩阵键盘的扫描方法
- FPGA学习心得
- 单片机——矩阵键盘
- 51单片机—矩阵键盘
- 键盘——独立键盘和矩阵键盘
- 51单片机———矩阵键盘
- 单片机——矩阵键盘秒表
- 51单片机—矩阵键盘-代码
- FPGA学习心得——LCD1602文字滚动显示(4位传输模式、ST7066U控制芯片)
- FPGA&CPLD学习心得
- 个人FPGA学习心得
- FPGA Verilog 矩阵键盘按下和释放时向串口发送键值
- 展讯平台驱动学习心得(二) —键盘扫描码的配置和使用
- 单片机实验——4X4矩阵键盘识别技术
- Objective-C研究院之NSMutableString(四)
- 一生都学不完的计谋
- python模块的打包
- android init.rc语法标准 .
- usaco Ordered Fractions
- FPGA学习心得——矩阵键盘
- mysql 添加列,修改列,删除列
- win、linux、unix查看系统主机名
- statement和preparedStatement的区别
- AfxGetApp->GetMainWnd()与AfxGetMainWnd
- java修改文件名
- 用Ant实现Java项目的自动构建和部署
- Linux下的.o,.so,.a,.la文件的整理
- 一步一步学习Spring(4)-基于Spring的Hibernate Search全文检索功能