键盘驱动程序
3 程序设计
3.1 流程
键盘扫描程序是整个程序的核心部分,其流程图如下图3.1所示。
图3.1 键盘扫描程序流程图
3.2 八位七段数码管显示程序
八位七段数码管显示程序,采用动态显示,每个数码管均可以从0到9、A到F的显示。通过查询键盘输出端的数据总线的通码值,将相应的通码在数码管上显示出来。程序见附录A,八位七段数码管显示如图3.2所示。
第9页(共32页)
键盘驱动程序
图3.2 八位七段数码管
3.3 16*16点阵显示程序
16*16点阵显示程序,通过查询数据总线的通码值,在LED点阵上显示键盘上相应的符号。程序见附录B,16*16点阵显示如图3.3所示。
第10页(共32页)
键盘驱动程序
图3.3 16*16点阵
3.4 键盘扫描程序
扫描码有两种不同的类型:“通码”和“断码”。当一个键被按下去或长按的时候,键盘就发送通码;当一个键被释放的时候,键盘就发送断码。每个键盘被分配了唯一的通码和断码,这样主机通过查找唯一的扫描码就可以确定是哪个按键被按下或释放。程序见附录C。
3.5 动态扫描程序
动态扫描程序,控制八位七段数码管和16*16点阵单独显示,当系统时钟频率达到一定值时,显示效果就和静态显示一样了。程序见附录D。
第11页(共32页)
键盘驱动程序
4 总结
4.1 遇到的问题及解决
课程设计一开始,老师先让我们熟悉了实验指导书上的实验一到实验六这六个实验,目的旨在于让我们熟悉课程设计的步骤以及相关的软硬件知识。
这六个实验相对来说比较简单,我与同学们基本上实现了仿真,只是我拿到的数据线有问题,实验的先前阶段我又没有发现这问题,所以一直没有实现仿真,后来问了下同学,才知道是数据线的问题,找到了症结所在,接下来的事就水到渠成了。
课程设计不可能不碰到一些问题比如:硬件的问题,软件的问题,程序的问题。我们这次课程设计使用的是新的设备,所以基本上没有出现硬件故障,只是有个别同学没有看设备的使用说明书,在做实验时碰到了一些操作问题,像什么数字信号模块的时钟没有选对啊,实验箱的电源没有插好啊等等。仿真软件也由于我们先前做了六个基本实验,碰到的问题也不到,哦,记起来了,有个问题困扰了我们很多同学,就是把实验箱与电脑连接的时候,发现实验箱与电脑无法正常的进行数据交换,我们很多同学开始都在想是不是实验箱坏了,后来发现是电脑没有找到硬件,经过扫描让电脑找到新的硬件后,问题也随之解决了。
碰到问题最多的是在编程的时候,众所周知,编写程序是项很枯燥无味的事,幸好我们有些例子程序,这样我们也不需要完全把程序编出来,只要编某个模块就行了,这次使用的实验箱上的接口有很多是共用一个端口,这给我们造成了很大的麻烦,要不是老师告诉使用动态扫描的方法,我们也许还不能实现这次课程设计的仿真。
4.2 扩展设想
我们可以通过按下外接键盘的按键,使实验箱上除了显示键盘的扫描码外播放音乐的基准音符,也可以通过12位LED灯的点亮数目来记录你按下了多少次按键。
第12页(共32页)
键盘驱动程序
4.3 心得与体会
设计之初,我对EDA知识的掌握应该说是还没入门,随着设计的深入,碰到了一系列的问题,为了实现仿真,我们就不得不去解决这一系列的问题,这样在解决问题的过程中我们不知不觉的就对EDA知识有了更深的了解,同时也巩固了以前的知识。
通过编程,我发现VHDL语言跟C语言、汇编语言在某些方面是相通的,所以无形之中我也对计算机语言有了更深的认识。编程是很费神的,又是一项细致活,这很锻炼人,同时也磨练人的意志。其实不管做什么,只要你用心认真的去做,你总是会发现很多有用的知识,你也会学到很多。
第13页(共32页)
键盘驱动程序
键盘驱动程序
摘要
键盘上的每一个键都有两个唯一的数值进行标志。为什么要用两个数值而不是一个数值呢?这是因为一个键可以被按下,也可以被释放。当一个键按下时,它们产生一个唯一的数值,当一个键被释放时,它也会产生一个唯一的数值,我们把这些数值都保存在一张表里面,到时候通过查表就可以知道是哪一个键被敲击,并且可以知道它是被按下还是被释放了。这些数值在系统中被称为键盘扫描码。本课程设计目的旨在使用Altera公司的EP2C35系列的FPGA芯片,利用SOPC-NIOSII-EP2C35开发板PS2键盘接口等资源,实现一个键盘驱动程序。以达到外接键盘按键的选择、8位动态七段数码管实现按键扫描码显示和16*16点阵实现按键字符显示的目的。
关键词:键盘;扫描码;数码管
键盘驱动程序
目录
1 绪论 ------------------------------------------------------------------------------------------- 1 2 系统设计 ------------------------------------------------------------------------------------- 2
2.1 总体设计 ------------------------------------------------------------------------------- 2 2.2 八位七段数码管显示模块 ---------------------------------------------------------- 3 2.3 16*16点阵显示模块 ----------------------------------------------------------------- 4 2.4 键盘扫描模块 ------------------------------------------------------------------------- 5 2.5 动态扫描模块 ------------------------------------------------------------------------- 7 3 程序设计 ------------------------------------------------------------------------------------- 9
3.1 流程 ------------------------------------------------------------------------------------- 9 3.2 八位七段数码管显示程序 ---------------------------------------------------------- 9 3.3 16*16点阵显示程序 ---------------------------------------------------------------- 10 3.4 键盘扫描程序 ------------------------------------------------------------------------ 11 3.5 动态扫描程序 ------------------------------------------------------------------------ 11 4 总结 ------------------------------------------------------------------------------------------ 12
4.1 遇到的问题及解决 ------------------------------------------------------------------ 12 4.2 扩展设想 ------------------------------------------------------------------------------ 12 4.3 心得与体会 --------------------------------------------------------------------------- 13 参考文献 ----------------------------------------------------------------------------------------- 14 附录 ----------------------------------------------------------------------------------------------- 15
附录A 八位七段数码管显示程序 ---------------------------------------------------- 15 附录B 16*16点阵显示程序 ----------------------------------------------------------- 18 附录C 键盘扫描程序 ------------------------------------------------------------------- 28 附录D 动态扫描程序 ------------------------------------------------------------------- 30 附录E 总电路图 ------------------------------------------------------------------------- 32
键盘驱动程序
1 绪论
EDA是电子设计自动化(Electronic Design Automation)的缩写,在20世纪60年代中期从计算机辅助设计(CAD)、计算机辅助制造(CAM)、计算机辅助测试(CAT)和计算机辅助工程(CAE)的概念发展而来的。
20世纪90年代,国际上电子和计算机技术较先进的国家,一直在积极探索新的电子电路设计方法,并在设计方法、工具等方面进行了彻底的变革,取得了巨大成功。在电子技术设计领域,可编程逻辑器件(如CPLD、FPGA)的应用,已得到广泛的普及,这些器件为数字系统的设计带来了极大的灵活性。这些器件可以通过软件编程而对其硬件结构和工作方式进行重构,从而使得硬件的设计可以如同软件设计那样方便快捷。这一切极大地改变了传统的数字系统设计方法、设计过程和设计观念,促进了EDA技术的迅速发展。
EDA技术就是以计算机为工具,设计者在EDA软件平台上,用硬件描述语言HDL完成设计文件,然后由计算机自动地完成逻辑编译、化简、分割、综合、优化、布局、布线和仿真,直至对于特定目标芯片的适配编译、逻辑映射和编程下载等工作。EDA技术的出现,极大地提高了电路设计的效率和可操作性,减轻了设计者的劳动强度。
本课程设计目的旨在使用Altera公司的EP2C35系列的FPGA芯片,利用SOPC-NIOSII-EP2C35开发板PS2键盘接口等资源,实现一个键盘驱动程序。以达到外接键盘按键的选择、8位动态七段数码管实现按键扫描码显示和16*16点阵实现按键字符显示的目的。
利用EDA工具,电子设计师可以从概念、算法、协议等开始设计电子系统,大量工作可以通过计算机完成,并可以将电子产品从电路设计、性能分析到设计出IC版图或PCB版图的整个过程的计算机上自动处理完成。
第1页(共32页)
键盘驱动程序
2 系统设计
VHDL语言是一种用于电路设计的高级语言。它在80年代的后期出现。最初是由美国国防部开发出来供美军用来提高设计的可靠性和缩减开发周期的一种使用范围较小的设计语言 。
VHDL主要用于描述数字系统的结构,行为,功能和接口。除了含有许多具有硬件特征的语句外,VHDL的语言形式和描述风格与句法是十分类似于一般的计算机高级语言。对于用VHDL完成的一个确定的设计,可以利用EDA工具进行逻辑综合和优化,并自动的把VHDL描述设计转变成门级网表。
VHDL的程序结构特点是将一项工程设计,或称设计实体(可以是一个元件,一个电路模块或一个系统)分成外部(或称可视部分,及端口)和内部(或称不可视部分),既涉及实体的内部功能和算法完成部分。在对一个设计实体定义了外部界面后,一旦其内部开发完成后,其他的设计就可以直接调用这个实体。这种将设计实体分成内外部分的概念是VHDL系统设计的基本点。
与其他的硬件描述语言相比,VHDL具有更强的行为描述能力,从而决定了它成为系统设计领域最佳的硬件描述语言。强大的行为描述能力是避开具体的器件结构,从逻辑行为上描述和设计大规模电子系统的重要保证。
本文利用模块化思想将整个设计分为八位七段数码管显示、16*16点阵显示和键盘扫描等模块,以达到键盘扫描码的显示。
2.1 总体设计
在本课程设计中要求利用外接键盘实现键盘按键的选择,在8位动态七段数码管上实现按键扫描码的显示,在16*16点阵上实现按键字符的显示。
设计中采用模块化,用键盘扫描输出端作为数据总线来对整个程序控制,各模块共一个系统时钟,数字信号源模块的时钟选择为1MHZPS2键盘采用是键盘内部的时钟。其总体设计如下图2.1所示。
第2页(共32页)
键盘驱动程序
图2.1 系统总体设计
2.2 八位七段数码管显示模块
八位七段数码管是电子开发过程中常用的输出显示设备。在实验系统中使用的是两个四位一体、共阴极型七段数码管。
由于七段数码管公共端连接到GND(共阴极型),当数码管的中的那一个段被输入高电平,则相应的这一段被点亮。反之则不亮。共阳极性的数码管与之相么。四位一体的七段数码管在单个静态数码管的基础上加入了用于选择哪一位数码管的位选信号端口。八个数码管的a、b、c、d、e、f、g、h、dp都连在了一起,8个数码管分别由各自的位选信号来控制,被选通的数码管显示数据,其余关闭。其单个静态数码管如下图2.2所示,数码管显示模块的电路原理如图2.3所示。
图2.2 静态七段数码管
第3页(共32页)
键盘驱动程序
图2.3 数码管显示电路原理
2.3 16*16点阵显示模块
16*16点阵由此256个LED通过排列组合而形成16行*16列的一个矩阵式的LED阵列,俗称16*16点阵。单个的LED的电路如下图2.4所示。
图2.4 单个LED电路图
由上图可知,对于单个LED的电路图当Rn输入一个高电平,同时Cn输入一个低电平时,电路形成一个回路,LED发光。也就是LED点阵对应的这个点被点亮。16*16点阵也就是由16行和16列的LED组成,其中每一行的所有16个LED的Rn端并联在一起,每一列的所有16个LED的Cn端并联在一起。通过给Rn输入一个高电平,也就相当于给这一列所有LED输入了一个高电平,这时只要某个LED的Cn端输入一个低电平时,对应的LED就会被点亮。具体的电路如下图2.5所示。
图2.5 16*16点阵电路原理图
第4页(共32页)
键盘驱动程序
16*16点阵的电路原理在前面已经做了详尽的说明,在此实验中,16*16点阵由4个8*8点阵组成,考虑到LED电流功耗与FPGA电流功耗的关系,在实验的电路中加入驱动电路。具体电路如下图2.6所示。
图2.6 16*16点阵电路图
2.4 键盘扫描模块
PS2通信协议是一种双向同步串行通迅协议。通迅的两端通过CLOCK(时钟信号端)同步,并通过DATA(数据端口)交换数据。任何一方如果想要抑制另外一方的通迅时,只需要把CLOCK拉到低电平。
PS2控制接口仅使用到两条传输端口,一为频率端口,另一则为数据端口如图2.7所示,且此传输埠必为三态(Tri-State)并具有双向(bidirectional)特性。PS2 传输产品上,常见为鼠标与键盘,两者的驱动原理均相同,仅扫描码(scan code)不同。因此我们以PS2键盘为例进行说明。
Male
Female
6-pin Mini-DIN
(PS2): 1 - Data
2 - Not Implemented 3 - Ground 4 - Vcc (+5V) 5 - Clock
6 - Not Implemented
(Plug)
(Socket)
图2.7 PS2 端口脚位定义
键盘其实就是一个大型的按键矩阵,它们由安装在电路板上的处理器(叫做“键盘编码器”)来监视着。虽然不同的键盘可能采用不同的处理器,但是它们完
第5页(共32页)
键盘驱动程序
成的任务都是一样的,即监视哪些按键被按下,哪些按键被释放了,并将这些信息传送到主机。如果有必要,处理器处理所有的去抖动,并在它的16字节的缓冲区里缓冲数据。主机端包含了一个“键盘控制器”与键盘处理器进行通讯,并解码来自键盘处理器的信息,然后高速系统当前按键对应的处理事情。主机与键盘之间的通讯仍旧采用IBM的协议。
键盘处理器花费很多时间来扫描或监视按键矩阵。如果发现有按键按下、释放或长按,键盘就发送“扫描码”的信息到主机。扫描码有两种不同的类型:“通码”和“断码”。当一个键被按下去或长按的时候,键盘就发送通码;当一个键被释放的时候,键盘就发送断码。每个键盘被分配了唯一的通码和断码,这样主机通过查找唯一的扫描码就可以确定是哪个按键被按下或释放。每个键一整套的通断码组成了“扫描码集”,现在所有的键盘都采用第二套扫描码。由于没有一个简单的公式可以计算扫描码,所以要知道某个特定按键的通码和断码,只能采用查表的方法来获得。需要特别注意的是,按键的通码值表示键盘上的一个按键,并不表示印刷在按键上的那个字符,这就意味着通码和ASCII码之间没有任何关联。
另外,第二套通码都只有一个字节宽,但也有少数“扩展按键”的通码是两字节或四字节宽,这类码的第一个字节总是0xE0。与通码一样,每个按键在释放的时候,键盘就会发送一个断码。每个键也都有它自己的唯一的断码,不过庆幸的是,断码与断码之间存在着必然的联系。多数第二套断码有两个字长,它们的第一个字节是0xF0,第二个字节就是对应按键的通码。扩展按键的断码通常有三个字节,前两个字节0xE0和0xF0,最后一个字节是这个按键通码的最后一个字节。表2-1列出了键盘的扫描码。
键值 通码 断码 A B C D E F G 1C 32 21 23 24 2B 34 F0,1C F0,32 F0,21 F0,23 F0,24 键值 9 ` - = \\ 通码 断码 46 0E 4E 55 5C 66 29 F0,46 键值 [ 通码 断码 54 67 6E 6F 65 F0,54 F0,67 F0,6E F0,6F F0,64 F0,65 F0,0E INSERT F0,4E HOME F0,55 PG UP F0,66 END F0,5C DELETE 64 F0,29 PG DN F0,2B BKSP F0,34 SPACE 6D F0,6D 第6页(共32页)
键盘驱动程序 H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 33 43 3B 42 4B 31 44 15 1B 2C 3C F0,33 F0,48 TAB CAPS 0D F0,0D 14 12 11 8B 19 59 58 8C 39 F0,14 F0,12 F0,11 U 63 ARROW L 61 ARROW D 60 ARROW F0,63 F0,61 F0,60 F0,3B L SHFT F0,42 L CTRL F0,4B L WIN F0,31 R SHFT F0,44 R CTRL F0,15 R ALT F0,1B ENTER F0,2C F0,3C ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRNT SCRN R 6A F0,6A ARROW 76 7E 4E 7C 79 71 70 69 72 6B 73 74 6C 75 5B 4C 52 41 49 F0,76 F0,7E F0,4E F0,7C F0,79 F0,71 F0,70 F0,69 F0,72 F0,6B F0,73 F0,74 F0,6C F0,75 F0,5B F0,4C F0,52 F0,41 F0,49 KP / KP * KP - KP + KP . KP 0 KP 1 KP 2 KP 3 KP 4 KP 5 KP 6 KP 7 KP 8 KP 9 ] ; ' , . / 4A F0,4A F0,8B NUM F0,19 F0,59 F0,58 F0,8C 3A F0,3A L ALT 4D F0,4D R WIN 2D F0,2D APPS F0,39 KP EN 8D F0,8D 5A F0,5A 08 07 0F 17 1F 27 2F 37 3F 47 4F 56 5E 57 F0,08 F0,07 F0,0F F0,17 F0,1F F0,27 F0,2F F0,37 F0,3F F0,47 F0,4F F0,56 F0,5E F0,57 F0,5F F0,62 2A F0,2A 1D F0,1D 22 35 45 16 1E 26 25 2E 36 F0,22 F0,35 F0,45 F0,16 F0,1E F0,26 F0,25 F0,2E F0,36 7A F0,7A 1A F0,1A 7D F0,7D 3D F0,3D SCROLL 5F 3E F0,3E PAUSE 62 4A F0,4A 表2-1 PS2键盘扫描码
2.5 动态扫描模块
本次设计所用的实验箱FPGA的引脚都和相应的实验开发模块固化了,并且有些引脚在几个模块里有重复定义。在EDA中不允许一个引脚同时两个模块使
第7页(共32页)
键盘驱动程序
用。在本设计中,八位七段数码管和16*16点阵的部分管脚被重复定义,若要同时显示,就要用到动态扫描。当扫描频率达到一定值时,效果就会和静态显示一样。这样既解决了引脚冲突的问题,又有效的节约了硬件资源。同时,实验也达到了预期的效果。
第8页(共32页)
键盘驱动程序
参考文献
[1] SOPCIIEDA实验指导书(第二版)[M]. [2] SOPCII使用手册(第二版)[M].
[3] 谭会生.EDA技术基础[M].湖南大学出版社,2004.
[4] 潘松,黄继业.EDA技术实用教程(第二版)[M].科学出版社,2005.
第14页(共32页)
键盘驱动程序
附录
附录A 八位七段数码管显示程序
library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all;
-------------------------------------------------------------------- entity led is
port( clk : in std_logic; --Clock Signal
data_in : in std_logic_vector(7 downto 0); --data bus
ledag : out std_logic_vector(6 downto 0); --定义七位输出信号 sel : out std_logic_vector(2 downto 0) --ledag Select ); end led;
-------------------------------------------------------------------- architecture behave of led is
signal dcount : std_logic_vector(2 downto 0); signal adh,adl : std_logic_vector(6 downto 0); signal adcount : std_logic_vector(7 downto 0); signal din_h,din_l : std_logic_vector(3 downto 0); signal coclk : std_logic; begin
process(clk) --out enable signal begin
if(clk'event and clk='1') then if adcount=\ coclk<='1';
adcount<=\ else
adcount<=adcount+1; coclk<='0'; end if; end if; end process;
process(clk) --rd the adc data
第15页(共32页)
键盘驱动程序
begin
if(clk'event and clk='1') then
din_h<=data_in(7 downto 4); din_l<=data_in(3 downto 0); end if; end process; process(clk) begin
case din_h is
when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when others=>adh<=adh; end case; case din_l is
when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \ when \第16页(共32页)
--display 0 --display 1 --display 2 --display 3 --display 4 --display 5 --display 6 --display 7 --display 8 --display 9 --display a --display b --display c --display d --display e --display f --no change --display 0 --display 1 --display 2 --display 3 --display 4 --display 5 --display 6 --display 7 --display 8 --display 9 --display a --display b --display c --display d --display e --display f
键盘驱动程序
when others=>adl<=adl; --no change end case; end process;
process(coclk) --display process begin
if(coclk'event and coclk='1') then dcount<=dcount+1; sel<=dcount; case dcount is
when \ when \ when \ when \ when \
when \ when \ when \ when others=>ledag<=\ end case; end if; end process; end behave;
第17页(共32页)
键盘驱动程序
附录B 16*16点阵显示程序
library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all;
-------------------------------------------------------------------- entity dot is
port( data_in : in std_logic_vector(7 downto 0); --data bus clk : in std_logic; --时钟输入
dotc : out std_logic_vector(15 downto 0); --点阵列控制 dotr : out std_logic_vector(15 downto 0) --点阵行显示 ); end dot;
-------------------------------------------------------------------- architecture behave of dot is
signal cdount : std_logic_vector(3 downto 0); begin
process(clk) --显示时序控制 begin
if clk'event and clk='1' then if cdount<15 then cdount<=cdount+1; else
cdount<=\ end if; end if; end process; process(cdount) begin
case cdount is
when \列选择(lg7088Ah) when \ when \ when \ when \ when \ when \ when \ when \
第18页(共32页)
键盘驱动程序
when \ when \ when \ when \ when \ when \ when \ when others=>dotc<=\ end case;
if data_in=\ then case cdount is
when \列显示显示1 when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=\ then case cdount is
when \列显示显示2 when \when \when \when \when \when \when \when \when \when \when \when \
第19页(共32页)
键盘驱动程序
when \when \when \
when others=>dotr<=\ end case;
elsif data_in=\ then case cdount is
when \列显示显示3 when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=107 then case cdount is
when \列显示显示4 when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\
第20页(共32页)
键盘驱动程序
end case;
elsif data_in=115 then case cdount is
when \列显示显示5 when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=116 then case cdount is
when \列显示显示6 when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示7
第21页(共32页)
键盘驱动程序
when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示8 when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示9 when \when \when \when \
第22页(共32页)
键盘驱动程序
when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示0 when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示. when \when \when \when \when \when \when \when \
第23页(共32页)
键盘驱动程序
when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示+ when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示- when \when \when \when \when \when \when \when \when \when \when \when \
第24页(共32页)
键盘驱动程序
when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示/ when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示* when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\
第25页(共32页)
键盘驱动程序
end case;
elsif data_in=x\ then case cdount is
when \列显示显示Numlock when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case;
elsif data_in=x\ then case cdount is
when \列显示显示ENTER when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case; else
case cdount is
when \列显示显示E
第26页(共32页)
键盘驱动程序
when \when \when \when \when \when \when \when \when \when \when \when \when \when \when \
when others=>dotr<=\ end case; end if; end process; end behave;
第27页(共32页)
键盘驱动程序
附录C 键盘扫描程序
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.all; USE IEEE.STD_LOGIC_ARITH.all;
USE IEEE.STD_LOGIC_UNSIGNED.all;
--------------------------------------------------------------------- ENTITY keyboard IS
PORT( keyboard_clk, keyboard_data, clk , reset, read : IN STD_LOGIC; scan_code : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); scan_ready : OUT STD_LOGIC); END keyboard;
--------------------------------------------------------------------- ARCHITECTURE rtl OF keyboard IS SIGNAL INCNT : std_logic_vector(3 downto 0); SIGNAL SHIFTIN : std_logic_vector(8 downto 0); SIGNAL READ_CHAR : std_logic; SIGNAL INFLAG, ready_set : std_logic; SIGNAL keyboard_clk_filtered : std_logic; SIGNAL filter : std_logic_vector(7 downto 0); BEGIN
PROCESS (read, ready_set) BEGIN
IF read = '1' THEN scan_ready <= '0';
ELSIF ready_set'EVENT and ready_set = '1' THEN scan_ready <= '1'; END IF;
END PROCESS;
--This process filters the raw clock signal coming from the keyboard using a shift register and two AND gates Clock_filter: PROCESS BEGIN
WAIT UNTIL clk'EVENT AND clk= '1';
filter (6 DOWNTO 0) <= filter(7 DOWNTO 1) ; filter(7) <= keyboard_clk;
IF filter = \
ELSIF filter= \
第28页(共32页)
键盘驱动程序
END IF;
END PROCESS Clock_filter;
--This process reads in serial data coming from the terminal PROCESS BEGIN WAIT UNTIL (KEYBOARD_CLK_filtered'EVENT KEYBOARD_CLK_filtered='1'); IF RESET='1' THEN
INCNT <= \ READ_CHAR <= '0'; ELSE
IF KEYBOARD_DATA='0' AND READ_CHAR='0' THEN READ_CHAR<= '1'; ready_set<= '0'; ELSE -- Shift in next 8 data bits to assemble a scan code IF READ_CHAR = '1' THEN IF INCNT < \ INCNT<= INCNT + 1;
SHIFTIN(7 DOWNTO 0) <= SHIFTIN(8 DOWNTO 1); SHIFTIN(8) <= KEYBOARD_DATA; ready_set <= '0'; -- End of scan code character, so set flags and exit loop ELSE
scan_code<= SHIFTIN(7 DOWNTO 0); READ_CHAR<='0'; ready_set<= '1'; INCNT<= \ END IF; END IF; END IF; END IF;
END PROCESS; END rtl;
第29页(共32页)
AND
键盘驱动程序
附录D 动态扫描程序
library ieee;
use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all;
-------------------------------------------------------------------- entity scan is
port( clk : in std_logic; --clock signal ledag_in:in std_logic_vector(6 downto 0);
sel_in : in std_logic_vector(2 downto 0); dotc_in : in std_logic_vector(15 downto 0); dotr_in : in std_logic_vector(15 downto 0); dotc : out std_logic_vector(15 downto 0); sel : out std_logic_vector(2 downto 0); dotr0,dotr1_ledag7,dotr2_ledag6,dotr3_ledag5, dotr4_ledag4,dotr5_ledag3,dotr6_ledag2, dotr7_ledag1,dotr8,dotr9,dotr10, dotr11,dotr12,dotr13,dotr14,dotr15 : out std_logic ); --ledag Select end scan;
-------------------------------------------------------------------- architecture behave of scan is begin
process(clk) --out enable signal begin if clk='1' then sel<=sel_in; dotc<=\ dotr1_ledag7<=ledag_in(6); dotr2_ledag6<=ledag_in(5); dotr3_ledag5<=ledag_in(4); dotr4_ledag4<=ledag_in(3); dotr5_ledag3<=ledag_in(2); dotr6_ledag2<=ledag_in(1); dotr7_ledag1<=ledag_in(0); dotr0<='0'; else dotc<=dotc_in;
第30页(共32页)
键盘驱动程序
sel<=\ dotr0<=dotr_in(0); dotr1_ledag7<=dotr_in(1); dotr2_ledag6<=dotr_in(2); dotr3_ledag5<=dotr_in(3); dotr4_ledag4<=dotr_in(4); dotr5_ledag3<=dotr_in(5); dotr6_ledag2<=dotr_in(6); dotr7_ledag1<=dotr_in(7); dotr8<=dotr_in(8); dotr9<=dotr_in(9); dotr10<=dotr_in(10); dotr11<=dotr_in(11); dotr12<=dotr_in(12); dotr13<=dotr_in(13); dotr14<=dotr_in(14); dotr15<=dotr_in(15); end if; end process; end behave;
第31页(共32页)
键盘驱动程序
附录E 总电路图
第32页(共32页)
百度搜索“70edu”或“70教育网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,70教育网,提供经典综合文库EDA课程设计-键盘驱动程序在线全文阅读。
相关推荐: