基于VHDL的键盘扫描及显示电路.docx

上传人:b****3 文档编号:3668027 上传时间:2022-11-24 格式:DOCX 页数:14 大小:124.43KB
下载 相关 举报
基于VHDL的键盘扫描及显示电路.docx_第1页
第1页 / 共14页
基于VHDL的键盘扫描及显示电路.docx_第2页
第2页 / 共14页
基于VHDL的键盘扫描及显示电路.docx_第3页
第3页 / 共14页
基于VHDL的键盘扫描及显示电路.docx_第4页
第4页 / 共14页
基于VHDL的键盘扫描及显示电路.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

基于VHDL的键盘扫描及显示电路.docx

《基于VHDL的键盘扫描及显示电路.docx》由会员分享,可在线阅读,更多相关《基于VHDL的键盘扫描及显示电路.docx(14页珍藏版)》请在冰豆网上搜索。

基于VHDL的键盘扫描及显示电路.docx

基于VHDL的键盘扫描及显示电路

工学院

EDA课程设计

说明书

设计题目基于VHDL的键盘扫描

及显示电路

 

系别电控系

专业班级__________________

学生__________________

学号__________________

指导教师__________________

日期__________________

 

基于VHDL的键盘扫描及显示电路

一、工作原理:

可编程器件的KEY_HANG[3..0]行信号输出端不停循环输出“1110”“1101”“1011”“0111”。

当没有键按下时可编程器件的KEY_LIE[3..0]列信号输入端检测到的是“1111”。

当有按键按下时,如按下1,此时KEY_HANG[3..0]行信号输出为“0111”,即KEY_HANG[3..0]的3管脚为“0”,可由电路看出,此时输入端KEY_LIE[3..0]检测到的将是“0111”。

KEY_LIE[3..0]的3管脚为0,可以在编写程序时,将输出信号KEY_HANG[3..0]与输入信号KEY_LIE[3..0]同时判断,比如可以认为当数据“KEY_HANG&KEY_LIE”为“01110111”时,可译码成数据1,。

同理可得其他按键的编码。

根据不同数据的编码译成不同的数据。

名称

IO属性

描述

备注

clk

in

输入时钟,1K和40K频率

KEY_HANG[3..0]

out

矩阵键盘的扫描输入端口

KEY_LIE[3:

0]

in

矩阵键盘的扫描输出端口

START

out

数据输出标志 

DISPDATA[6..0]

out

数码管译码显示译码输出

7bit

DASPSEL[1..0]

out

数码管扫描输出

2bit

CLK_1K

CLK_40K

 

 

二、设计思路:

1.循环输出行信号,检测列信号输入,将行列信号相并。

2.译键值。

3.去抖动。

在译没一个键值后,为了防止抖动,加了一个计算环节,一旦检测到列信号后,译码,紧跟着进入计数环节,此时键抖动不会进入其他环节,这样可以防止抖动。

4.数码管译码、循环显示。

电路的具体功能罗列如下:

1)采用4×4矩阵键盘作为操作数和操作符的输入设备。

2)采用2位8段数码管作为输出显示设备,显示按下的数字及简单的功能。

3)由于所有键盘在按下或者弹起的时候均有按键抖动,所以应该采用去抖电路,当检测到有按键按下去的时候,应该延时20ms后,再进行检测,如果仍有键盘按键被按下去的话,则进行键盘读值。

矩阵键盘模块key_4_4的RTL电路图如下所示。

当CLK_1K上升沿到来时状态转为state0,然后判断列与非后的值,看是否有按键按下,如果有输入数据,则自动启动20ms的计数器,当计满数后,产生一个指示信号,此信号为1bit,高电平有效。

当读到此指示信号后,便再次将row信号锁存至寄存器,便得到键盘的一个返回值。

如果row没有变化,则state转换为state2,对第二行进行按键扫描。

依此类推,扫描第三行与第四行。

因为普通的按键都是接触式的,当按键闭合或释放时,上下接触面都会产生一个很短暂的抖动,如图2.2所示,这个抖动时间一般都会持续5-10ms,虽然这个抖动时间很短,但对于FPGA工作在50M的高频率上的器件来说,还是可以捕捉的到的。

