矩阵键盘显示.docx

上传人:b****5 文档编号:5788410 上传时间:2023-01-01 格式:DOCX 页数:42 大小:459.83KB
下载 相关 举报
矩阵键盘显示.docx_第1页
第1页 / 共42页
矩阵键盘显示.docx_第2页
第2页 / 共42页
矩阵键盘显示.docx_第3页
第3页 / 共42页
矩阵键盘显示.docx_第4页
第4页 / 共42页
矩阵键盘显示.docx_第5页
第5页 / 共42页
点击查看更多>>
下载资源
资源描述

矩阵键盘显示.docx

《矩阵键盘显示.docx》由会员分享,可在线阅读,更多相关《矩阵键盘显示.docx(42页珍藏版)》请在冰豆网上搜索。

矩阵键盘显示.docx

矩阵键盘显示

 

 

EDA基础实验分册

 

矩阵键盘显示电路的设计

一、键盘显示原理

1键盘实现方案

实现键盘有两种方案:

一是采用现有的一些芯片实现键盘扫描;再就是用软件实现键盘扫描。

作为一个嵌入系统设计人员,总是会关心产品成本。

目前有很多芯片可以用来实现键盘扫描,但是键盘扫描的软件实现方法有助于缩减一个系统的重复开发成本,且只需要很少的CPU开销。

嵌入式控制器的功能很强,可能充分利用这一资源,这里就介绍一下软键盘的实现方案。

 

图10-1简单键盘电路

2键盘抖动的产生及去抖

通常在一个键盘中使用了一个瞬时接触开关,并且用如图10-1所示的简单电路,微处理器可以容易地检测到闭合。

当开关打开时,通过处理器的I/O口的一个上拉电阻提供逻辑1;当开关闭合时,处理器的/IO口的输入将被拉低得到逻辑0。

可遗憾的是,开关并不完善,因为当它们被按下或者被释放时,并不能够产生一个明确的1或者0。

尽管触点可能看起来稳定而且很快地闭合,但与微处理器快速的运行速度相比,这种动作是比较慢的。

当触点闭合时,其弹起就像一个球。

弹起效果将产生如图10-2所示的好几个脉冲。

弹起的持续时间通常将维持在5ms∼30ms之间。

我们可以在时钟的上升沿捕获一个稳定的按键值,从而达到消抖的目的。

 

图10-2按键抖动

3键盘扫描

键盘上阵列这些开关最有效的方法(当需要5个以上的键时)就形成了一个如图10-3所示的二维矩阵。

当行和列的数目一样多时,也就是方型的矩阵,将产生一个最优化的布列方式(I/O端被连接的时候)。

一个瞬时接触开关(按钮)放置在每一行与线一列的交叉点。

矩阵所需的键的数目显然根据应用程序而不同。

每一行由一个输出端口的一位驱动,而每一列由一个电阻器上拉且供给输入端口一位。

 

图10-3矩阵键盘

键盘扫描的实现过程如下:

对于4×4键盘,通常连接为4行、4列,因此要识别按键,只需要知道是哪一行和哪一列即可,为了完成这一识别过程,我们的思想是,首先固定输出4行为高电平,然后输出4列为低电平,在读入输出的4行的值,通常高电平会被低电平拉低,如果读入的4行均为高电平,那么肯定没有按键按下,否则,如果读入的4行有一位为低电平,那么对应的该行肯定有一个按键按下,这样便可以获取到按键的行值。

同理,获取列值也是如此,先输出4列为高电平,然后在输出4行为低电平,再读入列值,如果其中有哪一位为低电平,那么肯定对应的那一列有按键按下。

 

4*4的键盘面配置

5键盘键值的获取

键盘上的每一个按键其实就是一个开关电路,当某键被按下时,该按键的接点会呈现0的状态,反之,未被按下时则呈现逻辑1的状态。

扫描信号由Kr3~Kr0进入键盘,变化的顺序依次为1110-1101-1011-0111-1110。

每一次扫描一排,依次地周而复始。

例如现在的扫描信号为1011,代表目前正在扫描2、5、8,0这一排的按键,如果这排当中没有按键被按下的话,则由Kc3~Kc0读出的值为1111;反之当7这个按键被按下的话,则由Kc3~Kc0读出的值为1101。

  根据上面所述原理,我们可得到各按键的位置与数码关系如表所示。

  

如表按键位置与数码关系

Kr3-kr0

0111

0111

0111

0111

1011

1011

1011

1011

Kc3-kc0

0111

1011

1101

1110

0111

1011

1101

1110

键值

1

4

7

14

