找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3600|回复: 4
收起左侧

stc89单片机模拟鼠标单击的程序问题

[复制链接]
ID:244871 发表于 2017-11-1 10:55 | 显示全部楼层 |阅读模式
因为是单片机新手,在网上找了一段程序,是基于stc12系列的,在网上查了一下,修改了延时函数和端口定义,还是没有办法让电脑识别,现在贴出原程序,请大神指点一下,感激不尽。捣鼓了两天了,因为对调试也不太懂,不知道怎么交互,每次改了后下载、插上电脑实验/************************************************************/   
/*文件名称:单片机模拟PS/2鼠标程序                          */                                
/*作 者:蒋毅                                               */   
/*版 本:2008-6                                             */   
/*说 明:                                                  */   
/*修改记录:                                                 */   
/************************************************************/   
#include <stc12c5412ad.h>   
#include <intrins.h>   
#define uchar unsigned char   
#define uint  unsigned int   
/******************常用命令及参数定义************************/   
//EEPROM   
#define isp_read         1   
#define isp_program      2   
#define isp_erase        3   
#define isp_con          0x80   
#define ADDRESSH         0X10   
#define ADDRESSL         0X00   

//HOST-->MOUSE   
#define DISABLE_SEND     0XF5   //disable data reprorting   
#define ENABLE_SEND      0XF4   //enable data reprorting   
#define RESET            0XFF   //reset   
#define GETID            0XF2   //get device id   
#define SATATUS_REQUEST  0XE9   //datatus request   
#define HMRESEND         0XFE   //host ask mouse resend   
#define ERROR            0X55   //receive eeror   

//MOUSE-->HOST   
#define ANSWERER         0XFA   //answerer   
#define ID               0X00   //device id   
#define BAT              0XAA   //bat   
#define RESEND           0XFE   //resend   
#define SATATUS3         0X02   //satatus3   
#define SATATUS4         0X64   //satatus4   
#define DATABAG          0x08;     