为了使CPU对于一次按键操作只处理一次,在软件中必须加入去除抖动处理。

图2.2按键闭合时产生的抖动

由图中可以看出,最简单的去抖方法就是每隔一段时间读一次键盘,时间间隔大于10ms即可。

如果连续两次检测都有按键被按下,则可以肯定有按键被按下,而且也进入闭合稳定期。

三、数码管显示译码模块设计

数码管显示译码电路主要用来对实际的二进制数据装换为8段数码管的实际显示控制码,采用两个2位的8段共阴极数码管,数码管的显示方式有两种:

静态显示和动态显示。

具体如下:

静态显示方式:

所谓静态显示就是指无论是多少位数码管,同时处于显示状态。

静态显示的优点是:

数码管显示无闪烁,亮度高,软件控制比较容易;缺点是:

需要的硬件电路较多(每一个数码管都需要一个锁存器),将造成很大的不便,同时由于所有数码管都处于被点亮状态,所以需要的电流很大,当数码管的数量增多时,对电源的要求也就随之增高。

所以,在大部分的硬件电路设计中,很少采用静态显示方式。

动态显示方式:

所谓动态显示,是指无论在任何时刻只有一个数码管处于显示状态,每个数码管轮流显示。

动态显示的优点是:

硬件电路简单(数码管越多,这个优势越明显),由于每个时刻只有一个数码管被点亮,所以所有数码管消耗的电流较小;缺点是:

数码管亮度不如静态显示时的亮度高,例如有8个数码管,以1秒为单位,每个数码管点亮的时间只有1/8秒,所以亮度较低;如果刷新率较低,会出现闪烁现象;如果数码管直接与单片机连接,软件控制上会比较麻烦等。

显示译码方式如下:

1)时钟上升沿到来时分别对位选和段选进行译码。

2)将输入的2bite位选数据译码成4比特数据控制数码管的2位,由于是共阴极数码管要选定相应的数码管则使该位位低电平,其它位为高电平即可,如:

0000译码为0111_1111,对应于实验板上的左边第一位数码管。

3)将输入的4bite段选数据译码为8比特数据控制8个LED的亮灭,最高位接A,最低位接小数点位DP。

若要显示0则对应的译码为8’b1111_1100。

 

四、仿真

没有键按下时行循环输出“1110”“1101”“1011”“0111”

当随机按下时行保持所按下的状态不变

五、结论

这次EDA课程设计历时十天,学到很多很多的东西。

同时不仅可以巩固以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。

通过这次设计,进一步加深了对EDA的了解,让我对它有了更加浓厚的兴趣。

特别是当每一个子模块编写调试成功时,都会很高兴。

在编写顶层文件的程序时,遇到了不少问题,特别是各元件之间的连接,以及信号的定义,总是有错误。

排除困难后,程序编译就通过了。

在波形仿真时,也遇到了一点困难,想要的结果不能在波形上得到正确的显示,后来,经过屡次的调试之后,才发现在写代码之前对信号的相位考虑不足。

通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。

在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固。

总的来说,这次设计还是比较成功的,在设计中遇到了很多问题,最后在老师的辛勤指导下,终于迎刃而解,有点小小的成就感,终于觉得平时所学的知识有了实用的价值,达到了理论与实际相结合的目的,不仅学到了不少知识,而且锻炼了自己的能力,使自己对以后的路有了更加清楚的认识,同时,对未来有了更多的信心。

最后,对给过我帮助的老师和所有同学再次表示忠心的感!

6、程序

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

USEIEEE.STD_LOGIC_ARITH.ALL;

USEIEEE.STD_LOGIC_UNSIGNED.ALL;

 

ENTITYHHIS

PORT(

CLK_1K:

INSTD_LOGIC;-- 时钟输入1KHZ

CLK_40K:

INSTD_LOGIC;  --时钟输入40KHZ

KEY_LIE:

INSTD_LOGIC_VECTOR(3DOWNTO0);--列输入

START:

OUTSTD_LOGIC;--二-十进制数据输出标志

KEY_HANG:

OUTSTD_LOGIC_VECTOR(3DOWNTO0);--行输出

DATA_P:

OUTSTD_LOGIC_VECTOR(7DOWNTO0);--二-十进制数输出

DISP_DATA:

OUTSTD_LOGIC_VECTOR(6DOWNTO0);--数码管显示译码输出

DISP_SEL:

OUTSTD_LOGIC_VECTOR(1downto0));--数码管显示扫描输出

