● 0xEA (Set Stream Mode)——鼠标用应答0xFA 回应,然后复位它的位移计数器并进入stream模式。
● 0xE9 (Status Request)——鼠标用应答0xFA 回应,然后发送如表1.5,3个字节的状态包, 然后复位它的位移计数器。
Byte1 Byte2 Byte3 Always0 Mode Enable 表1.5 鼠标状态包格式 Scaling Always0 Left Btn 分辨率 采样速率 Middle Btn Right Btn 右键、中键、左键 =1,表示键被按下;=0 ,表示键没有按下。 Scaling = 1缩放比例位2:1; =0,比例为1 :1;见命令0xE7和0xE6。
Enable = 1表示数据报告被使能;=0,示数据报告被禁止;见命令0xF5和0xF4。
Mode = 1表示remote 模式被使能;=0,表示stream模式被使能;见命令0xF0和0xEA。
● 0xE8 (Set Resolution )——鼠标用应答0xFA 回应,然后从主机读取一个字节,并再次
用鼠标用应答0xFA应然回应,然后复位它的位移计数器,从主机读入的字节决定了分辨率如表1.6所示:
表1.6 鼠标位移分辩率对应表 主机发过来的数据 分辨率 0x00 1 计数值/毫米 0x01 2 计数值/毫米 0x02 4 计数值/毫米 0x03 8 计数值/毫米
● 0xE7 (Set Scaling 2:1)——鼠标用应答0xFA回应,然后使能2:1比例。
● 0xE6 (Set Scaling 1:1)——鼠标用应答0xFA回应,然后使能1:1比例。
对于标准鼠标而言,只有(Resend )0xFE和(Error) 0xFC 命令会发送给主机。这两条命令的工作情况和主机到设备间的命令一样。
注:
1、2 :1比例仅适用于Stream模式的自动数据报告中,对于回应Read Data 0xEB命令的报告数据是无效的。 2、鼠标和主机不缓冲Resend 0xFF 命令,这意味着0xFE 绝不会作为Resend 命令的回应来发送。 3、一个数据包可以是3字节的位移数据包,或4字节的位移数据包,Intellimouse的或3 字节的状态包Status Request 0xE9命令或2字节的完成代码ID包,0xAA 、0x00或0xFC、0x00或1字节的命令回应。
4、当PS/2数据线常置零时,PS/2鼠标将不断产生时钟脉冲。
1.5 PS/2通讯协议
PS2通讯协议是一种双向同步串行通讯协议。通讯的两端通过Clock(时钟脚)同步,并通过Data(数据脚)交换数据。任何一方如果想抑制另外一方通讯时,只需要把clock(时钟脚)拉到低电平。如果是PC机和PS2键盘间的通讯,则PC机必须做主机,也就是说,PC机可以抑制PS2键盘发送数据,而PS2键盘则不会抑制PC机发送数据, 也即主机总是在总线上有优先权。一般两设备间传输数据的最大时钟频率是33KHz,大多数PS2设备工作在10~20KHz。推荐值在15KHz左右,也就是说,clock(时钟脚)高、低电平的持续时间都为40μs。每一数据帧包含11~12个位,具体含义如表1.7所列。
表1.7 PS/2通讯数据帧格式 1个起始位 总是逻辑0 8个数据位 (LSB)低位在前 1个奇偶校验位 1个停止位 1个应答位 奇校验 总是逻辑1 仅用在主机对设备的通讯中 表中,如果数据位中1的个数为偶数,校验位就为1;如果数据位中1的个数为奇数,校验位就为0;总之,数据位中1的个数加上校验位中1的个数总为奇数,因此总进行奇校验。 1.5.1、PS/2设备到主机的通讯
时钟频率为10-16.7kHz 。从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒。数据变化到时钟脉冲的下降沿的时间至少要有5 微秒,并且不大于25微秒。这个定时非常重要你应该严格遵循它。主机可以在第11个时钟脉冲停止位之前把线拉低,导致设备放弃发送当前字节,这是非常罕见的。在停止位发送后设备在发送下个包前至少应该等待50微秒。这将给主机时间,当它处理接收到的字节时抑制发送(主机在收到每个包时通常自动做这个)。在主机释放抑制后,设备至少应该在发送任何数据前等50微秒。其通讯时序图如图1.1所示。
从PS2向PC机发送一个字节可按照下面的步骤进行: 1) 检测时钟线电平,如果时钟线为低,则延时50μs;
2) 检测判断时钟信号是否为高,为高,则向下执行,为低,则转到(1);
3) 检测数据线是否为高,如果为高则继续执行,如果为低,则放弃发送(此时PC机在向PS2设备发送数据,所以PS2设备要转移到接收程序处接收数据); 4) 延时20μs(如果此时正在发送起始位,则应延时40μs);
5) 输出起始位(0)到数据线上。这里要注意的是:在送出每一位后都要检测时钟线,以确保PC机没有抑制PS2设备,如果有则中止发送; 6) 输出8个数据位到数据线上; 7) 输出校验位; 8) 输出停止位(1);
9) 延时30μs(如果在发送停止位时释放时钟信号则应延时50μs);
按如下的过程发送单个位 1) 设置/复位数据 2) 延迟20微秒 3) 把时钟拉低 4) 延迟40微秒 5) 释放时钟 6) 延迟20微秒
图1.1 设备到主机的通讯
1.5.2、主机到PS/2设备的通讯
首先PS/2 设备总是产生时钟信号,如果主机要发送数据它必须首先把时钟和数据线设置为请求。发送状态如下示
● 通过下拉时钟线至少100微秒来抑制通讯
● 通过下拉数据线来应用请求,发送然后释放时钟
设备应该在不超过10 毫秒的间隔内就要检查这个状态。当设备检测到这个状态,它将开始
产生时钟信号,并且时钟脉冲标记下输入八个数据位和一个停止位。主机仅当时钟线为低的时候改变数据线而数据在时钟脉冲的上升沿被锁存,当发生在设备到主机通讯的过程中时正好相反。
在停止位发送后,设备要应答接收到的字节,就把数据线拉低并产生最后一个时钟脉冲,如果主机在第11 个时钟脉冲后不释放数据线,设备将继续产生时钟脉冲直到数据线被释放然后设备将产生一个错误。通讯时序图如图1.2、1.3所示。
主机可以在第11 个时钟脉冲应答位前中止一次传送,只要下拉时钟线至少100微秒。
主机必须按下面的步骤发送数据到PS/2设备 1) 把时钟线拉低至少100微秒 2) 把数据线拉低 3) 释放时钟线
4) 等待设备把时钟线拉低
5) 设置/复位数据线发送第一个数据位 6) 等待设备把时钟拉高 7) 等待设备把时钟拉低
8) 重复 5-7步发送剩下的7个数据位和校验位 9) 释放数据线
10) 等待设备把数据线拉低 11) 等待设备把时钟线拉低
12) 等待设备释放数据线和时钟线
图1.2 主机到设备的通讯
图1.3 主机到设备通讯的详细过程
图1.3描述了两个重要的定时条件:a和b。a在主机最初把数据线拉低后,设备开始产生时钟脉冲的时间,必须不大于15ms;b数据包被发送的时间,必须不大于2ms 。如果这两个条件不满足,主机将产生一个错误。在包收到后,主机为了处理数据立刻把时钟线拉低来抑制通讯,如果主机发送的命令要求有一个回应,这个回应必须在主机释放时钟线后20ms之内被收到。如果没有收到则主机产生一个错误,在设备到主机通讯的情况中,时钟改变后的5微秒内不应该发生数据改变的情况。
1.6 方案设计
1.6.1、设计思想
针对FPGA做时序控制不方便的缺点,本设计简化了通讯协议,对PS2鼠标的操作只用了一条指令,使能数据报告(0xF4)。利用鼠标上电自动复位并进入Stream模式后,送使能数据报告
指令(0xF4),便完成对鼠标的初使化。之后便可以接收PS2鼠标发送过来的数据包。该方案的优点是简化程序,节省资源;缺点是不能软复位,即鼠标由于出现异常情况而不正常工作,不能用软件复位,只能重新插拔鼠标。但出现异常状况的情况比较少,所以总来的该方案是比较合理的。
1.6.2、接口与控制
● Clock(input)——系统时钟,默认为48MHz,如要改为其它频率,需要改动如下几个参数:
parameter WATCHDOG_TIMER_VALUE = 19200; //看门狗计时器,400uS
parameter WATCHDOG_TIMER_BITS = 15; //400uS计时器所需计数器位数 parameter TIMER_5US_VALUE = 240; // 5uS计数值
parameter TIMER_5US_BITS = 8; // 5uS计时器所需计数器位数
● reset(input)——复位信号,高电平有效。复位时不会向PS/2鼠标发送复位命令,只向鼠
标发送数据使能报告。
● ps2_clk(bidir)——PS/2时钟线,为双向端口,外围电路需加上拉电阻。 ● ps2_data(bidri)——PS/2数据线,为双向端口,外围电路需加上拉电阻。 ● left_button(output)——左键标志位,高电平表示左键按下。 ● right_button(output)——右键标志位,高电平表示右键按下。 ● middle_button(output)——中键标志位,高电平表示中键按下。
● x_increment[8..0](output)——X轴增量,为9位二进制补码,最高位为符位。鼠标左移,位移增量为负;右移,位移增量为正。
● y_incremetn[8..0](output)——Y轴增量,为9位二进制补码,最高位为符位。鼠标上移,位移增量为负;下移,位移增量为正。
● data_ready(output)——高电平表示有新数据输出。输出为一个时钟脉冲。
1.7 调试总结
在调试过程中,最大的问题就是PS2时钟、数据线采集的同步问题。刚开始没有意识到这个问题,导致发送的指令及收到的数据总是出错(主要移位寄存器的操作,及位计数由于不同步计数出错导致的)。由于这个问题多花了一天的调试时间,以后值得注意(同步问题)。另外经调试,得出一些参数(对于我调试用的鼠标,其它的鼠标应该也是差不多)。发送指令给鼠标,260uS后收到鼠标的回应(0xFA),鼠标发送的数据包帧间的间隔大概是200uS。发送复位指令0xFF,360mS后收到自检成功(0xAA)和设备ID号(0x00)。收到ID号后,最好延时400uS右左再发送0xF4“使能数据报告”,不延时立即写可能会出错。此外当PS2数据线为常低时,鼠标会连续产生时钟信号。
另外有个问题比较怪,下面两个进程左边的可以正常运行,右边的不行,其中reset信号是输入引脚,由外面接一个按键,按下时为高电平。
是否外面引入的信号和FPGA内部信号的电气属性有什么区别? always @(posedge clock) always @(posedge clock) begin begin if(reset == 1'b1) if(reset) m2_state <= m2_reset; m2_state <= m2_reset; else else m2_state <= m2_next_state; m2_state <= m2_next_state; end end 以是程序调试中的一些问题,些外还有一个问题刚开始比较模糊,资料上说主机发送数据到PS2设备是在上升沿被取的,而后面又提到如果要仿真鼠标最好用下面的时序(读位操作): 1) 延迟20微秒
2) 把时钟拉低 3) 延迟40微秒 4) 释放时钟 5) 延迟20微秒 7) 读数据线
很明显是在上升沿后20uS才被读入,这与上面的说法有点矛盾,跟上述问题,对程序分别做改动,然后用逻辑分析仪分析,发现信号在上升沿被读入才是正确的。图1.4、1.5是调试中用逻辑分析仪抓到的一些波形。
图1.4 发送0xF4“使能数据报告”指令后,鼠标回应0xFA
图1.5 按下鼠标左键后,鼠标发送的数据包
1.8 学习小结
在设计的过程在学习了一种方法,就是当一个时钟(较低频率)要在一个进程里面同时判断上升沿和下降沿,可以用一个更高速成的时钟对慢的时钟采样,由低变高时产生一上升沿的脉冲,由高变低时产生一下降沿的脉冲,这样在进程里面就可以用电平的方法来判断边沿,当然这个是在边沿时差要求不高的场合。时序图如图1.6所示
(a)
(b)
图1.6 时钟边沿采样时序图