/***********************引脚定义*****************************/   
sbit  mouse_clk=P1^0;   
sbit  mouse_data=P1^1;   
sbit  ms1=P1^5;   
sbit  ms2=P1^6;   
sbit  ctls=P3^4;   
/***********************全局变量*****************************/   
uchar flag_send=0;//允许发送标志位   
uchar buffer=0;//命令缓冲单元   
/***********************函数声明*****************************/   
extern void delay1us(uchar i);   
//*********************读EEPROM一字节************************/   
uchar read_byte_eeprom(uchar addth,addtl)   
{   
uchar temp_data;   
ISP_ADDRH=addth;   
ISP_ADDRL=addtl;   
EA=0;   
ISP_CONTR=isp_con;   
ISP_CMD=isp_read;   
ISP_TRIG=0x46;   
ISP_TRIG=0xB9;   
temp_data=ISP_DATA;   
EA=1;   
return temp_data;   
}   
//*********************写EEPROM一字节***********************/   
void program_byte_eeprom(uchar temp_data, addth,addtl)   
{   
ISP_DATA=temp_data;   
ISP_ADDRH=addth;   
ISP_ADDRL=addtl;   
EA=0;   
ISP_CONTR=isp_con;   
ISP_CMD=isp_program;   
ISP_TRIG=0x46;   
ISP_TRIG=0xB9;   
EA=1;   
}   
//********************擦除EEPROM一扇区子函数*****************/   
void erase_sector_eeprom(uchar addth,addtl)   
{   
ISP_ADDRH=addth;   
ISP_ADDRL=addtl;   
EA=0;   
ISP_CONTR=isp_con;   
ISP_CMD=isp_erase;   
ISP_TRIG=0x46;   
ISP_TRIG=0xB9;   
EA=1;   
}   
/*******************ms级延时子函数***************************/   
void delay(uint k)         
{   
uint i;   
while(k--)   
  {   
   for(i=0;i<1200;i++);   
  }   
}   
/****************ps/2发送单个位到PC函数**********************/   
void send_bit(bit senbit)   
{   
mouse_data=senbit; //设置/复位数据   
delay1us(21);      //延迟20us   
mouse_clk=0;       //将时钟拉低   
delay1us(43);      //延迟40us   
mouse_clk=1;       //释放时钟   
}   
/***************ps/2发送单个字节到PC函数*********************/   
void send_byte(uchar tmp)   
{   
uchar i;   
uchar temp,check;   
temp=0;   
check=0;   
while(!mouse_clk);//等待CLK为高   
delay1us(54);//延时50us   
if(mouse_clk)//判断CLK是否为高,是:发送,否:放弃,转到接收程序   
  {   
   delay1us(21);//延时20us   
   for(i=0;i<11;i++)   
    {   
     delay1us(21);//延时20us   
     if(i==0) send_bit(0);//发送起始位0   
     else   
      {   
       if(i>=1&&i<9)//发送数据位   
        {   
         temp=tmp;   
         temp>>=(i-1);   
         temp=temp&0x01;   
         if(temp==0x01){send_bit(1);check++;}   
         else send_bit(0);   
        }   
       else   
         {   
         if(i==9)//发送校验位   
          {   
           check=check&0x01;   
           if(check==0x01) send_bit(0);//奇校验   
           else send_bit(1);   
          }   
         else send_bit(1);//发送停止位   
         }   
        }   
     if(mouse_clk==1) continue;//判断时钟是否被主机拉低,是-放弃发送   
     else break;   
    }   
    delay1us(32);//延时30us   
  }   
}   
/********************ps/2接收PC单个位函数********************/   
bit receive_bit()   
{   
bit tbit;   
tbit=0;   
delay1us(21);    //延迟20us   
mouse_clk=0;     //把时钟线拉低   
delay1us(43);    //延迟40us   
mouse_clk=1;     //释放时钟   
delay1us(21);    //延迟20us   
tbit=mouse_data; //读取数据   
return tbit;     //返回数据   
}   
/**********************ps/2输出应答位函数********************/   
void send_answerer()   
{   
delay1us(16);//延迟15us   
mouse_data=0;//把数据线拉低   
delay1us(5); //延迟5us   
mouse_clk=0; //把时钟线拉低   
delay1us(43);//延迟40us   
mouse_clk=1; //释放时钟线   
delay1us(5); //延迟5us   
mouse_data=1;//释放数据线   
}   
/*******************ps/2接收PC单个字节函数*******************/   
uchar receive_byte()   
{   
uchar i,temp,rdata,check;   
bit tmp,check_bit;   
tmp=0;   
check_bit=0;   
temp=0;   
rdata=0;   
check=0;   
while(!mouse_clk);//等待时钟为高   
if(!mouse_data)//判断数据线为低,是-接收,否-有错误发生,放弃   
  {   
   for(i=0;i<10;i++)//接收8个数据位,校验位,停止位   
    {   
     if(i>=0&&i<8)//读入8个数据位   
      {   
       tmp=receive_bit();   
       if(tmp==1) check++;   
       temp=(uchar)tmp;   
       temp<<=i;   
       rdata=rdata|temp;        
      }   
     else if(i==8)//读入校验位   
       check_bit=receive_bit();   
     else //读入停止位   
      tmp=receive_bit();   
     if(mouse_clk==1) continue;//判断时钟是否被主机拉低,是-放弃接收   
     else return 0x55;   
    }   
   /*判断停止位是否为1,否,产生一错误标志*/   
   if(!mouse_data) //否   
    {   
     while(!mouse_data);   
     return 0x55;   
    }   
   else //停止位为1   
    {   
     send_answerer();//输出应答位   
     check=(check+(uchar)check_bit)&0x01;   
     if(check==0)//检查校验位   
       return 0x55;//校验错误   
     else  return rdata;//返回收到的命令   
    }   
   }   
else return 0x55;   
}   
/***********************键盘扫描函数*************************/   
void keyscan()   
{   
uchar i,databag;   
uchar scancode,tmp;   
tmp=0x01;   
scancode=0;   
databag=0;   
if(flag_send)//判断是否允许数据报告   
{   
if((P1&0x1c)!=0x1c)//判断是否有键按下   
  {   
   delay(20);//延时消抖   
   if((P1&0x1c)!=0x1c)   
    {   
     ctls=0;//打开激光头   
     scancode=0x04;//逐键扫描   
     for(i=0;i<3;i++)   
      {   
       if((P1&scancode)!=scancode)//有键按下,置相应标志位为1   
        {   
         tmp<<=i;   
         databag=databag|tmp;   
         scancode<<=1;   
        }   
       else scancode<<=1;   
      }   
     delay(50);//延时50ms   
     send_byte(databag);   
     send_byte(ID);// 发送位移按键数据包   
     send_byte(ID);   
     databag=DATABAG;   
     if(ms1==1&&ms2==1)//持续按常亮无效   
      {   
       ctls=1;//关闭激光头   
       while((P1&0x1c)!=0x1c)//判键盘释放   
       WDT_CONTR=0X3E;//喂狗   
       send_byte(databag);// 发送位移按键数据包   
       send_byte(ID);   
       send_byte(ID);   
      }   
     else if(ms1==0&&ms2==1)//持续按常亮有效   
      {   
       while((P1&0x1c)!=0x1c)//判键盘释放   
       WDT_CONTR=0X3E;//喂狗   
       ctls=1;//关闭激光头   
       send_byte(databag);// 发送位移按键数据包   
       send_byte(ID);   
       send_byte(ID);   
      }   
     else//常亮   
      {   
       while((P1&0x1c)!=0x1c)//判键盘释放   
       WDT_CONTR=0X3E;//喂狗   
       send_byte(databag);// 发送位移按键数据包   
       send_byte(ID);   
       send_byte(ID);   
      }   
     }   
   }   
  }   
}   
/***********************处理主机命令函数*********************/   
void manage(uchar ljmp)   
{   
switch(ljmp)   
  {   
   case RESET:         //主机通知MOUSE复位     
   send_byte(ANSWERER);   
   send_byte(BAT);   
   send_byte(ID);   
   buffer=ID;   
   break;   

   case GETID:         //主机通知MOUSE获得ID   
   send_byte(ANSWERER);   
   send_byte(ID);   
   buffer=ID;   
   break;   

   case ENABLE_SEND :    //使能数据报告   
   send_byte(ANSWERER);   
   buffer=ANSWERER;   
   flag_send=1;   
   erase_sector_eeprom(ADDRESSH,ADDRESSL);   
   program_byte_eeprom(0X01,ADDRESSH,ADDRESSL);   
   break;   

   case DISABLE_SEND :   
   send_byte(ANSWERER);//禁止数据报告   
   buffer=ANSWERER;   
   flag_send=0;   
   erase_sector_eeprom(ADDRESSH,ADDRESSL);   
   break;      

   case SATATUS_REQUEST://主机通知MOUSE告诉状态信息   
   send_byte(ANSWERER);   
   send_byte(ID);   
   send_byte(SATATUS3);   
   send_byte(SATATUS4);   
   buffer=SATATUS4;   
   break;   

   case ERROR:         //MOUSE接收错误,通知主机重发   
   send_byte(RESEND);   
   buffer=RESEND;   
   break;      

   default:            //其它命令,都用0XFA回应   
   send_byte(ANSWERER);   
   buffer=ANSWERER;   
   break;      
  }   
}                       
/*************************主函数*****************************/   
void main()   
{   
uchar order;   
delay(500);//延时500ms   
send_byte(BAT);   
send_byte(ID);   
flag_send=read_byte_eeprom(ADDRESSH,ADDRESSL);   
WDT_CONTR=0X3E;//看门狗初始化   
while(1)   
  {   
   keyscan();   
   if(!mouse_data)   
    {   
    order=receive_byte();   
    manage(order);   
    }   
   WDT_CONTR=0X3E;//喂狗         
  }   
}   


