PS/2鼠标接口协议

news/2025/3/3 4:58:11/

一、PS/2鼠标接口

       PS/2接口用于许多现代的鼠标和键盘,由IBM最初开发和使用。物理上的PS/2接口有两种类型的连接器:5脚的DIN和6脚的MINI-DIN。

      

二、鼠标的接口协议原理    

        PS/2鼠标接口采用一种双向同步串行协议。即每在时钟线上发一个脉冲,就在数据线上发送一位数据。但是在相互传输中 ,主机是拥有总线控制权的,即它可以在任何时候抑制鼠标的发送。方法是把时钟线一直拉低,鼠标就不能产生时钟信号和发送数据。

        在两个方向的传输中,时钟信号都是由鼠标产生,即主机不产生通信时钟信号。

        如果主机要发送数据,它必须控制鼠标产生时钟信号。方法如下:主机首先下拉时钟线至少100μs抑制通信,然后再下拉数据线,最后释放时钟线。通过这一时序控制鼠标产生时钟信号。当鼠标检测到这个时序状态,会在10ms内产生时钟信号。

        

图1、鼠标到主机传输协议

           

图2、主机到鼠标的传输协议

三、鼠标的工作模式

         Reset模式:当鼠标上电或主机发复位命令(0xFF)给它时进入这种模式;

         Stream模式: 鼠标的默认模式,当鼠标上电或复位完成后,自动进入此模式,鼠标基本上以此模式工作;

         Remote模式:只有在主机发送了模式设置命令(0xF0)后,鼠标才进入这种模式;

         Wrap模式:该模式只用于测试鼠标与主机连接是否正确。

四、鼠标发送的数据格式

      

        Byte1中的Bit0、Bit1、Bit2分别表示左、右、中键的状态,用状态值0表示释放 ,用状态值1表示按下。Byte2和Byte3分别表示X轴和Y轴方向的移动计量值,是二进制补码值。Byte4的低四位表示滚轮的移动计量值,也是二进制补码值,高四位作为扩展符号位。这种数据包由带滚轮的三键三维鼠标产生。若是不带滚轮的三键鼠标,产生的数据包没有Byte4其余的相同。

五、Verilog代码

          PS2驱动

          odule ps2(
           iSTART,   //press the button for transmitting instrucions to device;
           iRST_n,   //FSM reset signal;
           iCLK_50,  //clock source;
           PS2_CLK,  //ps2_clock signal inout;
           PS2_DAT,  //ps2_data  signal inout;
           oLEFBUT,  //left button press display;
           oRIGBUT,  //right button press display;
           oMIDBUT,  //middle button press display;
           oX_MOV1,  //lower SEG of mouse displacement display for X axis.
           oX_MOV2,  //higher SEG of mouse displacement display for X axis.
           oY_MOV1,  //lower SEG of mouse displacement display for Y axis.
           oY_MOV2   //higher SEG of mouse displacement display for Y axis.
           );
           //interface;
//=======================================================
//  PORT declarations
//=======================================================

input iSTART;
input iRST_n;
input iCLK_50;

inout PS2_CLK;
inout PS2_DAT;

output oLEFBUT;
output oRIGBUT;
output oMIDBUT;
output [6:0] oX_MOV1;
output [6:0] oX_MOV2;
output [6:0] oY_MOV1;
output [6:0] oY_MOV2;

//instantiation
SEG7_LUT U1(.oSEG(oX_MOV1),.iDIG(x_latch[3:0]));
SEG7_LUT U2(.oSEG(oX_MOV2),.iDIG(x_latch[7:4]));
SEG7_LUT U3(.oSEG(oY_MOV1),.iDIG(y_latch[3:0]));
SEG7_LUT U4(.oSEG(oY_MOV2),.iDIG(y_latch[7:4]));
//instruction define, users can charge the instruction byte here for other purpose according to ps/2 mouse datasheet.
//the MSB is of parity check bit, that's when there are odd number of 1's with data bits, it's value is '0',otherwise it's '1' instead.

parameter enable_byte =9'b011110100;


