新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 用单片机pic16f877a实现鼠标数据的采集

用单片机pic16f877a实现鼠标数据的采集

作者:时间:2016-10-07来源:网络收藏

  最近弄个用单片机实现鼠标数据的采集。通过对鼠标底层通信原理与协议的分析,以单片机构成鼠标数据的采集的实现和液晶显示的实现。

本文引用地址:http://www.eepw.com.cn/article/201610/310912.htm

  现在继续写下去 !!!!!!尽管和比赛没有关系了

  一、先要熟悉鼠标的协议和接口

  下面是PS2的接口

  :

 

  这是鼠标在传输过程中数据的一个 帧:

  

 

  一个开始位:(为0)

  八个数据位:

  一个奇校验位:

  一个停止位:(它总是1)

  鼠标和单片机通信:

  1、单片机给鼠标发命令是按下面的格式进行的:

  

 

  (注意:一个应答信号的接收)

  这是它的详细过程:

  

 

  2、鼠标向单片机传送数据是下面的格式:

  

 

  二、下面就是设计鼠标和单片机的通信电路:(可以参考下面这个接法)

  

 

  (注意:数据和时钟都这是集电极开路的结构,平时是高电平 )

  三、外围布置好了就是具体程序的实现

  我们可以采用单片机16F877A的外部中断来响应鼠标的时钟,在中断中接收数据。

  我 们可按下面的步骤实现:

  1)把时钟线拉低至少100微秒

  2)把数据线拉低

  3)释放数据线

  4)等待设备把时钟线拉低

  5)设置/复位数据线发送第一个数据位

  6)等待设备把时钟拉高

  7)等待设备把时钟拉低

  8)重复5-7步发送剩下的7个数据位和校验位

  9)释放数据线

  10)等待设备把数据线拉低

  11)等待设备把时钟线拉低

  12)等待设备释放数据线和时钟线

  程序如下:

  //外部中断INT0初始化

  void INTE_init(void)

  {

  INTCON=0X00;

  GIE=1; //总中断

  RBPU=0;

  //INTE=1;//外部中断

  //INTEDG=0;//下升沿触发有效

  INTEDG=1;//上升沿触发有效

  TRISB=0x00;//正常工作下时钟RB0和数据RB2均输入

  INTF=0;//这三句是开外部中断

  PORTB=0X00;

  }

  //发送数据

  //发送11位数据:1START-8DATA-1PARITY-1STOP

  //并接收一个应答位ack = 0

  void mouse_write_dat(unsigned char dat)

  {

  unsigned char i; //循环变量

  INTE = 0; //关闭外部中断

  asm( "nop");

  mouse_clk = 0; //拉低时钟线

  delay(33); //至少延时100us

  mouse_sda = 0; //发送起始位

  mouse_clk = 1; //释放时钟线

  mouse_sda = 1; //释放数据线

  TRISB0=1;//时钟输入

  asm( "nop");

  TRISB=0X01;

  for(i = 0; i < 8; i++)

  { //至少要在25us内完成发送一位

  while(!mouse_clk); //等待设备把时钟线拉高

  mouse_sda =(bit)(dat& 0x01);//先发送最低位

  dat >>= 1; //下降沿写入数据

  while(mouse_clk); //等待设备把时钟线拉低

  }

  while(!mouse_clk); //等待设备把时钟线拉高

  mouse_sda = 0; //发送奇校验位

  while(mouse_clk); //等待设备把时钟线拉低

  while(!mouse_clk); //等待设备把时钟线拉高

  mouse_sda = 1; //发送停止位

  while(mouse_clk); //等待设备把时钟线拉低

  TRISB2=1;//数据输入

  asm( "nop");

  asm( "nop");

  while(!mouse_clk); //等待设备把时钟线拉高

  while(mouse_sda); //等待接收应答位(总是为0)

  while(mouse_clk); //等待设备把时钟线拉低

  while(!mouse_clk); //等待设备释放时钟线

  while(!mouse_sda); //等待设备释放数据线

  INTE = 1; //打开外部中断INTE

  }

  再就是鼠标的发数据模块可以参考下面的步骤:

  1)等待时钟线为高

  2)数据线仍然为低吗 有错误发生放弃

  3)读入8个数据位在读入这些位后

  4)读入校验位>测试时钟线数否被主机拉低

  5)读入停止位/这就意味着放弃这次传送

  6)数据线仍旧为0吗

  是保持时钟直到数据1然后产生一个错误

  7)输出应答位

  8)检查校验位

  如果校验位不正确则产生一个错误

  9)延迟45微秒给主机时间抑制下次的传送

  按如下次序读取每位8个数据位检验位和停止位

  1)延迟20微秒

  2)把时钟拉低

  3)延迟40微秒

  4)释放时钟

  5)延迟20微秒

  7)读数据线

  按如下次序发送应答位

  1)延迟15微秒

  2)把数据线拉低

  3)延迟5微秒

  4)把时钟线拉低

  5)延迟40微秒

  6)释放时钟线

  7)延迟5微秒

  8)释放数据线

  void interrupt INTE_ISR(void)

  {

  mouse_word >>= 1; //先向右空移一位

  if(mouse_sda) {mouse_word |= 0x0400; } //11位数据先接收最低位0000 010 (0 0000 000) 0 1START-8DATA-1PARITY-1STOP

  n++; if(n == 11) {mouse_read_dat(); n = 0;} //接收完成则读出数据

  INTF=0;

  }

  接下来就是读鼠标的数据了,首先要明白这个数据包中具体是些什么,看下面的图:

 

  (一般的鼠标就这些,具体的就要查鼠标的资料了)同志们 还不清楚就看下面的解释吧!!!

  鼠标内部有一个位移计数器,位移计数器是一个9位2的补码整数。它的最高位作为

  符号位出现在位移数据包的第一个字节里。这些计数器在鼠标读取输入发现有位移

  时被更新。这些值是自从最后一次发送位移数据包给主机后位移的累计量(即最后

  一次包发给主机后位移计数器被复位)。位移计数器可表示的值的范围是-255到+255,

  如果超过了范围,相应的溢出位就被设置,并且在复位前,计数器不会增减。正如我前

  面提及的一旦位移数据包成功地发送给主机,位移计数器就会复位,同样鼠标在收到主机

  不是Resend 0xFE命令外的其他命令,计数器也会复位。



关键词: pic16f877a 1602

评论


相关推荐

技术专区

关闭