標題:
請教:單片機讀ps/2鼠標為什么數(shù)據(jù)是錯誤的?
[打印本頁]
作者:
qixiaorui
時間:
2015-12-12 15:52
標題:
請教:單片機讀ps/2鼠標為什么數(shù)據(jù)是錯誤的?
本人新手,使用郭天祥老師的51單片機學(xué)習(xí)版,GTX TX-1C。想用單片機讀取ps/2鼠標的移動信息,但是讀的數(shù)據(jù)是錯誤的。
哪位老師能幫忙看一下錯在哪里?謝謝。
代碼如下:
主程序:
/**
* 單片機接PS2口鼠標,獲取鼠標移動數(shù)據(jù)和單擊事件
* 并在LCD1602上顯示
*/
#include <reg52.h>
#include <MOUSE.H>
#include <LCD1602_4.H>
#include <DELAY52.H>
#include <SHUMA.H>
sbit beep=P2^3; // 單擊出現(xiàn)時發(fā)出聲響
sbit test=P3^0;
void init();
void Mouse_start();
/**
* 主程序循環(huán)檢測鼠標位置和按鍵
* 并將相關(guān)信息寫入到LCD1602中
*/
void main(){
uchar i=0;
init();
Mouse_start();
// 初始化數(shù)據(jù)指針和接收緩沖區(qū)
mouse_pBuffer=0;
mouse_pData=0;
for(i=0;i<4;i++)
mouse_data[i]=0x74;
for(i=0;i<11;i++)
mouse_buffer[i]=0;
while(1){
// 顯示鼠標當前位置
CLEARSCREEN;
LCD1602_write_string(0,0,"x:");
LCD1602_write_int(0,2,move_x);
LCD1602_write_string(0,8,"y:");
LCD1602_write_int(0,10,move_y);
// 顯示按鍵狀態(tài)
if(mouse_data[0]&0x01){ // 點下左鍵
//beep=0;
LCD1602_write_string(1,0,"left");
}else if(mouse_data[0]&0x02){ // 點下右鍵
//beep=0;
LCD1602_write_string(1,0,"right");
}else if(mouse_data[0]&0x04){ // 點下中鍵
//beep=0;
LCD1602_write_string(1,0,"middle");
}else {
beep=1;
LCD1602_write_string(1,0,"nothing");
}
delayxms(50);
}
}
/**
* 初始化各元器件
*/
void init(){
LED_init(); // 初始化LED
SHUMA_init(); // 初始化數(shù)碼管
LCD1602_init(); // 初始化液晶1602
Mouse_init(); // 初始化鼠標
COM_init(); // 串口初始化
}
/**
* 設(shè)置鼠標進入流模式
*/
void Mouse_start(){
LCD1602_write_string(1,0,"start mouse....");
host_to_mouse(0xf4); // 設(shè)置鼠標使能,開始工作
EX1=0;
delayxms(5000);
EX1=1;
}
復(fù)制代碼
與鼠標有關(guān)的頭文件MOUSE.H
#ifndef MOUSE_H
#define MOUSE_H
// 晶振在11.0592MHZ下
#include "DELAY52.H"
#include "LCD1602_4.H"
#include "LED.H"
#include "COM.H"
#define delay10{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
#define delay100{delay10;delay10;delay10;delay10;delay10;delay10;delay10;delay10;delay10;delay10;}
sbit mouse_SDA=P3^6; // 數(shù)據(jù)線
sbit mouse_CLK=P3^3; // 時鐘線,外部中斷1輸入端口,低電平或下降沿觸發(fā)
bit pp=0; // 奇偶校驗位
bit ACK=0; // 響應(yīng)
uchar flag=0; // 標志位,鼠標初始化成功,開始發(fā)送數(shù)據(jù)則置1
uchar bdata mouse_byte; // 接收到的字節(jié),bdata為可尋址的片內(nèi)RAM
sbit mouse_byte_bit0=mouse_byte^0;
sbit mouse_byte_bit1=mouse_byte^1;
sbit mouse_byte_bit2=mouse_byte^2;
sbit mouse_byte_bit3=mouse_byte^3;
sbit mouse_byte_bit4=mouse_byte^4;
sbit mouse_byte_bit5=mouse_byte^5;
sbit mouse_byte_bit6=mouse_byte^6;
sbit mouse_byte_bit7=mouse_byte^7;
uchar bdata mouse_function; // 功能信息字節(jié)
uchar mouse_buffer[11]; // 接收位數(shù)據(jù)緩沖區(qū)
uchar mouse_pBuffer=0; // 接收位數(shù)據(jù)緩沖區(qū)的指針
uchar mouse_data[4]; // 接收鼠標數(shù)據(jù)緩沖區(qū),分別存放:功能信息字節(jié),x位偏移量,y位偏移量
uchar mouse_pData=0; // 鼠標數(shù)據(jù)緩沖區(qū)的指針
uint move_x=10000;
uint move_y=10000;
uint move_z=0;
void Mouse_start();
void host_to_mouse(uchar cmd);
void Mouse_init(){
mouse_pData=0;
mouse_pBuffer=0;
EA=1; // 開放中斷
EX1=1; // 允許外部中斷1
PX1=1; // 設(shè)置外部中斷1為最高優(yōu)先級
}
/**
* 主機發(fā)送數(shù)據(jù)
* 因為主機不產(chǎn)生通信時鐘,所以主機要發(fā)送數(shù)據(jù),
* 必須控制鼠標產(chǎn)生時鐘信號
*/
void host_to_mouse(uchar cmd){
uchar i;
EX1=0; // 主設(shè)備向從設(shè)備發(fā)送命令時,關(guān)閉外部中斷
// 計算奇偶校驗位
ACC=cmd;
//P為奇偶標志位,反映累加器ACC內(nèi)容的奇偶性
//如果ACC中的運算結(jié)果有偶數(shù)個1,則P為0,否則為1
//使用pp對P求反的目的是最終使用奇校驗
mouse_CLK=0; // 主機下拉時鐘線,至少100μs以抑制鼠標的通信
delayus(200);
mouse_SDA=0; // 然后下拉數(shù)據(jù)線,等于起始位
delayus(40);
mouse_CLK=1; // 并釋放時鐘線,鼠標檢測到該序列后會在10ms內(nèi)產(chǎn)生時鐘信號
// 鼠標產(chǎn)生時鐘后,主機即可向鼠標通過數(shù)據(jù)線發(fā)送指定的數(shù)據(jù)cmd
for(i=0;i<=7;i++){
while(mouse_CLK==1); // 等待低,準備數(shù)據(jù)
mouse_SDA=(cmd>>i)&0x01;
while(mouse_CLK==0); // 等待高,發(fā)送數(shù)據(jù)
}
while(mouse_CLK==1);
mouse_SDA=~P; // 發(fā)送奇偶校驗位
while(mouse_CLK==0);
while(mouse_CLK==1);
mouse_SDA=1; // 發(fā)送停止位
while(mouse_CLK==0);
while(mouse_CLK==1);
//ACK=mouse_SDA; // 接收應(yīng)答位,此時時鐘處于低
while(mouse_CLK==0);
EX1=1;
}
/**
* 奇校驗,正確返回1,否則返回0
*/
uchar Checkout(){
ACC=mouse_byte;
if(~P==mouse_buffer[9])
return 1;
else
return 0;
}
/**
* 分析收到的數(shù)據(jù)
*/
void data_analyse(){
// 將收到的11位信號中截取8位數(shù)據(jù)存放到mouse_byte字節(jié)中
mouse_byte_bit0=mouse_buffer[1];
mouse_byte_bit1=mouse_buffer[2];
mouse_byte_bit2=mouse_buffer[3];
mouse_byte_bit3=mouse_buffer[4];
mouse_byte_bit4=mouse_buffer[5];
mouse_byte_bit5=mouse_buffer[6];
mouse_byte_bit6=mouse_buffer[7];
mouse_byte_bit7=mouse_buffer[8];
// 如果校驗位正確,則更新新的值,否則原位置不發(fā)生變化
if(Checkout()){
if(mouse_pData<3){
mouse_data[mouse_pData++]=mouse_byte;
}
if(mouse_pData==3){ // 3個字節(jié)數(shù)據(jù)已經(jīng)收齊
// 向串口發(fā)送收到的三個字節(jié)
COM_send_hex(mouse_data[0]);
COM_send_hex(mouse_data[1]);
COM_send_hex(mouse_data[2]);
COM_send_char(0x0d);
COM_send_char(0x0a);
mouse_pData=0;
if(mouse_data[0]&0x10){ // 如果"X sign bit"為1,表示鼠標向左移
move_x-=(256-mouse_data[1]); // x坐標減,值為二進制補碼
}else{
move_x+=mouse_data[1];
}
if(mouse_data[0]&0x20){ // 如果"y sign bit"為1,表示鼠標向上移
move_y-=(256-mouse_data[2]); // y坐標減,值為二進制補碼
}else{
move_y+=mouse_data[2];
}
}
}
}
/**
* 外部中斷1,下降沿觸發(fā),觸發(fā)后直接可以讀取數(shù)據(jù)。大約每40us中斷一次
*/
void ReceiveData(void) interrupt 2{
if(mouse_pBuffer<=10){ // 收到11位數(shù)據(jù)
LED_light(1,1);
while(mouse_CLK==1);
mouse_buffer[mouse_pBuffer++]=mouse_SDA; // 接收數(shù)據(jù)
}
if(mouse_pBuffer==10){ // 當mouse_pBuffer讀到第9位的時候,就開始分析數(shù)據(jù)
LED_light(1,0);
mouse_pBuffer=0; // 重置偏移值
data_analyse(); // 數(shù)據(jù)分析
}
}
#endif
復(fù)制代碼
謝謝,等回復(fù)。
作者:
qixiaorui
時間:
2015-12-12 22:39
上位機顯示從鼠標獲取到的數(shù)據(jù)亂七八糟,根本沒有規(guī)律,不知道怎么回事了,請教....
單片機.jpg
(75.84 KB, 下載次數(shù): 117)
下載附件
2015-12-12 22:39 上傳
作者:
08fuyoucai12
時間:
2015-12-19 05:54
學(xué)習(xí)一下,期待大神來解答。
作者:
永遠的王同學(xué)
時間:
2015-12-21 23:25
樓主用的哪款芯片?和線纜的長度等等是否有關(guān)?做ISP下載線時被線纜的問題困擾了好久。再檢查檢查插口定義,祝你成功。
真心希望能夠幫到你。
作者:
jiakuo25
時間:
2017-3-27 17:32
這數(shù)據(jù)應(yīng)該是對的,
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1