//=======================================================
//  REG/WIRE declarations
//=======================================================
reg [1:0] cur_state,nex_state;
reg ce,de;
reg [3:0] byte_cnt,delay;
reg [5:0] ct;
reg [7:0] x_latch,y_latch,cnt;
reg [8:0] clk_div;
reg [9:0] dout_reg;
reg [32:0] shift_reg;
reg       leflatch,riglatch,midlatch;
reg       ps2_clk_in,ps2_clk_syn1,ps2_dat_in,ps2_dat_syn1;
wire      clk,ps2_dat_syn0,ps2_clk_syn0,ps2_dat_out,ps2_clk_out,flag;

//=======================================================
//  PARAMETER declarations
//=======================================================
//state define
parameter listen =2'b00,
          pullclk=2'b01,
          pulldat=2'b10,
          trans  =2'b11;
          
//=======================================================
//  Structural coding
//=======================================================          
//clk division, derive a 97.65625KHz clock from the 50MHz source;

always@(posedge iCLK_50)
    begin
        clk_div <= clk_div+1;
    end
    
assign clk = clk_div[8];
//tristate output control for PS2_DAT and PS2_CLK;
assign PS2_CLK = ce?ps2_clk_out:1'bZ;
assign PS2_DAT = de?ps2_dat_out:1'bZ;
assign ps2_clk_out = 1'b0;
assign ps2_dat_out = dout_reg[0];
assign ps2_clk_syn0 = ce?1'b1:PS2_CLK;
assign ps2_dat_syn0 = de?1'b1:PS2_DAT;
//
assign oLEFBUT = leflatch;
assign oRIGBUT = riglatch;
assign oMIDBUT = midlatch;
//multi-clock region simple synchronization
always@(posedge clk)
    begin
        ps2_clk_syn1 <= ps2_clk_syn0;
        ps2_clk_in   <= ps2_clk_syn1;
        ps2_dat_syn1 <= ps2_dat_syn0;
        ps2_dat_in   <= ps2_dat_syn1;
    end