回复

使用道具 举报

ID:244871 发表于 2017-11-2 10:17 | 显示全部楼层
怎么调试交互,自己顶一下,希望有人指点。贴出来我改过的代码。

/************************************************************/   
/*文件名称:单片机模拟PS/2鼠标程序                          */                                
/*作 者:蒋毅                                               */   
/*版 本:2008-6                                             */   
/*说 明:                                                  */   
/*修改记录:                                                 */   
/************************************************************/   
#include <STC12C5410AD.H>     
#include <intrins.h>   
#define uchar unsigned char   
#define uint  unsigned int   
/******************常用命令及参数定义************************/   
//EEPROM   
#define isp_read         1   
#define isp_program      2   
#define isp_erase        3   
#define isp_con          0x80   
#define ADDRESSH         0X10   
#define ADDRESSL         0X00   
   
//HOST-->MOUSE   
#define DISABLE_SEND     0XF5   //disable data reprorting   
#define ENABLE_SEND      0XF4   //enable data reprorting   
#define RESET            0XFF   //reset   
#define GETID            0XF2   //get device id   
#define SATATUS_REQUEST  0XE9   //datatus request   
#define HMRESEND         0XFE   //host ask mouse resend   
#define ERROR            0X55   //receive eeror   
   
//MOUSE-->HOST   
#define ANSWERER         0XFA   //answerer   
#define ID               0X00   //device id   
#define BAT              0XAA   //bat   
#define RESEND           0XFE   //resend   
#define SATATUS3         0X02   //satatus3   
#define SATATUS4         0X64   //satatus4
#define LBUTTONDOWN            0X09   //left button down
#define LBUTTONUP        0X08   //left button up
#define DATABAG          0x08;     
   
