SP2键盘Word文档下载推荐.docx

上传人:b****7 文档编号:21828306 上传时间:2023-02-01 格式:DOCX 页数:17 大小:771.38KB
下载 相关 举报
SP2键盘Word文档下载推荐.docx_第1页
第1页 / 共17页
SP2键盘Word文档下载推荐.docx_第2页
第2页 / 共17页
SP2键盘Word文档下载推荐.docx_第3页
第3页 / 共17页
SP2键盘Word文档下载推荐.docx_第4页
第4页 / 共17页
SP2键盘Word文档下载推荐.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

SP2键盘Word文档下载推荐.docx

《SP2键盘Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《SP2键盘Word文档下载推荐.docx(17页珍藏版)》请在冰豆网上搜索。

SP2键盘Word文档下载推荐.docx

上面只是简单的介绍了PS2从机到主机的通信协议,我们知道了键盘是一个字节一个字节的往主机发送数据的,但是,每个字节代表了什么内容呢,我们还需要对照键盘编码对照表来查看。

键盘扫描码分为第一套扫描码、第二套扫描码和第三套扫描码,我们日常生活中常见的扫描码绝大多数采用第二套扫描码,因此这里小梅哥就只附上第二套扫描码的内容。

实际一个按键由按下到释放时键盘将按照如下的规定往主机发送数据:

只要一个键被按下,这个键的通码(MAKE)就被发送到计算机。

通码只表示键盘上的一个按键,它不表示印刷在按键上的那个字符。

这就意味着在通码和ASCII码之间没有已定义好的关联,直到主机把扫描码翻译成一个字符或命令。

虽然多数第二套通码都只有一个字节宽,但也有少数“扩展按键”的通码是两字节或四字节宽,这类的通码第一个字节总是为E0H(如“END”、“HOME”……)。

正如键按下通码就被发往计算机一样,只要键一释放,断码就会被发送。

每个键都有它自己唯一的通码,它们也都有唯一的断码。

幸运的是,你不用总是通过查表来找出按键的断码――在通码和断码之间存在着必然的联系。

多数第二套断码有两字节长,它们的第一个字节是F0H,第二个字节是这个键的通码。

例如,当我们按下键盘上的“A”键时,键盘就会往主机发送”A”键对应的通码(MAKE)”1C”,如果你一直按下这个按键不释放,那么在一个短暂的延时之后,键盘会再次开始,以一定的速率持续向主机发送”1C“,直到该按键被释放。

在该按键被释放后,键盘将会向主机发送“A”的断码(Break),即首先发送“F0”,然后下一个字节再马上发送“1C”。

如果我们按下的是“END”、“PAGEUP”等扩展按键时,会怎么样呢?

这里,以”END”键举例。

当”END“键被按下后,键盘会首先向主机发送“E0”,发送完成后,又会接着发送下一个字节“69”,释放时也与前面的普通按键类似,先发送“E0”,然后发送“F0”,最后再发送“69”。

由上述分析可知,我们FPGA在解码到一次数据后,还需要对这个数据进行分析判断,判断该数据是否为断码标志“F0”以及扩展码标志”E0“。

三、 

硬件设计

PS2电路结构简单,因此这里就略去。

四、 

架构设计

本实验我们进行PS2键盘的解码实验,并将解码到的结果显示在数码管上,同时,为了使我们更加直观的感受到按键被按下和释放,小梅哥在这里增加了一个蜂鸣器,当有按键按下或释放(包括长按时每接收到一个通码)时,蜂鸣器发出一个短暂的响声,来反馈给操作者,让我们知道我们的解码模块解码到了按键信息。

设计结构如下图所示:

图4-1led实验模块组织结构图

详细端口名及其意义如下

表4-1独立按键检测实验端口说明

因为存在模块间的连接,因此有部分内部信号,下表为内部信号的名称和功能说明

表4-2独立按键检测实验内部信号说明

五、 

代码分析

这里,解码的关键是PS2接口的时钟信号,该时钟为异步时钟,我们需要通过边沿检测的方式来检测其下降沿,以便根据下降沿的个数来确定每个时钟我们因该做什么,边沿检测的电路,前面几个实验已经讲过很多次了,这里便不再做过多的解释,贴上代码即可:

regPS2_Clk_Tmp0,PS2_Clk_Tmp1,PS2_Clk_Tmp2,PS2_Clk_Tmp3;

wirenedge_PS2_Clk;

/*PS2从机时钟下降沿检测标志信号*/

always@(posedgeClkornegedgeRst_n)

if(!

Rst_n)begin

PS2_Clk_Tmp0<

=1'

b0;

PS2_Clk_Tmp1<

PS2_Clk_Tmp2<

PS2_Clk_Tmp3<

end

elsebegin

=PS2_Clk;

=PS2_Clk_Tmp0;

=PS2_Clk_Tmp1;

=PS2_Clk_Tmp2;

/*-------获取PS时钟信号的下降沿-------------*/ 

assignnedge_PS2_Clk=!

PS2_Clk_Tmp0&

!

PS2_Clk_Tmp1&

PS2_Clk_Tmp2&

PS2_Clk_Tmp3;

一个PS2的数据包总共由11位组成,因此会有11个时钟下降沿,因此我们必须对下降沿的个数准确计数,才能保证我们能够解码得到正确的数据,这里,使用我们的PS2时钟下降沿标志信号来使能我们的计数器自加,当计数器加到11后,表示一个数据包接收完成,将计数器清零,等待下一个下降沿的到来,相关代码如下:

/*------------PS2时钟下降沿个数计数器-----------------------*/ 

always@(posedgeClkornegedgeRst_n)

Rst_n)

Cnt1<

=4'

d0;

elseif(Cnt1==4'

d11)

elseif(nedge_PS2_Clk)

=Cnt1+1'

b1;

接下来,就是根据时钟下降沿的计数个数,来读取对应位的数据了,因为采用了非阻塞赋值的方式,因此,PS2时钟下降沿到来时,此时Cnt1执行自加1操作,但同时如果也来用Cnt1的值来确定数据位数,就一定会造成错误,因为此时,Cnt1的加1操作并没有执行,而是会在下一个时钟上升沿到来之时才变,因此,为了保证我们使用的Cnt1的数据是已经更新了的,我们需要在Cnt1已经变化之后再来使用其值做判断,即在PS2时钟下降沿检测成功后,滞后一个系统时钟周期后再来读取PS2_Din上的值,比较简单的操作方式就是将PS2时钟下降沿检测标志信号再用寄存器打一拍,对应代码如下:

always@(posedgeClk)nedge_PS2_Clk_Shift<

=nedge_PS2_Clk;

可能这里相对比较难以理解,希望大家结合仿真结果自学揣摩体会。

接下来就是根据Cnt1的计数值来读取每一位的数据了,这部分代码很简单,如下所示:

/*--------------读取8位数据位---------------*/ 

Data_tmp<

=8'

elseif(nedge_PS2_Clk_Shift)begin

case(Cnt1)

4'

d2:

Data_tmp[0]<

=PS2_Din;

d3:

Data_tmp[1]<

d4:

Data_tmp[2]<

d5:

Data_tmp[3]<

d6:

Data_tmp[4]<

d7:

Data_tmp[5]<

d8:

Data_tmp[6]<

d9:

Data_tmp[7]<

default:

=Data_tmp;

endcase 

else

通过以上操作,我们就能正确的解码PS2键盘发送过来的每一个字节的数据了,但是,这些数据代表了什么呢,如果是断码标志,或者是长码标志,我们又该如何进行操作呢,这里,小梅哥先贴上我的处理代码:

always@(posedgeClkornegedgeRst_n)

Break_r<

Key_Valve<

=10'

Key_Flag<

Long_Code_r<

d11)begin

if(Data_tmp==8'

hE0) 

/*判断是否为长码*/

/*将长码标志置1*/

elseif(Data_tmp==8'

hF0) 

/*判断是否为断码*/

/*将断码标志置1*/

elsebegin 

/*检测到的数据为通码*/

={Break_r,Long_Code_r,Data_tmp};

/*将长码标志、断码标志和解码到的按键码输出*/

/*产生解码成功标志信号*/