2

5

8

0

Kr3-kr0

1101

1101

1101

1101

1110

1110

1110

1110

Kc3-kc0

0111

1011

1101

1110

0111

1011

1101

1110

键值

3

6

9

15

10

11

12

13

获取到行值和列值以后,组合成一个8位的数据,根据实现不同的编码在对每个按键进行匹配,找到键值后在7段码管显示。

二、实验内容

本实验要求完成的任务是通过编程实现对4X4矩阵键盘按下键的键值的读取,并在数码管上完成一定功能(如移动等)的显示。

按键盘的定义,按下“*”键则在数码管是显示“E”键值。

按下“#”键在数码管上显示“F”键值。

其它的键则按键盘上的标识进行显示。

在此实验中数码管与FPGA的连接电路和管脚连接在以前的实验中都做了详细说明,这里不在赘述。

本实验箱上的4X4矩阵键盘的电路原理如图10-4所示。

与FPGA的管脚连接如表10-1所示。

 

图10-44X4矩阵键盘电路原理图

信号名称

对应FPGA管脚名

说明

KEY-C0

AC18

钜阵键盘的第1列选择

KEY-C1

AC17

钜阵键盘的第2列选择

KEY-C2

AD17

钜阵键盘的第3列选择

KEY-C3

AC16

钜阵键盘的第4列选择

KEY-R0

AD16

钜阵键盘的第1行选择

KEY-R1

AC15

钜阵键盘的第2行选择

KEY-R2

AD15

钜阵键盘的第3行选择

KEY-R3

AC14

钜阵键盘的第4行选择

表10-14X4矩阵键与FPGA的管脚连接表

三、实验步骤

1.下面我们建立一个矩阵键盘显示的VHDL工程

1)选择开始>程序>Altera>QuartusII5.1,运行QUARTUSII软件。

或者双击桌面上的QUARTUSII的图标运行QUARTUSII软件,出现如图1-3所示。

 

图1-3QUARTUSII软件运行界面

2)选择软件中的菜单File>NewProjectWizard,新建一个工程。

如图1-4所示。

 

 

图1-4新建工程对话框

3)点击图1-4中的NEXT进入工作目录,工程名的设定对话框如图1-5所示。

第一个输入框为工程目录输入框,用户可以输入如e:

/eda等工作路径来设定工程的目录,设定好后,所有的生成文件将放入这个工作目录。

第二个输入框为工程名称输入框,第三个输入框为顶层实体名称输入框。

用户可以设定如EXP1,一般情况下工程名称与实体名称相同。

使用者也可以根据自已的实际情况来设定工程名和顶层文件名。

注:

本处的顶层文件名必须和程序的实体名一致,否则编译会出错。

 

图1-5指定工程名称及工作目录

4)点击NEXT,进入下一个设定对话框,按默认选项直接点击NEXT进行器件选择对话框。

如图1-6所示。

这里我们以选用CycloneII系列芯片EP2C35F672C8为例进行介绍。

用户可以根据使用的不同芯片来进行设定。

 

图1-6器件选择界面

首先在对话框的左上方的Family下拉菜单中选取CycloneII,在中间右边的Speedgrade下拉菜单中选取8,在左下方的Availabledevices框中选取EP2C35F672C8,点击NEXT完成器件的选取,进入EDATOOL设定界面如图1-7所示。

 

图1-7EDATOOL对话框

5)按默认选项,点击Next出现新建工程以前所有的设定信息,如图1-8所示,点击Finish完成新建工程的建立。

 

图1-8新建工程信息

2、建立VHDL设计文件

1)在创建好设计工程后,选择File>NEW…菜单,出现图1-9所示的新建设计文件类型选择窗口。

这里我们以建立VHDL设计文件为例进行说明。

 

 

图1-9新建设计文件选择窗口

2)在New对话框(图1-9)中选择DeviceDesignFiles页下的VHDLFile,点击OK按钮,打开图形编辑器对话框,如图1-10所示。

图中标明了常用的每个按钮的功能

3)在文本编辑器中输入如下VHDL程序:

--下面是引用库-------------------------------------

libraryieee;--库函数

useieee.std_logic_1164.all;--定义了std_logic数据类型及相应运算

useieee.std_logic_arith.all;

--定义了signed和unsigned数据类型、相应运算和相关类型转换函数

useieee.std_logic_unsigned.all;

--定义了一些函数,可以使std_logic_vector类

--型被当作符号数或无符号数一样进行运算

------------------------------------------------------------------------

--下面是结构实体

----------------------------------------------------------------

entityexp10is--exp10为实体名

port(Clk:

instd_logic;--时钟信号

Kr:

instd_logic_vector(3downto0);--键盘行

Kc:

bufferstd_logic_vector(3downto0);--键盘列

a,b,c,d,e,f,g:

outstd_logic;--七段码管显示

Sa,sb,sc:

bufferstd_logic);--七段码管片选

endexp10;--结束实体

--------------------------------------------------------------------

architecturebehaveofexp10is--behave为结构体名

signalkeyr,keyc:

std_logic_vector(3downto0);--键盘行列扫描信号量

signalkcount:

std_logic_vector(2downto0);

signaldcount:

std_logic_vector(2downto0);

signalkflag1,kflag2:

std_logic;

signalbuff1,buff2,buff3,buff4,buff5,buff6,buff7,buff8:

integerrange0to15;

signalDisp_Temp:

integerrange0to15;

signalDisp_Decode:

std_logic_vector(6downto0);

begin

process(Clk)--扫描键盘扫描键盘的列

begin

if(Clk'eventandClk='1')then

if(Kr="1111")then

kflag1<='0';

kcount<=kcount+1;

if(kcount=0)then

kc<="1110";--扫描第一列

elsif(kcount=1)then

kc<="1101";--扫描第二列

elsif(kcount=2)then

kc<="1011";--扫描第三列

else

kc<="0111";--扫描第四列

endif;

else

kflag1<='1';

keyr<=Kr;

keyc<=Kc;

endif;

kflag2<=kflag1;

endif;

endprocess;

process(Clk)--显示右移

begin

if(Clk'eventandClk='1')then--上升沿

if(kflag1='1'andkflag2='0')then

buff1<=buff2;--移位

buff2<=buff3;

buff3<=buff4;

buff4<=buff5;

buff5<=buff6;

buff6<=buff7;

buff7<=buff8;

endif;

endif;

endprocess;

process(Clk)--获取键值

begin

if(Clk'eventandClk='1')then

if(kflag1='1'andkflag2='0')then

if(keyr="0111")then--扫描第一列

casekeycis

when"0111"=>buff8<=1;--扫描第一行

when"1011"=>buff8<=4;--扫描第二行

when"1101"=>buff8<=7;--扫描第三行

when"1110"=>buff8<=14;--扫描第四行

whenothers=>buff8<=buff8;--nochange

endcase;

elsif(keyr="1011")then--扫描第二列

casekeycis

when"0111"=>buff8<=2;--扫描第一行

when"1011"=>buff8<=5;--扫描第二行

when"1101"=>buff8<=8;--扫描第三行

when"1110"=>buff8<=0;--扫描第四行

whenothers=>buff8<=buff8;--nochange

endcase;

elsif(keyr="1101")then--扫描第三列

casekeycis

when"1110"=>buff8<=15;--扫描第一行

when"1101"=>buff8<=9;--扫描第二行

when"1011"=>buff8<=6;--扫描第三行

when"0111"=>buff8<=3;--扫描第四行

whenothers=>buff8<=buff8;--nochange

endcase;

elsif(keyr="1110")then--扫描第四列

casekeycis

when"1110"=>buff8<=13;--扫描第一行

when"1101"=>buff8<=12;--扫描第二行

when"1011"=>buff8<=11;--扫描第三行

when"0111"=>buff8<=10;--扫描第四行

whenothers=>buff8<=buff8;--nochange

endcase;

endif;

endif;

endif;

endprocess;

process(dcount)--数码管驱动扫描

begin

case(dcount)is

when"000"=>Disp_Temp<=buff1;--扫描第一个数码管

when"001"=>Disp_Temp<=buff2;--扫描第二个数码管

when"010"=>Disp_Temp<=buff3;--扫描第三个数码管

when"011"=>Disp_Temp<=buff4;

when"100"=>Disp_Temp<=buff5;

when"101"=>Disp_Temp<=buff6;

when"110"=>Disp_Temp<=buff7;

when"111"=>Disp_Temp<=buff8;--'1'

endcase;

endprocess;

process(Clk)

begin

if(Clk'eventandClk='1')then--扫描累加

dcount<=dcount+1;

a<=Disp_Decode(0);--七段数码管a段赋值

b<=Disp_Decode

(1);--七段数码管b段赋值

c<=Disp_Decode

(2);--七段数码管c段赋值

d<=Disp_Decode(3);--七段数码管d段赋值

e<=Disp_Decode(4);--七段数码管e段赋值

f<=Disp_Decode(5);--七段数码管f段赋值

g<=Disp_Decode(6);--七段数码管g段赋值

sa<=dcount(0);--数码管的片选信号赋值第一位

sb<=dcount

(1);--数码管的片选信号赋值第二位

sc<=dcount

(2);--数码管的片选信号赋值第三位

endif;

endprocess;

process(Disp_Temp)--显示转换

begin

caseDisp_Tempis

when0=>Disp_Decode<="0111111";--'0'

when1=>Disp_Decode<="0000110";--'1'

when2=>Disp_Decode<="1011011";--'2'

when3=>Disp_Decode<="1001111";--'3'

when4=>Disp_Decode<="1100110";--'4'

when5=>Disp_Decode<="1101101";--'5'

when6=>Disp_Decode<="1111101";--'6'

when7=>Disp_Decode<="0000111";--'7'

when8=>Disp_Decode<="1111111";--'8'

when9=>Disp_Decode<="1101111";--'9'

when10=>Disp_Decode<="1110111";--'A'

when11=>Disp_Decode<="1111100";--'b'

when12=>Disp_Decode<="0111001";--'C'

when13=>Disp_Decode<="1011110";--'d'

when14=>Disp_Decode<="1111001";--'E'

when15=>Disp_Decode<="1110001";--'-'

whenothers=>Disp_Decode<="0000000";--全灭

endcase;

endprocess;

endbehave;

关于VHDL,我们以上面键盘显示程序为例来解释VHDL的语法构成,以使大家对VHDL有个整体的把握。

一个VHDL程序有三部分构成,其为:

1.库和包library(设计资源);

2.实体entity(外部端口)

3.结构体architecture(内部结构)

①库和包library(设计资源)的介绍

1.1useieee.std_logic_1164.all;--定义了std_logic数据类型及相应运算

1.2useieee.std_logic_arith.all;--定义了signed和unsigned数据类型、相应运算

--和相关类型转换函数

1.3useieee.std_logic_unsigned.all;--定义了一些函数,可以使std_logic_vector

--类型被当作符号数或无符号数一样进行运算

本程序中用到3个库函数包:

如下:

补充:

当使用库时,需要说明使用的库名称,同时需要说明库中包集合的名称及范围;每个实体都应独立进行库的说明;库的说明应该在实体之前;经过说明后,实体和结构体就可以自动调用库中的资源;

②实体entity(外部端口)

entityexp10is--exp10为实体名

port(Clk:

instd_logic;--时钟信号

Kr:

instd_logic_vector(3downto0);--键盘行

Kc:

bufferstd_logic_vector(3downto0);--键盘列

a,b,c,d,e,f,g:

outstd_logic;--七段码管显示

Sa,sb,sc:

bufferstd_logic);--七段码管片选

endexp10;--结束实体

实体说明主要描述对象的外貌,即对象的输入和输出(I/O)的端口信息,它并不描述器件的具体功能。

在电路原理图上实体相当于元件符号。

 

Clka--g

Krkc

SaSbSc

③结构体architecture(内部结构)

结构体具体指明了该设计实体的行为,定义了该设计实体的功能,规定了该设计实体的数据流程,指派了实体中内部元件的连接关系。

architecturebehaveofexp10is--behave为结构体名

signalkeyr,keyc:

std_logic_vector(3downto0);

--键盘行列扫描信号量

signalkcount:

std_logic_vector(2downto0);

signaldcount:

std_logic_vector(2downto0);

signalkflag1,kflag2:

std_logic;

signalbuff1,buff2,buff3,buff4,buff5,buff6,buff7,buff8:

integerrange0to15;

signalDisp_Temp:

integerrange0to15;

signalDisp_Decode:

std_logic_vector(6downto0);

begin

process(Clk)--扫描键盘扫描键盘的列

begin

if(Clk'eventandClk='1')then

if(Kr="1111")then

kflag1<='0';

kcount<=kcount+1;

if(kcount=0)then

kc<="1110";--扫描第一列

elsif(kcount=1)then

kc<="1101";--扫描第二列

elsif(kcount=2)then

kc<="1011";--扫描第三列

else

kc<="0111";--扫描第四列

endif;

else

kflag1<='1';

keyr<=Kr;

keyc<=Kc;

endif;

kflag2<=kflag1;

endif;

endprocess;

process(Clk)--显示右移

begin

if(Clk'eventandClk='1')then--上升沿

if(kflag1='1'andkflag2='0')then

buff1<=buff2;--移位

buff2<=buff3;

buff3<=buff4;

buff4<=buff5;

buff5<=buff6;

buff6<=buff7;

buff7<=buff8;

endif;

endif;

en

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 日语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1