/***********************引脚定义*****************************/   
sbit  mouse_clk=P3^3;   
sbit  mouse_data=P3^5;   
sbit  ms1=P1^0;   
//sbit  ms2=P1^6;   
//sbit  ctls=P3^4;   
/***********************全局变量*****************************/   
uchar flag_send=0;//允许发送标志位   
uchar buffer=0;//命令缓冲单元   
/***********************函数声明*****************************/   
void delay10us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=1;a>0;a--);
}
void delay5us(void)   //误差 0us
{
    _nop_();  //if Keil,require use intrins.h
}
void delay20us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=3;b>0;b--)
        for(a=1;a>0;a--);
}
void delay50us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=9;b>0;b--)
        for(a=1;a>0;a--);
}  
//*********************读EEPROM一字节************************/   
uchar read_byte_eeprom(uchar addth,addtl)   
{   
uchar temp_data;   
ISP_ADDRH=addth;   
ISP_ADDRL=addtl;   
EA=0;   
ISP_CONTR=isp_con;   
ISP_CMD=isp_read;   
ISP_TRIG=0x46;   
ISP_TRIG=0xB9;   
temp_data=ISP_DATA;   
EA=1;   
return temp_data;   
}   
//*********************写EEPROM一字节***********************/   
void program_byte_eeprom(uchar temp_data, addth,addtl)   
{   
ISP_DATA=temp_data;   
ISP_ADDRH=addth;   
ISP_ADDRL=addtl;   
EA=0;   
ISP_CONTR=isp_con;   
ISP_CMD=isp_program;   
ISP_TRIG=0x46;   
ISP_TRIG=0xB9;   
EA=1;   
}   
//********************擦除EEPROM一扇区子函数*****************/   
void erase_sector_eeprom(uchar addth,addtl)   
{   
ISP_ADDRH=addth;   
ISP_ADDRL=addtl;   
EA=0;   
ISP_CONTR=isp_con;   
ISP_CMD=isp_erase;   
ISP_TRIG=0x46;   
ISP_TRIG=0xB9;   
EA=1;   
}   
/*******************ms级延时子函数***************************/   
void delay50ms(void)   //误差 0us
{
    unsigned char a,b;
    for(b=165;b>0;b--)
        for(a=150;a>0;a--);
}
void delay20ms(void)   //误差 0us
{
    unsigned char a,b;
    for(b=215;b>0;b--)
        for(a=45;a>0;a--);
}
void delay500ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=205;c>0;c--)
        for(b=116;b>0;b--)
            for(a=9;a>0;a--);
}
/****************ps/2发送单个位到PC函数**********************/   
void send_bit(bit senbit)   
{   
mouse_data=senbit; //设置/复位数据   
delay20us();      //延迟20us   
mouse_clk=0;       //将时钟拉低   
delay20us();  
delay20us();    //延迟40us   
mouse_clk=1;       //释放时钟   
}   
/***************ps/2发送单个字节到PC函数*********************/   
void send_byte(uchar tmp)   
{   
uchar i;   
uchar temp,check;   
temp=0;   
check=0;   
while(!mouse_clk);//等待CLK为高   
delay50us();//延时50us   
if(mouse_clk)//判断CLK是否为高,是:发送,否:放弃,转到接收程序   
  {   
   delay20us();//延时20us   
   for(i=0;i<11;i++)   
    {   
     delay20us();//延时20us   
     if(i==0) send_bit(0);//发送起始位0   
     else   
      {   
       if(i>=1&&i<9)//发送数据位   
        {   
         temp=tmp;   
         temp>>=(i-1);   
         temp=temp&0x01;   
         if(temp==0x01){send_bit(1);check++;}   
         else send_bit(0);   
        }   
       else   
         {   
         if(i==9)//发送校验位   
          {   
           check=check&0x01;   
           if(check==0x01) send_bit(0);//奇校验   
           else send_bit(1);   
          }   
         else send_bit(1);//发送停止位   
         }   
        }   
     if(mouse_clk==1) continue;//判断时钟是否被主机拉低,是-放弃发送   
     else break;   
    }   
    delay20us();
        delay10us();//延时30us   
  }   
}   
/********************ps/2接收PC单个位函数********************/   
bit receive_bit()   
{   
bit tbit;   
tbit=0;   
delay20us();    //延迟20us   
mouse_clk=0;     //把时钟线拉低   
delay20us();
delay20us();    //延迟40us   
mouse_clk=1;     //释放时钟   
delay20us();    //延迟20us   
tbit=mouse_data; //读取数据   
return tbit;     //返回数据   
}   
/**********************ps/2输出应答位函数********************/   
void send_answerer()   
{   
delay10us();
delay5us();//延迟15us   
mouse_data=0;//把数据线拉低   
delay5us(); //延迟5us   
mouse_clk=0; //把时钟线拉低   
delay20us();
delay20us();//延迟40us   
mouse_clk=1; //释放时钟线   
delay5us(); //延迟5us   
mouse_data=1;//释放数据线   
}   
/*******************ps/2接收PC单个字节函数*******************/   
uchar receive_byte()   
{   
uchar i,temp,rdata,check;   
bit tmp,check_bit;   
tmp=0;   
check_bit=0;   
temp=0;   
rdata=0;   
check=0;   
while(!mouse_clk);//等待时钟为高   
if(!mouse_data)//判断数据线为低,是-接收,否-有错误发生,放弃   
  {   
   for(i=0;i<10;i++)//接收8个数据位,校验位,停止位   
    {   
     if(i>=0&&i<8)//读入8个数据位   
      {   
       tmp=receive_bit();   
       if(tmp==1) check++;   
       temp=(uchar)tmp;   
       temp<<=i;   
       rdata=rdata|temp;        
      }   
     else if(i==8)//读入校验位   
       check_bit=receive_bit();   
     else //读入停止位   
      tmp=receive_bit();   
     if(mouse_clk==1) continue;//判断时钟是否被主机拉低,是-放弃接收   
     else return 0x55;   
    }   
   /*判断停止位是否为1,否,产生一错误标志*/   
   if(!mouse_data) //否   
    {   
     while(!mouse_data);   
     return 0x55;   
    }   
   else //停止位为1   
    {   
     send_answerer();//输出应答位   
     check=(check+(uchar)check_bit)&0x01;   
     if(check==0)//检查校验位   
       return 0x55;//校验错误   
     else  return rdata;//返回收到的命令   
    }   
   }   
else return 0x55;   
}   
/***********************键盘扫描函数*************************/   
void keyscan()   
{   
// uchar i;           
if(flag_send)//判断是否允许数据报告   
{   
if(ms1==0)//判断是否有键按下   
  {   
   delay20ms();//延时消抖   
   if(ms1==0)   
    {   
     delay50ms();//延时50ms   
     send_byte(LBUTTONDOWN);   
     send_byte(ID);// 发送位移按键数据包   
     send_byte(ID);
         }
   }        
   else  
   {   
      delay20ms();//延时消抖   
      if(ms1==1)   
      {   
       delay50ms();//延时50ms   
       send_byte(LBUTTONUP);   
       send_byte(ID);// 发送位移按键数据包   
       send_byte(ID);
          }   
   }   
  }   
}   
/***********************处理主机命令函数*********************/   
void manage(uchar ljmp)   
{   
switch(ljmp)   
  {   
   case RESET:         //主机通知MOUSE复位     
   send_byte(ANSWERER);   
   send_byte(BAT);   
   send_byte(ID);   
   buffer=ID;   
   break;   
   
   case GETID:         //主机通知MOUSE获得ID   
   send_byte(ANSWERER);   
   send_byte(ID);   
   buffer=ID;   
   break;   
   
   case ENABLE_SEND :    //使能数据报告   
   send_byte(ANSWERER);   
   buffer=ANSWERER;   
   flag_send=1;   
   erase_sector_eeprom(ADDRESSH,ADDRESSL);   
   program_byte_eeprom(0X01,ADDRESSH,ADDRESSL);   
   break;   
   
   case DISABLE_SEND :   
   send_byte(ANSWERER);//禁止数据报告   
   buffer=ANSWERER;   
   flag_send=0;   
   erase_sector_eeprom(ADDRESSH,ADDRESSL);   
   break;      
   
   case SATATUS_REQUEST://主机通知MOUSE告诉状态信息   
   send_byte(ANSWERER);   
   send_byte(ID);   
   send_byte(SATATUS3);   
   send_byte(SATATUS4);   
   buffer=SATATUS4;   
   break;   
   
   case ERROR:         //MOUSE接收错误,通知主机重发   
   send_byte(RESEND);   
   buffer=RESEND;   
   break;      
   
   default:            //其它命令,都用0XFA回应   
   send_byte(ANSWERER);   
   buffer=ANSWERER;   
   break;      
  }   
}                       
/*************************主函数*****************************/  
void main()   
{   
uchar order;  
delay500ms();//延时500ms   
send_byte(BAT);   
send_byte(ID);   
flag_send=read_byte_eeprom(ADDRESSH,ADDRESSL);   
WDT_CONTR=0X3E;//看门狗初始化   
while(1)   
  {   
   keyscan();   
   if(!mouse_data)   
    {   
    order=receive_byte();   
    manage(order);   
    }   
   WDT_CONTR=0X3E;//喂狗         
  }   
}   
   
回复

使用道具 举报

ID:244871 发表于 2017-11-2 16:18 | 显示全部楼层
我在处理收到数据的地方加了一句将p13端口置为低电平,重新加电量了一下是低电平,说明ps鼠标连接电脑成功了,可是按键按下没有任何反应,求指教啊。
回复

使用道具 举报

ID:272876 发表于 2019-7-16 11:10 | 显示全部楼层
好了吗
回复

使用道具 举报

ID:272876 发表于 2019-7-16 16:02 | 显示全部楼层
解决了吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表