如果该程序已验证过的,用的是AVR系列单片机的IO口模拟PS2协议。
#include
#include
#include "myh.h"
//MOUSE
//时钟接CLK:5--INT0--PD2
#define PINMCLK (PIND&BIT2)
#define PRTMCLK_H {DDRD&=NBIT2;PORTD|=BIT2;}
#define PRTMCLK_L {DDRD|=BIT2;PORTD&=NBIT2;}
//数据接DAT:1--PC4
#define PINMDAT (PINC&BIT4)
#define PRTMDAT_H {DDRC&=NBIT4;PORTC|=BIT4;}
#define PRTMDAT_L {DDRC|=BIT4;PORTC&=NBIT4;}
//KEYBOARD
#define PINKCLK (PIND&BIT3)
#define PRTKCLK_H {DDRD&=NBIT3;PORTD|=BIT3;}
#define PRTKCLK_L {DDRD|=BIT3;PORTD&=NBIT3;}
//数据接DAT:1--PC4
#define PINKDAT (PINC&BIT5)
#define PRTKDAT_H {DDRC&=NBIT5;PORTC|=BIT5;}
#define PRTKDAT_L {DDRC|=BIT5;PORTC&=NBIT5;}
//sbit pclk=P3^2;
//sbit pdat=P3^1;
uchar wait;
uchar mcnt=0;
uchar kcnt=0;
schar axes_x=0,axes_y=0;
schar mbuf[4];
uchar kbuf[4];
void delay(uint t) //延时 t*10us
{
char i;
for(;t>0;t--)
for(i=10;i>0;i--);
}
uchar send2m(uchar dat)//高电平期间改变数据,下降沿发出去
{
uchar i,ack,intc,check=1;
uint buf;
//EX0=0;
//IE0=0;
intc=GICR;
GICR&=0x3f; //不使能中断
buf=dat;
for(i=0;i<8;i++)
{
check^=dat&0x01; //校验,出现奇数个一该位为0。
dat>>=1;
}
buf|=check<<8; //校验位
buf|=3<<9; //停止位,以及应答位
// pclk=0;
// pdat=0;
PRTMCLK_L;
PRTMDAT_L; //下接时钟和数据
delay(10);
// pclk=1; //请求
PRTMCLK_H; //释放时钟线
for(i=0;i<11;i++) //发送8位数据
{
while(PINMCLK); //等待下降沿
if(buf&0x01)
PRTMDAT_H
else
PRTMDAT_L
//pdat=buf&0x01;
buf>>=1;
//if(i==10)ack=pdat; //最后一位为输入的应答
if(i==10)ack=PINMDAT;
//while(!pclk);
while(!PINMCLK); //等待上升沿
}
PRTMDAT_H;
//EX0=1;
GICR=intc;
return ack;
}
void chuli(void)
{
mcnt=0;
axes_x+=(schar)mbuf[1];
axes_y+=(schar)mbuf[2];
}
void display(uint number)//从0到F显示
{
char i,n[4]={0}, //要显示的四个数字
num[16]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X27,0X7F,0X6F,
0X77,0X7C,0X39,0X5E,0X79,0X71};//十六个数字的段码
n[0]=number>>12&0X0F;
n[1]=number>>8 &0X0F;
n[2]=number>>4 &0X0F;
n[3]=number &0X0F;
for(i=0;i<4;i++)
{
PORTD=~(0X80>>i);
PORTB=num[n[i]];delay(500);
PORTB=0x00; //显示清空
}
}
void port_init(void)
{
DDRB = 0xFF;//B用于显示
PORTB = 0xFF;
DDRC = 0x0F;//PC4,PC5为输入
PORTC = 0x7F; //m103 output only
DDRD = 0xF0; //INT0 INT1 为输入
PORTD = 0xFF;
}
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
//external interupt on INT0
char i;
uint buf;
// EX0=0;
PRTKCLK_L; //抑制键盘时钟
//PRTKDAT_L;
//-while(1);
buf=0;
if(PINMDAT)
{
PORTC|=BIT0;
delay(10);
PORTC&=NBIT0;
return; //启始位为0
}
while(!PINMCLK); //等待启始位结束
for(i=0;i<10;i++) //8位数据+校验+停止,LSB在前
{
while(PINMCLK);//下降沿接收数据
if(PINMDAT)buf|=(1<
while(!PINMCLK);
}
mbuf[mcnt]=buf&0xff;
wait=50;
mcnt++;
if(mcnt==3)
chuli();
PRTKCLK_H; //允许键盘时钟
GIFR=0XC0; //向高两位写1,清中断标志
//IE0=0;
}
#pragma interrupt_handler int1_isr:3
void int1_isr(void)
{
char i;
uint buf;
PRTMCLK_L; //抑制鼠标时钟
buf=0;
if(PINKDAT)
{
PORTC|=BIT0;
delay(10);
PORTC&=NBIT0;
return; //启始位为0
}
while(!PINKCLK); //等待启始位结束
for(i=0;i<10;i++) //8位数据+校验+停止,LSB在前
{
while(PINKCLK);//下降沿接收数据
if(PINKDAT)buf|=(1<
while(!PINKCLK);
}
kbuf[kcnt]=buf&0xff;
kcnt=0;
PRTMCLK_H; //允许鼠标时钟
GIFR=0XC0; //向高两位写1,清中断标志
}
//call this routine to initialise all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
MCUCR = 0x0A; //1010,int0,int1 下降沿
GICR = 0xC0; //int1,int0 enable
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialised
}
void main()
{
uint dat;
init_devices();
send2m(0xff);
delay(10);
send2m(0xeb);
while(1)
{
//dat=axes_x<<8|axes_y;
dat=axes_x<<8|kbuf[0];
display(dat);
//display(kbuf[0]);
if(wait)
{
wait--;
if(wait==0)
mcnt=0;
}
}
}