FPGA控制的PS2接口电路设计毕业论文毕业设计.doc_第1页
FPGA控制的PS2接口电路设计毕业论文毕业设计.doc_第2页
FPGA控制的PS2接口电路设计毕业论文毕业设计.doc_第3页
FPGA控制的PS2接口电路设计毕业论文毕业设计.doc_第4页
FPGA控制的PS2接口电路设计毕业论文毕业设计.doc_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

FPGA控制的PS/2接口电路设计摘要:PS2作为键盘接口至今仍在广泛使用。本论文根据PS2键盘接口的协议,用VHD语言编程,用FPGA控制PS2,使其能够接收从键盘键入的信息,并把它显示在数码管和液晶显示频上。The Design of PS / 2 Interface Circuit by Control of FPGAAbstract:Today,PS2 keyboard interface is still being used widely.This report is based PS2 keyboard interface protocol, with VHD language programming, using FPGA control PS2, so that it can receive information from the keyboard to type, and display it in the digital frequency of the tube and liquid crystal display.关键词:VHDL,FPGA , PS2, QuartusII引言:PS2是一类应用广泛的键盘接口。本文论述了用FPGA控制PS2的设计思想及方法,并实现把按键的扫描码及其对应的ASCII码显示在LED及LCD上。设计原理 通过分析,本次设计需要分四部分实现:1.接收从键盘发出的扫描码信息2.把接收到的扫描码转换成ASCII码3.把扫描码和ASCII码显示在数码管上4.把扫描码和ASCII码显示在LED液晶上。1.PS2键盘接口协议介绍PS2协议和接口最初是由IBM公司开发并广泛使用的应用于键盘/鼠标的协议和接口。PS2键盘接口是6芯的插头,各插头定义如下: 1 DATA Key Data 2 n/c Not connected 3 GND Gnd 4 VCC Power , +5 VDC 5 CLK Clock 6 n/c Not connected 在PS2的6个芯中,2和6未定义,3和4为电源和地,需要用FPGA控制的只有1(数据)和5(时钟)。2.把从键盘发出的数据转换成扫描码 每当有按键按下或弹起时键盘都会发出一帧或几帧数据,每一帧数据一共都12位,其数据格式如下表所示:1个起始位总是逻辑08个数据位(LSB)低位在前1个奇偶校验位奇校验1个停止位总是逻辑11个应答位仅用在主机对设备的通讯中 从键盘发出的数据是在时钟信号的下降沿的时候才被读取,FPGA要想接收到键盘发出的数据就要配合PS2的时序。具体设计思路如下: 首先我们来定义几个端口。首先要有数据输入端口K_DATA和键盘时钟K_CLOCK。K_DATA是从键盘发出的一位一位串行数据,我们要在K_CLOCK的下降沿到来时接收这12位串行数据,并最终输出我们想要的中间1至8位数据。这8位输出我们用DATASCAN来表示。另外再对整个系统设置一个复位信号RST。为了方便接收数据,我们有必要定义一个计数器COUNT,使它对K_CLOCK键盘时钟计数,COUNT的值在0到11之间变化,COUNT等于11时清零,其余自加1。另外再定义一个接收键盘数据的中间变量TMPDATA,每当检测到K_CLOCK下降沿到来时,就把DATA的值赋给TMPDATA,这样,当K_CLOCK的12个下降沿到来时,TMPDATA就接收到了键盘发出的全部12位数据。在程序中,我们还要定义一个串并转换结束的标志信号FLAG,当COUNT大于8时就可以把FLAG置为1,当检测到FLAG变为1时,就把TMPDATA的1至8位赋给输出端口DATA,这样,我们就得到了想要的8位扫描码输出。为了和下一步的扫描码转换成ASCII码建立联系,我们还要定义一个触发中断信号INTERRUPT1,当COUNT等于11的时候把INTERRUPT1置1触发中断,作为扫描码转换为ASCII码的使能信号。这部分电路的仿真结果如下(以输出1C为例):3.把扫描码转换成ASCII码 把扫描码转换成ASCII码的目的是为了识别按键。现在,我们已经有了从键盘发出的扫描码信息,那么,如何根据这些扫描码信息来区分按下的是哪一个键呢? 实际上,键盘接口中的微处理器负责扫描或监视按键的动作,如果发现有按键按下,按住或者释放,键盘将会发送扫描码的信息包。扫描码有通码和断码两种,当一个按键按下或按住,键盘就向接口发送一个字节的键盘接通的扫描码,称为通码。当该按键弹起或释放时,键盘向接口发送两个字节的键盘断开的扫描码,称为断码。断码和通码有一定的联系,多数第二套断码有两字节长。它们的第一个字节是F0 ,第二个字节是这个键的通码。扩展按键的断码通常有三个字节,它们前两个字节是E0h,F0h ,最后一个字节是这个按键通码的最后一个字节。键盘每个按键被分配了唯一的通码和断码。这样,我们通过查找唯一的通码和断码就可以确定按下的是哪一个键。每个键一整套的通断码组成了扫描码集。有三套标准的扫描码集,所有现代的键盘默认使用第二套扫描码。 有了这个基础,我们就可以设计程序把扫描码转换成ASCII码了。这部分的核心是查表。需要注意的是当Shift键和CapsLock键按下时的不同结果。我们同样先来定义几个端口。用scan作为扫描码的输入端口,CLK作为时钟信号,它与上一个扫描码输出电路的触发中断信号INTERRUPT1相连接。定义DATAASCII为最终的ASCII码输出。另外再定义一个ASCII码转换结束的中断信号INTERRUPT2。 整个转换的思路是,由接收过来的扫描码的值,通过查表判断这个扫描码对应的是哪一个按键,再在ASCII表中查找这个按键的ASCII值,然后把按键的ASCII值输出。这里面牵扯到组合键的问题。即Shift和Capslock这两个键有没有按下。为了判断组合键有没有按下,我们设计几个触发器来保存上一个时钟的特殊组合键的状态,以便后来的ASCII码转换。当检测到有这两个按键按下时,就把相应的Shifted_D或Capslocked_D置为1,然后再通过D触发器把这两个键的状态锁存起来。锁存后为Shifted和Capslocked。判断这两个键按下的依据是判断扫描码的值,若扫描码的值对应的是这两个按键,就可以把相应的键的状态置1。在转换时我们先不管组合键有没有按下,先根据扫描码的值通过查表找到它的ASCII值,最后再判断组合键有没有按下。具体操作是,当接收到扫描码时,先判断扫描码的值是否为Shift或Capslock的扫描码值,如果是的话就表示有组合键按下了,这时把Shifted_D或Capslocked_D置1,否则置0.转换成的ASCII码用TMPASCII表示。当这些工作完成以后,再判断Shifted或Capslocked的值是否为1,若这两个值都为1或0,则应为小写,这时就需要把前得到的TMPASCII的值加上十六进制的“20”。当然,这些大小写转换是针对ASCII值在“A”和“a”之间而言的。另外,有些键上面有上下两排字符,当Shift键按下时用到的是上面一排,这个应该注意。解决这个问题的方法很简单,由于在前面我们已经把Shift键前一个状态锁存起来,在进行扫描码到ASCII码转换的时候,若遇到有两排字符的键时,先判断Shifted是否为1,若为1则转换上面字符的ASCII值就行了。最后我们把转换得到的值赋给一个信号ASCII。若没有按键按下或扫描码对应的不是键盘的126个键,则把ASCII赋成“10000000”。在转换中我们还应该考虑一个问题。比如我们要显示小写的a这个字母,当按下a再弹起时我们接收到的一串扫描码应该为1C,F0,1C。再比如我们要显示大写的字母A,应该是先按Shift键,再按A键,然后弹起A键,再弹起Shift键。那么我们接收到的扫描码就该为:12,1C,F0,1C,F0,12。我们接收到这么些扫描码,而我们要输出的ASCII码应该为61(A为小写时)和41(A为大写时)。如果我们都一一转换的话会出错。注意到如果我们在“F0”扫描码到来时才进行转换就可以解决问题了。因此,在转换前先判断扫描码是不是为F0,若是的话就代表断码到来了,这时把定义好的DUANMA_D置1,否则置0,再把它锁入锁存器,输出为DUANMA,在进行ASCII码转换时,我们都把DUANMA等于1作为转换的一个条件,这样就可以得到正确的ASCII码值了。接下来的问题是,我们应该在什么时候把转换成的ASCII码输出呢?在前面,我们把没有转换的ASCII信号赋为“10000000”,所以,每当CLK下降沿到来时,我们去检测ASCII的后7位是否为“0000000”,若不是则说明已经转换结束了,这时我们给程序一个转换结束标志FLAG,当检测到FLAG上升沿到来时,把ASCII的值传递给最终的ASCII码输出端口DATAASCII,同时触发中断INTERRUPT2。这部分电路的仿真结果如下(以输出大写和小写字母A的ASSCII码值为例):4.把扫描码及ASCII码值显示在数码管上经过前两部分的设计分析,我们已经得到了按键的扫描码值和ASCII码值。我们要用动态扫描的方法把这两个值显示在数码管上。显示这两个键值需要点亮4个数码管。实现动态扫描的原理就是使这4个数码管依次点亮,由于依次点亮的时间间隔很短,而人都有一定时间的视觉暂留,所以就会看到4个数码管同时点亮。为了依次点亮4个数码管,我们定义一个计数器CNT,CNT在“00”到“11”之间变化。CNT每变化依次,我们把相应的段选信号输出到对应的数码管,那么,当CNT连续变化很快时,我们就可以看到四个数码管点亮了。接下来的问题是,段选信号如何获得?容易想到,段选信号就是扫描码的高四位、低四位和ASCII码的高四位、低四位所对应的数字的段选信号。所以我们要把扫描码和ASCII码的高四位、低四位分别求出来。而扫描码和ASCII码的值我们提前是不知道的,所以我们要建立一个对照表,我们先把扫描码和ASCII码的高四位和低四位放在四个变量中,然后分别判断这四位对应的是0到F之间的哪一个数,然后求出这个数对应的段选信号,并把它放在信号中,等到相应的CNT到来时,把这个段选信号输出到数码管就行了。5.把扫描码及ASCII码显示在LCD液晶屏上在这里要用到LCD1602。LCD1602为一个16位,两行的液晶显示频,我们要想把键值显示在LCD上,只要按照它的协议来做就行了。 LCD接收数据有它对应的时钟,这个我们可以通过分频产生。当时钟到来时,我们要决定是送指令还是数据,是读还是写,还要送入相应的指令或数据信息。根据要求,我们要在上面一行显示“Scancode:*”,第二行显示:“ASCIIcode:*”。在显示这些字符之前,必须先做以下准备:1.开显示 2.使指针自加1 3.清屏 4.设置显示模式(这里用5*7显示模式)。做完这几步工作才可以传递数据。首先给LCD一个指令,让指针指到第一行的第一个点阵(当然,如果不想从第一个点阵开始显示,也可以把指针指到其它地方)。在下一个时钟到来时,就要依次把“Scancode:”这几个字符的ASCII值赋给数据端口,接下来就该显示扫描码值了。显示扫描码的值比较麻烦,因为扫描码是提前未知的,所以我们还得先解码。做这部分的工作和LED显示部分一样,也是要提前先建立一个对照表,求出扫描码和ASCII码的高四位和低四位对应的是0到F之间的哪一个数据,不同的是不再把数据对应的段选信号赋给对应的变量了,而是把数据所对应的ASCII码值赋给变量。因为LCD要接收ASCII码值然后显示ASCII值对应的字符。有了这部分工作,当轮到显示扫描码时,就要把前面得到的扫描码高、低四位对应数据的ASCII码送到数据端口就行了。扫描码显示完后,就该显示ASCII码了,这时指针不能自加1了,而应该跳到下一行显示。所以应该把下一行第一个点阵的地址赋给数据端口,然后再依次把“ASCIIcode:”这几个字符的ASCII码值赋给数据端口,然后再把ASCII码高、低四位对应数据的ASCII码值送到数据端口,这样就可以显示出ASCII码的数据了。6.设计顶层文件 当前面四个模块都设计完成以后,就可以设计顶层文件了,也就是把相应的模块连接起来。在这里我们用端口映射的方法。具体链接在这里就不再赘述了。顶层文件设计完成后,整体编译一遍,然后进行RTL级仿真,便得到如下所示的硬件连接电路:结束语本次的PS2键盘接口设计,总的来说,实现了4大功能:1,用FPGA控制PS2键盘接口,接收键盘发出的扫描码数据2.把接收到的扫描码转换成ASCII码3.把扫描码和ASCII码显示在数码管上4.把扫描码和ASCII码显示在LCD液晶上。这四个功能的设计,基本上涵盖了平时讲课的大部分内容。对我们来说这是一次很好的锻炼机会,也使我们对实际系统的设计掌握了一定的经验,提升了我们对这门课的理解,同时培养了我们编程和写论文的能力。回想自己所设计的程序,里面还有很多瑕疵,比如显示扫描码时部分,每显示一个键需要接收至少3个字节(按下时键盘发出一个字节的通码,弹起时发送两个字节的断码)的数据,比如显示大写字母A的一串扫描码为12,1C,F0,1C,F0,12。这5个扫描码将会分别显示在数码管和液晶上,而其实我们更希望只显示1C。想改进的话可以在扫描码转换为ASCII码部分,把最后得到的ASCII码再反过来求出按键的扫描码,这样又要建立一个大的对照表,但目前也只能想到这个方法,而且比较麻烦,所以不再设计。另外,根据所设计的程序的功能,只有当按键弹起时才能把按键的信息显示出来,而实际上我们希望当按住键不放时也能显示键值信息。更多需要改进的地方这里就不再列举了。总之,这次的设计真的使我受益匪浅。参考文献1 侯伯亨,刘凯,顾新. VHDL硬件描述语言与数字逻辑电路设计【M】.西安:西安电子科技大学出版社,20092 刘勇 ,王玉晶,曲斌,于洋.1种嵌入式 PC 非标准键盘的设计【M】.微计算机信息,2007,23-1:8788。3 苗新法,王秀华.PS2键盘在嵌入式系统中的应用研究【M】.兰州:兰州交通大学学报(自然科学版), 2007(1).4 徐晓 , 汪道辉 .标准PS2键盘与单片机的接口设计【J】.中国测试技术, 2005(1).5 王勇.电子设计自动化实验指导书【M】.河南科技大学:电子信息工程学院,2009.电路设计源程序:-接收键盘发出的扫描码library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use ieee.std_logic_arith.all;entity keyboard isport(k_data:in std_logic; k_clock:in std_logic; rst:in std_logic; datascan:out std_logic_vector(7 downto 0); interrupt1:out std_logic);end keyboard;architecture one of keyboard is signal tmpdata:std_logic_vector(11 downto 0):=000000000000; signal flag:std_logic; signal count:integer range 0 to 11;beginprocess(rst,k_clock)begin if(rst=1)then count=0; elsif(k_clockevent and k_clock=0)then if(count=11)then count=0;else count=count+1;tmpdata(count)=k_data;end if; end if;end process;process(count)begin if(count=10)then flag=1; else flag=0; end if;end process;process(flag,rst)begin if(rst=1)then interrupt1=0; elsif(flagevent and flag=1)then interrupt1=1;datascan=tmpdata(8 downto 1); end if;end process;end;-把扫描码转换成ASCII码library ieee;use ieee.std_logic_1164.all;entity dff isport(clk:in std_logic; d:in std_logic; q:out std_logic);end dff;architecture one of dff is signal tmp:std_logic;begin process(clk) beginif(clkevent and clk=1)thentmp=d;end if; end process; q=tmp;end;library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use ieee.std_logic_arith.all;entity convert isport(scan:in std_logic_vector(7 downto 0); rst:in std_logic; clk:in std_logic; dataascii:out std_logic_vector(7 downto 0); interrupt2:out std_logic);end convert;architecture one of convert issignal tmpASCII:integer range 0 to 16#7F#;signal ASCII:std_logic_vector(7 downto 0);signal duanma_D:std_logic:=0;signal shifted_D:std_logic:=0;signal capslocked_D:std_logic:=0;signal duanma:std_logic:=0;signal shifted:std_logic:=0;signal capslocked:std_logic:=0;signal flag:std_logic;component dff isport(clk:in std_logic; d:in std_logic; q:out std_logic);end component;beginduanma_D=1 when scan=xF0else 0;shifted_D=0 when rst=1 elsenot shifted when(scan=x12 or scan=x59)elseshifted;capslocked_D=0 when rst=1 elsenot capslocked when(scan=x58 and duanma=1)elsecapslocked; tmpAscii=16#09# when scan=00001101 else16#60# when scan=00001110 and shifted=0 else16#7E# when scan=00001110 and shifted=1 else16#51# when scan=00010101 else16#31# when scan=00010110 and shifted=0 else16#21# when scan=00010110 and shifted=1 else16#5A# when scan=00011010 else16#53# when scan=00011011 else16#41# when scan=00011100 else16#57# when scan=00011101 else16#32# when scan=00011110 and shifted=0 else16#40# when scan=00011110 and shifted=1 else16#43# when scan=00100001 else16#58# when scan=00100010 else16#44# when scan=00100011 else16#45# when scan=00100100 else16#34# when scan=00100101 and shifted=0 else16#24# when scan=00100101 and shifted=1 else16#33# when scan=00100101 and shifted=0 else16#23# when scan=00100101 and shifted=1 else16#20# when scan=00101001 else16#56# when scan=00101010 else16#46# when scan=00101011 else16#54# when scan=00101100 else16#52# when scan=00101101 else16#35# when scan=00101110 and shifted=0 else16#25# when scan=00101110 and shifted=1 else16#4E# when scan=00110001 else16#42# when scan=00110010 else16#48# when scan=00110011 else16#47# when scan=00110100 else16#59# when scan=00110101 else16#36# when scan=00110110 and shifted=0 else16#5E# when scan=00110110 and shifted=1 else16#4D# when scan=00111010 else16#4A# when scan=00111011 else16#55# when scan=00111100 else16#37# when scan=00111101 and shifted=0 else16#26# when scan=00111101 and shifted=1 else16#38# when scan=00111110 and shifted=0 else16#2A# when scan=00111110 and shifted=1 else16#2C# when scan=01000001 and shifted=0 else16#3C# when scan=01000001 and shifted=1 else16#4B# when scan=01000010 else16#49# when scan=01000011 else16#4F# when scan=01000100 else16#30# when scan=01000101 and shifted=0 else16#29# when scan=01000101 and shifted=1 else16#39# when scan=01000110 and shifted=0 else16#28# when scan=01000110 and shifted=1 else16#2E# when scan=01001001 and shifted=0 else16#3E# when scan=01001001 and shifted=1 else16#2F# when scan=01001010 and shifted=0 else16#3F# when scan=01001010 and shifted=1 else16#4C# when scan=01001101 else16#3B# when scan=01001100 and shifted=0 else16#3A# when scan=01001100 and shifted=1 else16#50# when scan=01001101 else16#2D# when scan=01001110 and shifted=0 else16#5F# when scan=01001110 and shifted=1 else16#27# when scan=01010010 and shifted=0 else16#22# when scan=01010010 and shifted=1 else16#5B# when scan=01010100 and shifted=0 else16#7B# when scan=01010100 and shifted=1 else16#3D# when scan=01010101 and shifted=0 else16#2B# when scan=01010101 and shifted=1 else16#0D# when scan=01011010 else16#5D# when scan=01011011 and shifted=0 else16#7D# when scan=01011011 and shifted=1 else16#5C# when scan=01011101 and shifted=0 else16#7C# when scan=01011101 and shifted=1 else16#08# when scan=01100110 else16#1B# when scan=01110110; ascii16#40#) and (tmpAscii=16#5A#)and duanma=1 else conv_std_logic_vector(tmpAscii,8)when duanma=1 else 10000000;u1:dff port map(clk,duanma_D,duanma);u2:dff port map(clk,shifted_D,shifted);u3:dff port map(clk,capslocked_D,capslocked);process(rst,clk)beginif(rst=0)then if(clkevent and clk=0)then if(ASCII(6 downto 0)/=0000000)then flag=1; else flag=0; end if; end if;end if;end process;process(flag)beginif(flag=1)then dataascii=ascii; interrupt2=1;else interrupt2=0;end if;end process;end;-把扫描码和ASCII码显示在LED数码管上library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity leddisp isport(rst:in std_logic; enabl:in std_logic; clk:in std_logic; data_scan:in std_logic_vector(7 downto 0); data_ascii:in std_logic_vector(7 downto 0); sg:out std_logic_vector(6 downto 0);end;architecture one of leddisp issignal data_scan_h:std_logic_vector(3 downto 0);signal data_scan_l:std_logic_vector(3 downto 0);signal data_ascii_h:std_logic_vector(3 downto 0);signal data_ascii_l:std_logic_vector(3 downto 0);signal cnt:std_logic_vector(1 downto 0);signal a,b,c,d:std_logic_vector(6 downto 0);begin process(rst,enabl)beginif(rst=0)then if(clkevent and clk=1)then data_scan_h=data_scan(7 downto 4); data_scan_l=data_scan(3 downto 0); data_ascii_h=data_ascii(7 downto 4); data_ascii_laaaaaaaaaaaaaaaanull; end case; case data_scan_l iswhen 0000 =bbbbbbbbbbbbbbbbnull; end case; case data_ascii_h iswhen 0000 =ccccccccccccccccnull; end case; case data_ascii_l iswhen 0000 =ddddddddddddddddnull; end case;end process; process(enabl,clk) beginif(rst=1)then cnt=00;elsif(clkevent and clk=1)then if(cnt=11)then cnt=00; else cntsgsgsgsgnull; end case;end if; end process;end;-把扫描码和ASCII码显示在LED液晶上library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use ieee.std_logic_arith.all;entity lcddisp isport(rst:in std_logic; clk:in std_logic; enabl:in std_logic; data_scan:in std_logic_vector(7 downto 0); data_ascii:in std_logic_vector(7 downto 0); data:out std_logic_vecto

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论