END;

ARCHITECTURERTLOFHHIS

SIGNALINT:

STD_LOGIC;--列与非信号

SIGNALCLK_SEL:

STD_LOGIC;--键值控制1khz的时钟信号

SIGNALSTART_REG:

STD_LOGIC;--数据输出标志信号

SIGNALDISP_SEL_REG:

STD_LOGIC_VECTOR(1DOWNTO0);--数码管显示扫描信号

SIGNALDATA_L,DATA_H:

STD_LOGIC_VECTOR(3DOWNTO0);--二-十进制低位、高位信号

SIGNALDATA_TMP:

STD_LOGIC_VECTOR(3DOWNTO0);--二-十进制低位高位暂存信号

SIGNALKEY_HANG_TMP:

STD_LOGIC_VECTOR(3DOWNTO0);--行输出信号

SIGNALDISP_DATA_REG:

STD_LOGIC_VECTOR(3DOWNTO0);--二-十进制低位、高位暂存信号(数码管用)

SIGNALKEY_CODE:

STD_LOGIC_VECTOR(7DOWNTO0);--行列相并信号

SIGNALDATA_P_REG:

STD_LOGIC_VECTOR(7DOWNTO0);--二-十进制数信号

BEGIN

KEY_CODE<=KEY_HANG_TMP&KEY_LIE;--行、列相并

DATA_P<=DATA_P_REG;

START<=START_REG;

KEY_HANG<=KEY_HANG_TMP;

DISP_SEL<=DISP_SEL_REG;

CLK_SEL<=CLK_1KAND(NOTINT);--无键按下时有CLK-SEL时钟信号输出

 

PROCESS(CLK_SEL,CLK_40K,INT)

VARIABLESTATE:

INTEGERRANGE0TO3;

BEGIN

IFRISING_EDGE(CLK_40K)THEN--一个40K的脉冲上升沿到来输入一次列状态以判断是否有按键按下

INT<=NOT(KEY_LIE(3)ANDKEY_LIE

(2)ANDKEY_LIE

(1)ANDKEY_LIE(0));

ENDIF;

IFRISING_EDGE(CLK_SEL)THEN--一个1K的脉冲的上升沿到来输出一个带表行的状态

CASESTATEIS--变量表示状态机,4循环

WHEN0=>

KEY_HANG_TMP<="1110";

STATE:

=1;

WHEN1=>

KEY_HANG_TMP<="1101";

STATE:

=2;

WHEN2=>

KEY_HANG_TMP<="1011";

STATE:

=3;

WHEN3=>

KEY_HANG_TMP<="0111";

STATE:

=0;

ENDCASE;

ENDIF;

ENDPROCESS;

PROCESS(CLK_40K,INT)--进程是并行的

VARIABLESTATE:

INTEGERRANGE0TO3;

VARIABLECOUNTER:

INTEGERRANGE0TO31;

BEGIN

IFINT='0'THEN

STATE:

=0;

COUNTER:

=0;

ELSIFRISING_EDGE(CLK_40K)THEN

CASESTATEIS

WHEN0=>

DATA_TMP<=DATA_L;--低四位放入暂存信号

STATE:

=1;

WHEN1=>--再嵌套一个CASE语句

 

CASEKEY_CODEIS--实现把像并数据译码十六进制的1到F

WHEN"01110111"=>

DATA_L<="0001";--把1放入低四位

DATA_H<=DATA_TMP;--把暂存信号的容放入高四位,相相当于向左移位

STATE:

=2;--跳出嵌套CASE语句,转向外CASE语句的状态2

WHEN"01111011"=>

DATA_L<="0010";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"01111101"=>

DATA_L<="0011";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"01111110"=>

DATA_L<="0100";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"10110111"=>

DATA_L<="0101";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"10111011"=>

DATA_L<="0110";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"10111101"=>

DATA_L<="0111";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"10111110"=>

