|
//PS2鼠標(biāo)驅(qū)動程序
//測試發(fā)送其他命令鼠標(biāo)如何回復(fù)。比如0xff
#include <reg51.H>
sbit mouse_sda = P1^6; //鼠標(biāo)數(shù)據(jù)線
sbit mouse_clk = P3^2; //鼠標(biāo)時鐘線:單片機0號中斷
sbit led_jc = P0^7; //LED檢測鼠標(biāo)時鐘是否發(fā)生
sbit led_L = P0^3;
//按鍵LED指示,鼠標(biāo)左鍵
sbit led_R = P0^4; //按鍵LED指示,鼠標(biāo)右鍵
//數(shù)據(jù)定義
unsigned char n, m; //循環(huán)變量
unsigned int mouse_word;mouse_wordbf=0; //接收字16bits,臨時變量用于接受11位的數(shù)據(jù)
unsigned char mouse_data[3]; //接收字節(jié)緩沖區(qū),保存3字節(jié)的數(shù)據(jù)報告
bit mouse_left; //左鍵,
bit mouse_right;//右鍵,按鍵狀態(tài)變量
unsigned int move_x;//橫坐標(biāo)無符號整形2字節(jié)
unsigned int move_y;//縱坐標(biāo)
//函數(shù)聲明
void int0(void); //外部中斷INT0初始化
void delay100us(void); //延時100微妙 函數(shù)定義
void mouse_write_dat(unsigned char dat); //發(fā)送數(shù)據(jù)
void mouse_read_dat(void); //讀出數(shù)據(jù)
bit check_parity(void); //奇校驗
void ys (x);
void delay50ms(void); //50毫秒延時
//外部中斷INT0初始化
void int0(void) //初始化外部中斷p3.2狀態(tài)
{EA = 1; //總中斷
EX0 = 1; //外部中斷
PX0 = 1; //中斷優(yōu)先級
IT0 = 0; //低電平觸發(fā)
}
void delay100us(void)//這里是亂寫的延時函數(shù)居然正確。
{unsigned char i, j;
for(i = 30; i > 0; i--)
for(j = 1; j > 0; j--);
}
void ys (x)//這是一條測試用的延時函數(shù),可以延時幾秒鐘
{unsigned char ii, jj;
for(ii = x; ii > 0; ii--)
for(jj = 9000; jj > 0; jj--);
}
//外部中斷INT0服務(wù)
//接收完11位數(shù)據(jù)就開始處理
void INT0_intservice(void) interrupt 0 //安裝0號中斷
{EX0 = 0;
mouse_word >>= 1; //先向右空移一位
if(mouse_sda) mouse_word |= 0x0400;//先接收最低位00001000 00000000,
n++;
if(n == 11) {mouse_read_dat(); n = 0;}//接收完成則讀出數(shù)據(jù)
//檢led_jc=1; 測是否有時鐘信號
EX0 = 1;
}
//處理程序段
//讀出3字節(jié)數(shù)據(jù),數(shù)據(jù)整理、奇校驗、和指揮拆分3字節(jié)數(shù)據(jù)
void mouse_read_dat(void)
{mouse_data[m] = (unsigned char)(mouse_word >> 1);//去掉
mouse_wordbf=mouse_word;
mouse_word=0;
if(check_parity()) //奇校驗成功
{mouse_word = 0; //清接收數(shù)據(jù)字
m++;
if(m == 3) //數(shù)據(jù)處理,拆分數(shù)據(jù)包 注意拆分的是第一字節(jié)
{move_x+=mouse_data[2];//獲得位移量
move_y+=mouse_data[3];//獲得y位移量
if(mouse_data[0] & 0x01) mouse_left = 1;//左鍵
else mouse_left = 0;
if(mouse_data[0] & 0x02) mouse_right = 1;//右鍵
else mouse_right = 0;
m = 0;
}
}
}
//奇校驗
bit check_parity(void)
{ACC=mouse_data[m];
if(~P == (bit)(mouse_wordbf & 0x0200)) return 1; //奇校驗成功則返回1
else return 0; //奇校驗失敗則返回0
}
//發(fā)送數(shù)據(jù)
//發(fā)送11位數(shù)據(jù):1START-8DATA-1PARITY-1STOP
//并接收一個應(yīng)答位ack = 0
void mouse_write_dat(unsigned char dat)
{ unsigned char i; //循環(huán)變量
bit parity; //奇校驗位
EX0 = 0; //關(guān)閉外部中斷
ACC = dat; //存入累加器A,得到P(為偶校驗)
parity = ~P; //對P求反獲得奇校驗位
mouse_clk = 0;//拉低時鐘線
delay100us(); //至少延時100us
mouse_sda = 0;//發(fā)送起始位
mouse_clk = 1;//釋放時鐘線
for(i = 0; i < 8; i++)
{while(mouse_clk); //等待設(shè)備把時鐘線拉低
mouse_sda =(bit)(dat& 0x01); //先發(fā)送最低位
dat >>= 1; //下降沿寫入數(shù)據(jù)
while(!mouse_clk);//等待設(shè)備把時鐘線拉高
}
while(mouse_clk); //等待設(shè)備把時鐘線拉低
mouse_sda = parity; //發(fā)送奇校驗位
while(!mouse_clk); //等待設(shè)備把時鐘線拉高
while(mouse_clk); //等待設(shè)備把時鐘線拉低
mouse_sda = 1; //發(fā)送停止位
while(!mouse_clk);//等待設(shè)備把時鐘線拉高
while(mouse_sda); //等待接收應(yīng)答位(總是為0)
while(mouse_clk); //等待設(shè)備把時鐘線拉低
while(!mouse_clk); //等待設(shè)備釋放時鐘線,把時鐘拉高
while(!mouse_sda); //等待設(shè)備釋放數(shù)據(jù)線,把時鐘拉高
EX0 = 1; //打開外部中斷INT0
}
void main(void)
{P0=0xff;//先把LED關(guān)了
mouse_clk = 1; //拉高時鐘線
ys(100000);
int0();
mouse_write_dat(0xf4); //立馬發(fā)送鼠標(biāo)使能命令過去
while(mouse_data[0] != 0xfa); //數(shù)據(jù)包的第一字節(jié)判斷鼠標(biāo)是否應(yīng)答,不然就一直停在這里
mouse_data[0] = 0; //清應(yīng)答數(shù)據(jù)
m = 0;
while(1)
{
//檢led_jc=0;//guandeng
led_L = mouse_left;//顯示數(shù)據(jù)包1的內(nèi)容
led_R = mouse_right;
P0=mouse_x;//P0口直接顯示x位移量的值
}
}
|
|