标题:
请教:单片机读ps/2鼠标为什么数据是错误的?
[打印本页]
作者:
qixiaorui
时间:
2015-12-12 15:52
标题:
请教:单片机读ps/2鼠标为什么数据是错误的?
本人新手,使用郭天祥老师的51单片机学习版,GTX TX-1C。想用单片机读取ps/2鼠标的移动信息,但是读的数据是错误的。
哪位老师能帮忙看一下错在哪里?谢谢。
代码如下:
主程序:
/**
* 单片机接PS2口鼠标,获取鼠标移动数据和单击事件
* 并在LCD1602上显示
*/
#include <reg52.h>
#include <MOUSE.H>
#include <LCD1602_4.H>
#include <DELAY52.H>
#include <SHUMA.H>
sbit beep=P2^3; // 单击出现时发出声响
sbit test=P3^0;
void init();
void Mouse_start();
/**
* 主程序循环检测鼠标位置和按键
* 并将相关信息写入到LCD1602中
*/
void main(){
uchar i=0;
init();
Mouse_start();
// 初始化数据指针和接收缓冲区
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);
// 显示按键状态
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(); // 初始化数码管
LCD1602_init(); // 初始化液晶1602
Mouse_init(); // 初始化鼠标
COM_init(); // 串口初始化
}
/**
* 设置鼠标进入流模式
*/
void Mouse_start(){
LCD1602_write_string(1,0,"start mouse....");
host_to_mouse(0xf4); // 设置鼠标使能,开始工作
EX1=0;
delayxms(5000);
EX1=1;
}
复制代码
与鼠标有关的头文件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; // 数据线
sbit mouse_CLK=P3^3; // 时钟线,外部中断1输入端口,低电平或下降沿触发
bit pp=0; // 奇偶校验位
bit ACK=0; // 响应
uchar flag=0; // 标志位,鼠标初始化成功,开始发送数据则置1
uchar bdata mouse_byte; // 接收到的字节,bdata为可寻址的片内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; // 功能信息字节
uchar mouse_buffer[11]; // 接收位数据缓冲区
uchar mouse_pBuffer=0; // 接收位数据缓冲区的指针
uchar mouse_data[4]; // 接收鼠标数据缓冲区,分别存放:功能信息字节,x位偏移量,y位偏移量
uchar mouse_pData=0; // 鼠标数据缓冲区的指针
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; // 设置外部中断1为最高优先级
}
/**
* 主机发送数据
* 因为主机不产生通信时钟,所以主机要发送数据,
* 必须控制鼠标产生时钟信号
*/
void host_to_mouse(uchar cmd){
uchar i;
EX1=0; // 主设备向从设备发送命令时,关闭外部中断
// 计算奇偶校验位
ACC=cmd;
//P为奇偶标志位,反映累加器ACC内容的奇偶性
//如果ACC中的运算结果有偶数个1,则P为0,否则为1
//使用pp对P求反的目的是最终使用奇校验
mouse_CLK=0; // 主机下拉时钟线,至少100μs以抑制鼠标的通信
delayus(200);
mouse_SDA=0; // 然后下拉数据线,等于起始位
delayus(40);
mouse_CLK=1; // 并释放时钟线,鼠标检测到该序列后会在10ms内产生时钟信号
// 鼠标产生时钟后,主机即可向鼠标通过数据线发送指定的数据cmd
for(i=0;i<=7;i++){
while(mouse_CLK==1); // 等待低,准备数据
mouse_SDA=(cmd>>i)&0x01;
while(mouse_CLK==0); // 等待高,发送数据
}
while(mouse_CLK==1);
mouse_SDA=~P; // 发送奇偶校验位
while(mouse_CLK==0);
while(mouse_CLK==1);
mouse_SDA=1; // 发送停止位
while(mouse_CLK==0);
while(mouse_CLK==1);
//ACK=mouse_SDA; // 接收应答位,此时时钟处于低
while(mouse_CLK==0);
EX1=1;
}
/**
* 奇校验,正确返回1,否则返回0
*/
uchar Checkout(){
ACC=mouse_byte;
if(~P==mouse_buffer[9])
return 1;
else
return 0;
}
/**
* 分析收到的数据
*/
void data_analyse(){
// 将收到的11位信号中截取8位数据存放到mouse_byte字节中
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];
// 如果校验位正确,则更新新的值,否则原位置不发生变化
if(Checkout()){
if(mouse_pData<3){
mouse_data[mouse_pData++]=mouse_byte;
}
if(mouse_pData==3){ // 3个字节数据已经收齐
// 向串口发送收到的三个字节
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,下降沿触发,触发后直接可以读取数据。大约每40us中断一次
*/
void ReceiveData(void) interrupt 2{
if(mouse_pBuffer<=10){ // 收到11位数据
LED_light(1,1);
while(mouse_CLK==1);
mouse_buffer[mouse_pBuffer++]=mouse_SDA; // 接收数据
}
if(mouse_pBuffer==10){ // 当mouse_pBuffer读到第9位的时候,就开始分析数据
LED_light(1,0);
mouse_pBuffer=0; // 重置偏移值
data_analyse(); // 数据分析
}
}
#endif
复制代码
谢谢,等回复。
作者:
qixiaorui
时间:
2015-12-12 22:39
上位机显示从鼠标获取到的数据乱七八糟,根本没有规律,不知道怎么回事了,请教....
单片机.jpg
(75.84 KB, 下载次数: 117)
下载附件
2015-12-12 22:39 上传
作者:
08fuyoucai12
时间:
2015-12-19 05:54
学习一下,期待大神来解答。
作者:
永远的王同学
时间:
2015-12-21 23:25
楼主用的哪款芯片?和线缆的长度等等是否有关?做ISP下载线时被线缆的问题困扰了好久。再检查检查插口定义,祝你成功。
真心希望能够帮到你。
作者:
jiakuo25
时间:
2017-3-27 17:32
这数据应该是对的,
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1