SP2键盘Word文档下载推荐.docx
- 文档编号:21828306
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:17
- 大小:771.38KB
SP2键盘Word文档下载推荐.docx
《SP2键盘Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《SP2键盘Word文档下载推荐.docx(17页珍藏版)》请在冰豆网上搜索。
上面只是简单的介绍了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位*/
/*暂时
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SP2 键盘