//FSM shift
always@(*)
begin
   case(cur_state)
     listen  :begin
              if ((!iSTART) && (cnt == 8'b11111111))
                  nex_state = pullclk;
              else
                  nex_state = listen;
                         ce = 1'b0;
                         de = 1'b0;
              end
     pullclk :begin
              if (delay == 4'b1100)
                  nex_state = pulldat;
              else
                  nex_state = pullclk;
                         ce = 1'b1;
                         de = 1'b0;
              end
     pulldat :begin
                  nex_state = trans;
                         ce = 1'b1;
                         de = 1'b1;
              end
     trans   :begin
              if  (byte_cnt == 4'b1010)
                  nex_state = listen;
              else    
                  nex_state = trans;
                         ce = 1'b0;
                         de = 1'b1;
              end
     default :    nex_state = listen;
   endcase
end
//idle counter
always@(posedge clk)
begin
  if ({ps2_clk_in,ps2_dat_in} == 2'b11)
    begin
        cnt <= cnt+1;
    end
  else begin
        cnt <= 8'd0;
       end
end
//periodically reset ct; ct counts the received data length;
assign flag = (cnt == 8'hff)?1:0;
always@(posedge ps2_clk_in,posedge flag)
begin
  if (flag)
     ct <= 6'b000000;
  else
     ct <= ct+1;
end
//latch data from shift_reg;outputs is of 2's complement;
//Please treat the cnt value here with caution, otherwise wrong data will be latched.
always@(posedge clk,negedge iRST_n)
begin
   if (!iRST_n)
   begin
      leflatch <= 1'b0;
      riglatch <= 1'b0;
      midlatch <= 1'b0;
      x_latch  <= 8'd0;
      y_latch  <= 8'd0;
   end
   else if (cnt == 8'b00011110 && (ct[5] == 1'b1 || ct[4] == 1'b1))
   begin
      leflatch <= shift_reg[1];
      riglatch <= shift_reg[2];
      midlatch <= shift_reg[3];
      x_latch  <= x_latch+shift_reg[19 : 12];
      y_latch  <= y_latch+shift_reg[30 : 23];
   end
end

//pull ps2_clk low for 100us before transmit starts;
always@(posedge clk)
begin
  if (cur_state == pullclk)
     delay <= delay+1;
  else
     delay <= 4'b0000;
end
//transmit data to ps2 device;eg. 0xF4
always@(negedge ps2_clk_in)
begin
  if (cur_state == trans)
     dout_reg <= {1'b0,dout_reg[9:1]};
  else
     dout_reg <= {enable_byte,1'b0};
end
//transmit byte length counter
always@(negedge ps2_clk_in)
begin
  if (cur_state == trans)
     byte_cnt <= byte_cnt+1;
  else
     byte_cnt <= 4'b0000;
end
//receive data from ps2 device;
always@(negedge ps2_clk_in)
begin
  if (cur_state == listen)
     shift_reg <= {ps2_dat_in,shift_reg[32:1]};
end
//FSM movement
always@(posedge clk,negedge iRST_n)
begin
  if (!iRST_n)
     cur_state <= listen;
  else
     cur_state <= nex_state;
end
endmodule


http://www.ppmy.cn/news/440300.html

相关文章

某购房通小程序解密分析【2023.6.17】

声明 本文以教学为基准、本文提供的可操作性不得用于任何商业用途和违法违规场景。 本人对任何原因在使用本人中提供的代码和策略时可能对用户自己或他人造成的任何形式的损失和伤害不承担责任。 如有侵权,请联系我进行删除。 主要对小程序返回的加密结果进行解密的分析过程只…

如何在iPhone上用ChatGPT替换Siri

To use ChatGPT with Siri on an iPhone or iPad, get an OpenAI API key and download the ChatGPT Siri shortcut. Enter your API key in the shortcut setup and select the GPT model you want to use, then hit “Add Shortcut.” Trigger the shortcut manually first t…

运行yolov5的train.py时发生报错

在计算机视觉领域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;是一种流行的目标检测算法&#xff0c;它能够快速准确地识别图像中的物体&#xff0c;并输出其边界框和类别信息。YOLOv5是YOLO系列的最新版本&#xff0c;相比之前版本在精度和速度上都有了显著提…

知识图谱项目——红色文化之张学良人物知识图谱(Neo4j+vue+flask+mysql实现)

张学良人物简史知识图谱_说明文档 本项目为人工智能专业大三知识图谱课程期末作业。意在完成一个以张学良为背景的红色文化类知识图谱。文末放上本项目的代码地址。 文章目录 张学良人物简史知识图谱_说明文档:rocket:前端:rocket:后端:rocket:中间件:rocket:数据库:rocket:服…

Skimage.measure 的compare_psnr和compare_ssim的改动

Skimage.measure 的compare_psnr和compare_ssim的改动及错误解决 最近在尝试复现使用DnCNN进行图像去噪的过程中发现&#xff0c;代码中计算峰值信噪比psnr和结构相似性指数ssim的代码还是之前旧版本的&#xff0c;在进行导入的时候会爆红 from skimage.measure import compar…

红米手机连接小米wifi显示已连接服务器,小米手机连wifi已连接却无法访问互联网怎么回事...

您好&#xff0c;wifi信号不论是否有网络手机等设备均可以进行连接的&#xff0c;用户连接wifi后无法使用网络首先要确认您的宽带线路是否通畅&#xff0c;可以查看下宽带猫的指示灯是否有los红灯闪烁&#xff0c;如果有就是宽带故障所以路由器的wifi不能使用网络&#xff0c;此…

单片机如何接上云服务器_如何实现单片机与手机的远距离通信?

通过云服务器中转可以实现单片机与手机的远距离通信 只要有互联网连接&#xff0c;通过云服务器中转&#xff0c;单片机和手机无论处于地球的哪一个角落都可以进行通信&#xff0c;这就是物联网的魅力了。 单片机如何接入互联网&#xff1f; 单片机作为处理器&#xff0c;本身是…

世纪互联运营的office365登陆手机Outlook

世纪互联运营的office365不能直接选客户端的office365登陆 配置InakiVargues的手机邮箱&#xff1a;1、 下载邮件Outlook手机客户端&#xff08;Android&#xff09;2、 因为是世纪互联运营的邮箱&#xff0c;所以设置的时候选择的不是office365&#xff0c;而是exchange模式…