为什么连上手指鼠标不能显示鼠标正确的位移量呢
时间:10-02
整理:3721RD
点击:
高手们,可以给看看这个程序吗,为什么连上现在网上流行的手指鼠标不能显示鼠标正确的位移量呢,谢谢!/************************************************************************************************************** 鼠标测距项目 *********************************
***********************************************************************************/
/**********************************************************************************
** 函数名 :main
** 函数功能 :主函数
** 输入 :无
** 输出 :无
***********************************************************************************/
#include<reg51.h>
#include<intrins.h>
#include"lcd.h"
#include<string.h>
#define uchar unsigned char
#define sint signed int
#define uint unsigned int
//#include"mouse.h"
/************************************************************************************************************/
#define delay10 {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}//延时10us
#define delay100 {delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10;}
sbit SDA=P3^2; //P3^3 //int0号中断(本程序不用中断接收方式)
sbit CLK=P3^3;
bit pp=0,ACK=0;
uchar recv=0;
signed int move_x=00000;//存放横坐标
signed int move_y=00000;//存放纵坐标
signed int move_z=00000; //总共接收到的字节总数
unsigned char data xy[16]= "x: y: "; //2 10
unsigned char data lmr[16]= "key:N z: "; //5 10
unsigned char idata deal_1[20]=" "; //用来存放初始化鼠标时鼠标返回的信息
unsigned char idata deal_2[20]=" ";
uchar idata ret_ini_dat[18]=0; //间接寻址片内数据存储区,可访问片内全部RAM空间(256bytes)
/* 产生编码器信号*/
unsigned int time=0;
unsigned int meichong_x=0;
sbit AZ=P1^0;
sbit AF=P1^1;
sbit BZ=P1^2;
sbit BF=P1^3;
sbit CS=P1^6;
/*编码器信号定义完成*/
void host_to_mouse(uchar cmd)
{
uchar i;
CLK=0;
delay100;
delay100;
ACC=cmd;
pp=~P; //获得奇偶校验位
SDA=0;
delay(2); //后加
CLK=1;
for(i=0;i<8;i++)
{
while(CLK!=0);
SDA=cmd&0x01;
cmd>>=1;
while(CLK!=1);
}
while(CLK!=0);
SDA=pp; //发送奇偶校验位
while(CLK!=1);
while(CLK!=0);
SDA=1;
while(CLK!=1);
while(CLK!=0);
ACK=SDA; //接收应答位
while(CLK!=1);
}
uchar mouse_to_host()
{
uchar i,temp=0;
//CLK=!CLK; //////////////////////////////////
while(CLK!=0); //等待低电平
//SDA=!SDA; ////////////////////////////////
while(SDA!=0);
// CLK=!CLK; //////////////////////////////////
while(CLK!=1); //等待高电平
for(i=0;i<8;i++)
{
temp>>=1;
// CLK=!CLK; //////////////////////////////////
while(CLK!=0);
// SDA=!SDA; ////////////////////////////////
if(SDA==1)
temp=0x80|temp;
// CLK=!CLK; //////////////////////////////////
while(CLK!=1);
}
// CLK=!CLK; //////////////////////////////////
while(CLK!=0);
pp=SDA; //接收奇偶校验位
//CLK=!CLK; //////////////////////////////////
while(CLK!=1);
//CLK=!CLK; //////////////////////////////////
while(CLK!=0);
//CLK=!CLK; //////////////////////////////////
while(CLK!=1);
ACC=temp;
//if(~P==pp) //如果检验成功则返回接收到的数据,否则返回0
//{
recv=temp;
return temp;
// }
// return 0;
}
//用0xf0代替相邻的0xc8,0x03可使鼠标进入remote模式,默认为stream模式
uchar code num[15]={0xf3,0x64,0xf3,0x50, //0xc8 200/sec,0x64 100/sec
0x50,0xc8,0xf2, //0x50 80/sec,0xf2读设备类型
0xf3,0xc8,0xf2,0xf0, //0x0a 10/sec,0xf2读设备类型,0x03滚轮分辨率8count/mm
0xe6,0xf3,0x28,0xf4};//0XE6 设置缩放比率为1:1,0x28 40/sec
//(0xe8,0xxx)设置滚轮分辨率,/0xe8,0x03/
/*uchar code num[13]={ 0xf3,0x64,0xf2,0xe8,0x03,
0xf3,0xc8,0xf3,0x64,
0xe6,0xf3,0x28,0xf4}; */
//微软支持第4 和第5 键的Intellimouse 的驱动
/*uchar code num[17]={0xf3,0xc8,0xf3,0x64,
0xf3,0x50,0xf2,0xf3,
0xc8,0xf3,0xc8,0xf3,
0xc8,0xf3,0x50,0xf2,0x04}; */
bit init_mouse()
{
uchar K=0,D=0;
bit good=1;
for(K=0;K<3;K++)
{
host_to_mouse(0xff); //复位命令,鼠标连续返回三个字节
ret_ini_dat[0]=mouse_to_host();//鼠标返回0xfa
ret_ini_dat[1]=mouse_to_host();//鼠标返回0xaa
ret_ini_dat[2]=mouse_to_host();//鼠标返回0x00
}
for(D=0;D<15;D++)
{
host_to_mouse(num[D]);
ret_ini_dat[D+3]=mouse_to_host();
}
return good=0;
}
void deal_recive_data()//处理初始化鼠标时返回给主机的部分数据,用以作调试
{ //处理成十六进制和ASCII码
uchar i=0,j=0,xx=0;
for(i=0;i<10;i++)
{
xx=ret_ini_dat;
if(((xx>>4)&0x0f)>=0x00 && ((xx>>4)&0x0f)<=0x09)
deal_1[j++]=((xx>>4)&0x0f)+0x30;
else
deal_1[j++]=((xx>>4)&0x0f)+55;
if((xx&0x0f)>=0x00 && (xx&0x0f)<=0x09)
deal_1[j++]=(xx&0x0f)+0x30;
else
deal_1[j++]=(xx&0x0f)+55;
}
j=0;
for(i=10;i<20;i++)
{
xx=ret_ini_dat;
if(((xx>>4)&0x0f)>=0x00 && ((xx>>4)&0x0f)<=0x09)
deal_2[j++]=((xx>>4)&0x0f)+0x30;
else
deal_2[j++]=((xx>>4)&0x0f)+55;
if((xx&0x0f)>=0x00 && (xx&0x0f)<=0x09)
deal_2[j++]=(xx&0x0f)+0x30;
else
deal_2[j++]=(xx&0x0f)+55;
}
}
/**************************************************************************************************************/
void display()
{
signed int nx=move_x,ny=move_y,nz=move_z;
uchar length=0;
if(move_x<0) {nx=-move_x;xy[2]='-';}
else
xy[2]=' ';
for(length=7;length>2;length--)
{
xy[length]=nx%10+48;
nx/=10;
}
if(move_y<0) {ny=-move_y;xy[10]='-';}
else
xy[10]=' ';
for(length=15;length>10;length--)
{
xy[length]=ny%10+48;
ny/=10;
}
//if(move_z<0){nz=-move_z;lmr[10]='-';}
//else
//lmr[10]=' ';
//for(length=15;length>10;length--)
//{
//lmr[length]=nz%10+48;
// nz/=10;
//}
write_command(0x80);
write_bytes(xy);
delay(10);
// write_command(0x80+0x8);
//write_bytes(lmr);
}
uchar fx=0,fy=0,fz=0,a0=0,a1=0,a2=0,a3=0,fl=0,fm=0,fr=0;
//uchar fxf=0,fyf=0;
void deal_data()
{
if(fx) //位5:x符号标志位,为1表示x位移量为负
move_x-=(256-a1);//x坐标减
else
move_x+=a1;//x坐标加
if(fy) //位6:y符号标志位,为1表示y位移量为负
move_y-=(256-a2);//y坐标减
else
move_y+=a2;//y坐标加
//if(fz)
// move_z-=(16-(a3&0x0f));
//else
// move_z+=(a3&0x07);
// if(fr) //如果点下右键
// {lmr[4]='R';return;}
// else if(fm) //如果点下中键
// {lmr[4]='M';return;}
// else if(fl) //如果点下左键
// {lmr[4]='L';return;}
// else
// {lmr[4]='N';return;}
}
void main()
{
CS=1;
SDA=1;CLK=1;
delay(500);//鼠标上电后在500ms左右就会发给主机0xaa和0x00
CLK=0; // 后加
delay(500);// 后加
SDA=0; // 后加
CLK=1; // 后加
/*定时器0初始化*/
TMOD=0X01;
TH0=0XFF;
TL0=0x9C;
AZ=1;
AF=0;
BZ=1;
BF=0;
mouse_to_host();//如果没有接收这两个字节,可能鼠标一次上电后,
mouse_to_host();//不能正常初始化成功或者可以用加长廷时来代替接收
init_lcd(); //初始化1602
delay100; //这个廷时相当重要,否则可能在1602中有乱码出?write_command(0x80);//定位光标在第一行
write_bytes("Initializing....");
write_command(0x80+0x04);//定位光标在第二行
delay(3);
while(init_mouse());//初始化鼠标
deal_recive_data();//处理初始化鼠标时返回给主机的部分数据,用以作调试
write_command(0x80);
write_bytes(deal_1);//显示初始化鼠标时返回给主机的部分数据,用以作调试
write_command(0x80+0x04);
write_bytes(deal_2);//显示初始化鼠标时返回给主机的部分数据,用以作调试
write_command(0x80+0x04);
delay(500);
write_bytes(" Mouse Normal ");
write_bytes(" Please wait! ");
delay(500);
write_command(0x80);
write_bytes("Test PS/2 mouse.");
write_command(0x80+0x04);
write_bytes("Copyright-11-28-");
while(1)
{
host_to_mouse(0xeb);//在remote模式中,主机每发送一个0xeb命令,从机
mouse_to_host(); //将应答0xfa,之后就是数据包
a0=mouse_to_host();//第一个数据包
fr=a0&0x02; //右键
fm=a0&0x04; //中键
fl=a0&0x01; //左键
fx=a0&0x10; //x的符号位
fy=a0&0x20; //y的符号位
a1=mouse_to_host();//第二个数据包 x位移量
// write_command(0x80);
// write_bytes("lm");
a2=mouse_to_host();//第三个数据包 y位移量
// a3=mouse_to_host();//第四个数据包 z位移量
//fz=a3&0x08; //z的符号位
/* fxf=a0&0x40+0x30;
fyf=a0&0x80+0x30;
lmr[6]=fxf;
lmr[7]=fyf;*/
deal_data(); //将x,y,z,fl,fr,fm加入字符串中
display(); //加入之后再一次性刷新显示
/*产生编码器信号,定时器设置*/
if(a1>0&time==0)
{
meichong_x=a1*1;
EA=1;
ET0=1;
TR0=1;
}
}
}
/*
第1个数据包
位0:左键按下标志位,为1表示左键被按下。
位1:右键按下标志位,为1表示右键被按下。
位2:中键按下标志位,为1表示中键被按下。
位3:保留位,总是为1。
位4:X符号标志位,为1表示X位移量为负。
位5:Y符号标志位,为1表示Y位移量为负。
位6:X溢出标志位,为1表示X位移量溢出了。
位7:Y溢出标志位,为1表示Y位移量溢出了。
三维鼠标数据包中第一个数据包每位的含义与
二维鼠标数据包中第一个数据包中每位含义完全相同,
唯一不同的就在于它每次会多发送一个数据包,
即第4个数据包,这个数据包包含了Z的位移量,
同X、Y位移量相同的是,它们都是以补码表示的。
不过与X及Y位移量不同的是,Z位移量是4位的,
其中最高位(第四位)是符号位,因此,Z位移量的有效的范围为:-8~7。
而X与Y的位移量是9位的,最高一位(第9位)是符号位,
这个符号位在第一个数据包中表示,
故,X与Y的位移量的有效范围为:-256~255。*/
void timer0_int(void) interrupt 1
{
TH0=0XFF;
TL0=0x9C;
time ++;
if(time==meichong_x)
{
EA=0;
ET0=0;
TR0=0;
time=0;
}
else {
AZ=~AZ;
AF=~AF;
}
}
***********************************************************************************/
/**********************************************************************************
** 函数名 :main
** 函数功能 :主函数
** 输入 :无
** 输出 :无
***********************************************************************************/
#include<reg51.h>
#include<intrins.h>
#include"lcd.h"
#include<string.h>
#define uchar unsigned char
#define sint signed int
#define uint unsigned int
//#include"mouse.h"
/************************************************************************************************************/
#define delay10 {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}//延时10us
#define delay100 {delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10;}
sbit SDA=P3^2; //P3^3 //int0号中断(本程序不用中断接收方式)
sbit CLK=P3^3;
bit pp=0,ACK=0;
uchar recv=0;
signed int move_x=00000;//存放横坐标
signed int move_y=00000;//存放纵坐标
signed int move_z=00000; //总共接收到的字节总数
unsigned char data xy[16]= "x: y: "; //2 10
unsigned char data lmr[16]= "key:N z: "; //5 10
unsigned char idata deal_1[20]=" "; //用来存放初始化鼠标时鼠标返回的信息
unsigned char idata deal_2[20]=" ";
uchar idata ret_ini_dat[18]=0; //间接寻址片内数据存储区,可访问片内全部RAM空间(256bytes)
/* 产生编码器信号*/
unsigned int time=0;
unsigned int meichong_x=0;
sbit AZ=P1^0;
sbit AF=P1^1;
sbit BZ=P1^2;
sbit BF=P1^3;
sbit CS=P1^6;
/*编码器信号定义完成*/
void host_to_mouse(uchar cmd)
{
uchar i;
CLK=0;
delay100;
delay100;
ACC=cmd;
pp=~P; //获得奇偶校验位
SDA=0;
delay(2); //后加
CLK=1;
for(i=0;i<8;i++)
{
while(CLK!=0);
SDA=cmd&0x01;
cmd>>=1;
while(CLK!=1);
}
while(CLK!=0);
SDA=pp; //发送奇偶校验位
while(CLK!=1);
while(CLK!=0);
SDA=1;
while(CLK!=1);
while(CLK!=0);
ACK=SDA; //接收应答位
while(CLK!=1);
}
uchar mouse_to_host()
{
uchar i,temp=0;
//CLK=!CLK; //////////////////////////////////
while(CLK!=0); //等待低电平
//SDA=!SDA; ////////////////////////////////
while(SDA!=0);
// CLK=!CLK; //////////////////////////////////
while(CLK!=1); //等待高电平
for(i=0;i<8;i++)
{
temp>>=1;
// CLK=!CLK; //////////////////////////////////
while(CLK!=0);
// SDA=!SDA; ////////////////////////////////
if(SDA==1)
temp=0x80|temp;
// CLK=!CLK; //////////////////////////////////
while(CLK!=1);
}
// CLK=!CLK; //////////////////////////////////
while(CLK!=0);
pp=SDA; //接收奇偶校验位
//CLK=!CLK; //////////////////////////////////
while(CLK!=1);
//CLK=!CLK; //////////////////////////////////
while(CLK!=0);
//CLK=!CLK; //////////////////////////////////
while(CLK!=1);
ACC=temp;
//if(~P==pp) //如果检验成功则返回接收到的数据,否则返回0
//{
recv=temp;
return temp;
// }
// return 0;
}
//用0xf0代替相邻的0xc8,0x03可使鼠标进入remote模式,默认为stream模式
uchar code num[15]={0xf3,0x64,0xf3,0x50, //0xc8 200/sec,0x64 100/sec
0x50,0xc8,0xf2, //0x50 80/sec,0xf2读设备类型
0xf3,0xc8,0xf2,0xf0, //0x0a 10/sec,0xf2读设备类型,0x03滚轮分辨率8count/mm
0xe6,0xf3,0x28,0xf4};//0XE6 设置缩放比率为1:1,0x28 40/sec
//(0xe8,0xxx)设置滚轮分辨率,/0xe8,0x03/
/*uchar code num[13]={ 0xf3,0x64,0xf2,0xe8,0x03,
0xf3,0xc8,0xf3,0x64,
0xe6,0xf3,0x28,0xf4}; */
//微软支持第4 和第5 键的Intellimouse 的驱动
/*uchar code num[17]={0xf3,0xc8,0xf3,0x64,
0xf3,0x50,0xf2,0xf3,
0xc8,0xf3,0xc8,0xf3,
0xc8,0xf3,0x50,0xf2,0x04}; */
bit init_mouse()
{
uchar K=0,D=0;
bit good=1;
for(K=0;K<3;K++)
{
host_to_mouse(0xff); //复位命令,鼠标连续返回三个字节
ret_ini_dat[0]=mouse_to_host();//鼠标返回0xfa
ret_ini_dat[1]=mouse_to_host();//鼠标返回0xaa
ret_ini_dat[2]=mouse_to_host();//鼠标返回0x00
}
for(D=0;D<15;D++)
{
host_to_mouse(num[D]);
ret_ini_dat[D+3]=mouse_to_host();
}
return good=0;
}
void deal_recive_data()//处理初始化鼠标时返回给主机的部分数据,用以作调试
{ //处理成十六进制和ASCII码
uchar i=0,j=0,xx=0;
for(i=0;i<10;i++)
{
xx=ret_ini_dat;
if(((xx>>4)&0x0f)>=0x00 && ((xx>>4)&0x0f)<=0x09)
deal_1[j++]=((xx>>4)&0x0f)+0x30;
else
deal_1[j++]=((xx>>4)&0x0f)+55;
if((xx&0x0f)>=0x00 && (xx&0x0f)<=0x09)
deal_1[j++]=(xx&0x0f)+0x30;
else
deal_1[j++]=(xx&0x0f)+55;
}
j=0;
for(i=10;i<20;i++)
{
xx=ret_ini_dat;
if(((xx>>4)&0x0f)>=0x00 && ((xx>>4)&0x0f)<=0x09)
deal_2[j++]=((xx>>4)&0x0f)+0x30;
else
deal_2[j++]=((xx>>4)&0x0f)+55;
if((xx&0x0f)>=0x00 && (xx&0x0f)<=0x09)
deal_2[j++]=(xx&0x0f)+0x30;
else
deal_2[j++]=(xx&0x0f)+55;
}
}
/**************************************************************************************************************/
void display()
{
signed int nx=move_x,ny=move_y,nz=move_z;
uchar length=0;
if(move_x<0) {nx=-move_x;xy[2]='-';}
else
xy[2]=' ';
for(length=7;length>2;length--)
{
xy[length]=nx%10+48;
nx/=10;
}
if(move_y<0) {ny=-move_y;xy[10]='-';}
else
xy[10]=' ';
for(length=15;length>10;length--)
{
xy[length]=ny%10+48;
ny/=10;
}
//if(move_z<0){nz=-move_z;lmr[10]='-';}
//else
//lmr[10]=' ';
//for(length=15;length>10;length--)
//{
//lmr[length]=nz%10+48;
// nz/=10;
//}
write_command(0x80);
write_bytes(xy);
delay(10);
// write_command(0x80+0x8);
//write_bytes(lmr);
}
uchar fx=0,fy=0,fz=0,a0=0,a1=0,a2=0,a3=0,fl=0,fm=0,fr=0;
//uchar fxf=0,fyf=0;
void deal_data()
{
if(fx) //位5:x符号标志位,为1表示x位移量为负
move_x-=(256-a1);//x坐标减
else
move_x+=a1;//x坐标加
if(fy) //位6:y符号标志位,为1表示y位移量为负
move_y-=(256-a2);//y坐标减
else
move_y+=a2;//y坐标加
//if(fz)
// move_z-=(16-(a3&0x0f));
//else
// move_z+=(a3&0x07);
// if(fr) //如果点下右键
// {lmr[4]='R';return;}
// else if(fm) //如果点下中键
// {lmr[4]='M';return;}
// else if(fl) //如果点下左键
// {lmr[4]='L';return;}
// else
// {lmr[4]='N';return;}
}
void main()
{
CS=1;
SDA=1;CLK=1;
delay(500);//鼠标上电后在500ms左右就会发给主机0xaa和0x00
CLK=0; // 后加
delay(500);// 后加
SDA=0; // 后加
CLK=1; // 后加
/*定时器0初始化*/
TMOD=0X01;
TH0=0XFF;
TL0=0x9C;
AZ=1;
AF=0;
BZ=1;
BF=0;
mouse_to_host();//如果没有接收这两个字节,可能鼠标一次上电后,
mouse_to_host();//不能正常初始化成功或者可以用加长廷时来代替接收
init_lcd(); //初始化1602
delay100; //这个廷时相当重要,否则可能在1602中有乱码出?write_command(0x80);//定位光标在第一行
write_bytes("Initializing....");
write_command(0x80+0x04);//定位光标在第二行
delay(3);
while(init_mouse());//初始化鼠标
deal_recive_data();//处理初始化鼠标时返回给主机的部分数据,用以作调试
write_command(0x80);
write_bytes(deal_1);//显示初始化鼠标时返回给主机的部分数据,用以作调试
write_command(0x80+0x04);
write_bytes(deal_2);//显示初始化鼠标时返回给主机的部分数据,用以作调试
write_command(0x80+0x04);
delay(500);
write_bytes(" Mouse Normal ");
write_bytes(" Please wait! ");
delay(500);
write_command(0x80);
write_bytes("Test PS/2 mouse.");
write_command(0x80+0x04);
write_bytes("Copyright-11-28-");
while(1)
{
host_to_mouse(0xeb);//在remote模式中,主机每发送一个0xeb命令,从机
mouse_to_host(); //将应答0xfa,之后就是数据包
a0=mouse_to_host();//第一个数据包
fr=a0&0x02; //右键
fm=a0&0x04; //中键
fl=a0&0x01; //左键
fx=a0&0x10; //x的符号位
fy=a0&0x20; //y的符号位
a1=mouse_to_host();//第二个数据包 x位移量
// write_command(0x80);
// write_bytes("lm");
a2=mouse_to_host();//第三个数据包 y位移量
// a3=mouse_to_host();//第四个数据包 z位移量
//fz=a3&0x08; //z的符号位
/* fxf=a0&0x40+0x30;
fyf=a0&0x80+0x30;
lmr[6]=fxf;
lmr[7]=fyf;*/
deal_data(); //将x,y,z,fl,fr,fm加入字符串中
display(); //加入之后再一次性刷新显示
/*产生编码器信号,定时器设置*/
if(a1>0&time==0)
{
meichong_x=a1*1;
EA=1;
ET0=1;
TR0=1;
}
}
}
/*
第1个数据包
位0:左键按下标志位,为1表示左键被按下。
位1:右键按下标志位,为1表示右键被按下。
位2:中键按下标志位,为1表示中键被按下。
位3:保留位,总是为1。
位4:X符号标志位,为1表示X位移量为负。
位5:Y符号标志位,为1表示Y位移量为负。
位6:X溢出标志位,为1表示X位移量溢出了。
位7:Y溢出标志位,为1表示Y位移量溢出了。
三维鼠标数据包中第一个数据包每位的含义与
二维鼠标数据包中第一个数据包中每位含义完全相同,
唯一不同的就在于它每次会多发送一个数据包,
即第4个数据包,这个数据包包含了Z的位移量,
同X、Y位移量相同的是,它们都是以补码表示的。
不过与X及Y位移量不同的是,Z位移量是4位的,
其中最高位(第四位)是符号位,因此,Z位移量的有效的范围为:-8~7。
而X与Y的位移量是9位的,最高一位(第9位)是符号位,
这个符号位在第一个数据包中表示,
故,X与Y的位移量的有效范围为:-256~255。*/
void timer0_int(void) interrupt 1
{
TH0=0XFF;
TL0=0x9C;
time ++;
if(time==meichong_x)
{
EA=0;
ET0=0;
TR0=0;
time=0;
}
else {
AZ=~AZ;
AF=~AF;
}
}
找个最老的那种鼠标试试,没准新的鼠标数据和以前不一样了呢
最老的鼠标可以实现,但是新的鼠标不行,就想着用新的啊,请问是不是通信协议发生了变化,还是发送的数据发生了变化?
既然老的可以那就证明程序没问题,上网找找新的鼠标的资料,如果没有就要麻烦点,比如你可以用示波器看看发送的数据
嗯,谢谢,我试试