/*清零长码标志*/

/*清零断码标志*/ 

end 

=Key_Valve;

=Break_r;

=Long_Code_r;

这里,小梅哥使用了两个标志寄存器,当检测数据完成后,即Cnt1=11时,就对解码到到数据进行判断,如果Data_tmp==8'

hE0,则解码到到数据为长码(扩展码)标志,此时便将长码标志寄存器置1,如果Data_tmp==8'

hF0,则解码到到数据为断码标志,此时便将断码标志寄存器置1。

然后,当解码到其他数据(如单字节通码或双子节通码的第二个字节)后,便将解码到的数据连同断码和长码标志寄存器的状态输出,并给出按键检测成功标志(Key_Flag置1)。

六、 

仿真分析

为了对小梅哥设计的PS2键盘解码驱动进行验证,小梅哥编写了一个Testbench来模拟键盘发送数据,通过观察键盘解码驱动的输出来验证该解码模块的正确性,关于模拟键盘发送数据,在一份介绍PS2协议的手册中有如下描述:

我推荐仿真键盘/鼠标采用下面的过程发送一字节的数据到主机:

1) 

等待Clock线为高电平,即等待主机释放Clock线;

2) 

延时50us;

3) 

判断Clock线是否为高电平?

No――跳到第1步;

4)Data线是否为高电平?

No――放弃(跳到从主机读取字节的程序中)。

5) 

延迟20us,输出起始位(0),然后延迟20us,再拉低Clock线保持40us后释放Clock线,形成一个脉冲;

6) 

延时20us,测试Clock线是否为高电平?

7) 

输出第1个数据位,然后延时20us,再拉低Clock线保持40us后释放Clock线,形成一个脉冲;

8) 

重复6-7步发送剩下的7个数据位和校验位;

9) 

因此,我们的模拟键盘发送数据的过程只需要依照上面的流程来即可,这里贴上小梅哥编写的testbench:

`timescale1ns/1ns

modulePS2_Key_Board_Driver_tb;

regClk;

/*systemclock*/

regRst_n;

/*复位信号*/

regPS2_Din;

/*PS2键盘数据线*/

regPS2_Clk;

/*PS2键盘时钟线*/

wireKey_Flag;

/*解码得到键值标志信号*/

wire[9:

0]Key_Valve;

/*解码结果,其中最高位为通/断码识别位,0为通码,1为断码,低八位为码值*/

PS2_Key_Board_Driveru1(

.Clk(Clk),

.Rst_n(Rst_n),

.PS2_Din(PS2_Din),

.PS2_Clk(PS2_Clk),

.Key_Flag(Key_Flag),

.Key_Valve(Key_Valve)

);

initialbegin

Clk=1;

Rst_n=0;

PS2_Din=1;

PS2_Clk=1;

#200;

Rst_n=1;

Key_Event(8'

h1A);

/*Z*/

#400;

h35);

/*X*/

#800;

h44);

/*O*/

#1320;

h4D);

/*P*/

#2560;

h24);

/*E*/

#1230;

h31);

/*N*/

#20000;

Long_Key_Event(8'

h70);

/*"

INSERT"

*/

h6c);

HOME"

h7d);

PAGEUP"

h71);

DELETE"

h69);

END"

h7a);

PAGEDOWN"

#2000000;

$stop;

/*---------生成工作时钟-----------*/

always#10Clk=~Clk;

/*----任务:

以PS2协议发送一个字节的数据-----*/

taskSend_data;

input[7:

0]Data;

begin

PS2_Din=0;

/*发送起始位*/

PS2_Clk=0;

#40000;

PS2_Din=Data[0];

/*发送第0位*/

PS2_Din=Data[1];

/*发送第1位*/

PS2_Din=Data[2];

/*发送第2位*/

PS2_Din=Data[3];

/*发送第3位*/

PS2_Din=Data[4];

/*发送第4位*/

PS2_Din=Data[5];

/*发送第5位*/

PS2_Din=Data[6];

/*发送第6位*/

PS2_Din=Data[7];

/*发送第7位*/

/*暂时

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

当前位置:首页 > 初中教育

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

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