怎么调试交互,自己顶一下,希望有人指点。贴出来我改过的代码。
/************************************************************/
/*文件名称:单片机模拟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;//喂狗
}
}
|