DATA_L<="1000";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"11010111"=>--9键

DATA_L<="1001";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"11011011"=>--0键

DATA_L<="0000";

DATA_H<=DATA_TMP;

STATE:

=2;

WHEN"11011101"=>--A键,实现步进加一功能

IFDATA_H="1001"THEN

IFDATA_L="1001"THEN

DATA_H<="1001";

DATA_L<="1001";

ELSEDATA_L<=DATA_L+1;

ENDIF;

ELSIFDATA_L="1001"THEN

DATA_L<="0000";

DATA_H<=DATA_H+1;

ELSE

DATA_L<=DATA_L+1;

DATA_H<=DATA_H;

ENDIF;

STATE:

=2;

WHEN"11011110"=>--B键,实现步键加十

IFDATA_H="1001"THEN

DATA_H<="1001";

ELSE

DATA_L<=DATA_L;

DATA_H<=DATA_H+1;

ENDIF;

STATE:

=2;

WHEN"11100111"=>--C键,实现步进减一

IFDATA_L="0000"ANDDATA_H="0000"THEN

DATA_L<="0000";

DATA_H<="0000";

ELSIFDATA_L="0000"THEN

DATA_L<="1001";

DATA_H<=DATA_H-1;

ELSE

DATA_L<=DATA_L-1;

DATA_H<=DATA_H;

ENDIF;

STATE:

=2;

 

WHEN"11101011"=>--D键,实现步进减十

IFDATA_H="0000"THEN

DATA_H<="0000";

ELSE

DATA_L<=DATA_L;

DATA_H<=DATA_H-1;

ENDIF;

STATE:

=2;

 

WHEN"11101110"=>--E键,实现送数功能

DATA_L<=DATA_L;

DATA_H<=DATA_H;

DATA_P_REG<=DATA_H&DATA_L;

START_REG<='1';--数据输出标志信号置一

STATE:

=2;

WHEN"11101101"=>--F键,实现清零功能

DATA_L<="0000";

DATA_H<="0000";

STATE:

=2;

WHENOTHERS=>--不可缺少

STATE:

=2;

ENDCASE;

 

WHEN2=>--状态2实现去抖动功能

IFCOUNTER=31THEN--计数延时去抖

COUNTER:

=0;

STATE:

=3;

ELSE

COUNTER:

=COUNTER+1;

STATE:

=2;

ENDIF;

 

WHEN3=>--清除数据输出标志

START_REG<='0';

STATE:

=3;

ENDCASE;

ENDIF;

ENDPROCESS;

PROCESS(CLK_1K,DATA_L,DATA_H)--数码管循环显示

VARIABLESTATE:

INTEGERRANGE0TO1;

BEGIN

IFRISING_EDGE(CLK_1K)THEN

CASESTATEIS

WHEN0=>

DISP_SEL_REG<="10";--输入10到数码管显示扫描信号

DISP_DATA_REG<=DATA_L;--二-十进制低高位暂存节点

STATE:

=1;

WHEN1=>

DISP_SEL_REG<="01";

DISP_DATA_REG<=DATA_H;

STATE:

=0;

ENDCASE;

ENDIF;

ENDPROCESS;

PROCESS(CLK_1K,DISP_DATA_REG)--数码管译码

BEGIN

IFRISING_EDGE(CLK_1K)THEN

CASEDISP_DATA_REGIS

WHEN"0000"=>

DISP_DATA<="1111110";--0

WHEN"0001"=>

DISP_DATA<="0110000";--1

WHEN"0010"=>

DISP_DATA<="1101101";

WHEN"0011"=>

DISP_DATA<="1111001";

WHEN"0100"=>

DISP_DATA<="0110011";

WHEN"0101"=>

DISP_DATA<="1011011";

WHEN"0110"=>

DISP_DATA<="1011111";

WHEN"0111"=>

DISP_DATA<="1110000";

WHEN"1000"=>

DISP_DATA<="1111111";

WHEN"1001"=>

DISP_DATA<="1111011";

WHENOTHERS=>

DISP_DATA<="0000000";

ENDCASE;

ENDIF;

ENDPROCESS;

END;

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

当前位置:首页 > 工程科技 > 电子电路

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

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