找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

帖子
查看: 5062|回復(fù): 4
收起左側(cè)

請(qǐng)教:?jiǎn)纹瑱C(jī)讀ps/2鼠標(biāo)為什么數(shù)據(jù)是錯(cuò)誤的?

[復(fù)制鏈接]
ID:98930 發(fā)表于 2015-12-12 15:52 | 顯示全部樓層 |閱讀模式
本人新手,使用郭天祥老師的51單片機(jī)學(xué)習(xí)版,GTX TX-1C。想用單片機(jī)讀取ps/2鼠標(biāo)的移動(dòng)信息,但是讀的數(shù)據(jù)是錯(cuò)誤的。
哪位老師能幫忙看一下錯(cuò)在哪里?謝謝。

代碼如下:

主程序:

  1. /**
  2. * 單片機(jī)接PS2口鼠標(biāo),獲取鼠標(biāo)移動(dòng)數(shù)據(jù)和單擊事件
  3. * 并在LCD1602上顯示
  4. */

  5. #include <reg52.h>
  6. #include <MOUSE.H>
  7. #include <LCD1602_4.H>
  8. #include <DELAY52.H>
  9. #include <SHUMA.H>


  10. sbit beep=P2^3;  // 單擊出現(xiàn)時(shí)發(fā)出聲響
  11. sbit test=P3^0;


  12. void init();
  13. void Mouse_start();

  14. /**
  15. *  主程序循環(huán)檢測(cè)鼠標(biāo)位置和按鍵
  16. *        并將相關(guān)信息寫(xiě)入到LCD1602中
  17. */
  18. void main(){
  19.   uchar i=0;

  20.   init();
  21.   Mouse_start();

  22.   // 初始化數(shù)據(jù)指針和接收緩沖區(qū)
  23.   mouse_pBuffer=0;
  24.   mouse_pData=0;
  25.   for(i=0;i<4;i++)
  26.      mouse_data[i]=0x74;
  27.   for(i=0;i<11;i++)
  28.      mouse_buffer[i]=0;

  29.   while(1){
  30.         // 顯示鼠標(biāo)當(dāng)前位置
  31.         CLEARSCREEN;

  32.         LCD1602_write_string(0,0,"x:");
  33.         LCD1602_write_int(0,2,move_x);
  34.         LCD1602_write_string(0,8,"y:");
  35.         LCD1602_write_int(0,10,move_y);


  36.         // 顯示按鍵狀態(tài)
  37.         if(mouse_data[0]&0x01){  // 點(diǎn)下左鍵
  38.                 //beep=0;
  39.                 LCD1602_write_string(1,0,"left");
  40.         }else if(mouse_data[0]&0x02){                // 點(diǎn)下右鍵
  41.                 //beep=0;
  42.                 LCD1602_write_string(1,0,"right");
  43.         }else if(mouse_data[0]&0x04){                // 點(diǎn)下中鍵
  44.                 //beep=0;
  45.                 LCD1602_write_string(1,0,"middle");
  46.         }else {                 
  47.                 beep=1;
  48.                 LCD1602_write_string(1,0,"nothing");
  49.         }
  50.        
  51.         delayxms(50);
  52.   }
  53.   
  54. }

  55. /**
  56. *  初始化各元器件
  57. */
  58. void init(){
  59.   LED_init();          // 初始化LED
  60.   SHUMA_init();   // 初始化數(shù)碼管
  61.   LCD1602_init(); // 初始化液晶1602
  62.   Mouse_init();          // 初始化鼠標(biāo)
  63.   COM_init();     // 串口初始化
  64. }

  65. /**
  66. * 設(shè)置鼠標(biāo)進(jìn)入流模式
  67. */
  68. void Mouse_start(){
  69.   
  70.   LCD1602_write_string(1,0,"start mouse....");  
  71.   host_to_mouse(0xf4);    // 設(shè)置鼠標(biāo)使能,開(kāi)始工作
  72.   EX1=0;
  73.   delayxms(5000);
  74.   EX1=1;
  75. }
復(fù)制代碼

與鼠標(biāo)有關(guān)的頭文件MOUSE.H

  1. #ifndef MOUSE_H
  2. #define MOUSE_H

  3. // 晶振在11.0592MHZ下

  4. #include "DELAY52.H"
  5. #include "LCD1602_4.H"
  6. #include "LED.H"
  7. #include "COM.H"
  8. #define delay10{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
  9. #define delay100{delay10;delay10;delay10;delay10;delay10;delay10;delay10;delay10;delay10;delay10;}

  10. sbit mouse_SDA=P3^6;  // 數(shù)據(jù)線
  11. sbit mouse_CLK=P3^3;  // 時(shí)鐘線,外部中斷1輸入端口,低電平或下降沿觸發(fā)

  12. bit pp=0;   // 奇偶校驗(yàn)位
  13. bit ACK=0;        // 響應(yīng)
  14. uchar flag=0; // 標(biāo)志位,鼠標(biāo)初始化成功,開(kāi)始發(fā)送數(shù)據(jù)則置1

  15. uchar bdata mouse_byte;  // 接收到的字節(jié),bdata為可尋址的片內(nèi)RAM
  16. sbit mouse_byte_bit0=mouse_byte^0;
  17. sbit mouse_byte_bit1=mouse_byte^1;
  18. sbit mouse_byte_bit2=mouse_byte^2;
  19. sbit mouse_byte_bit3=mouse_byte^3;
  20. sbit mouse_byte_bit4=mouse_byte^4;
  21. sbit mouse_byte_bit5=mouse_byte^5;
  22. sbit mouse_byte_bit6=mouse_byte^6;
  23. sbit mouse_byte_bit7=mouse_byte^7;

  24. uchar bdata mouse_function;  // 功能信息字節(jié)
  25. uchar mouse_buffer[11];      // 接收位數(shù)據(jù)緩沖區(qū)
  26. uchar mouse_pBuffer=0;                  // 接收位數(shù)據(jù)緩沖區(qū)的指針
  27. uchar mouse_data[4];   // 接收鼠標(biāo)數(shù)據(jù)緩沖區(qū),分別存放:功能信息字節(jié),x位偏移量,y位偏移量
  28. uchar mouse_pData=0;   // 鼠標(biāo)數(shù)據(jù)緩沖區(qū)的指針

  29. uint move_x=10000;
  30. uint move_y=10000;
  31. uint move_z=0;


  32. void Mouse_start();
  33. void host_to_mouse(uchar cmd);


  34. void Mouse_init(){
  35.         mouse_pData=0;
  36.         mouse_pBuffer=0;

  37.     EA=1;        // 開(kāi)放中斷
  38.         EX1=1;  // 允許外部中斷1
  39.         PX1=1;  // 設(shè)置外部中斷1為最高優(yōu)先級(jí)
  40. }


  41. /**
  42. * 主機(jī)發(fā)送數(shù)據(jù)
  43. * 因?yàn)橹鳈C(jī)不產(chǎn)生通信時(shí)鐘,所以主機(jī)要發(fā)送數(shù)據(jù),
  44. * 必須控制鼠標(biāo)產(chǎn)生時(shí)鐘信號(hào)
  45. */
  46. void host_to_mouse(uchar cmd){
  47.         uchar i;

  48.         EX1=0;  // 主設(shè)備向從設(shè)備發(fā)送命令時(shí),關(guān)閉外部中斷

  49.         // 計(jì)算奇偶校驗(yàn)位
  50.         ACC=cmd;
  51.                   //P為奇偶標(biāo)志位,反映累加器ACC內(nèi)容的奇偶性
  52.              //如果ACC中的運(yùn)算結(jié)果有偶數(shù)個(gè)1,則P為0,否則為1
  53.                          //使用pp對(duì)P求反的目的是最終使用奇校驗(yàn)

  54.         mouse_CLK=0;  // 主機(jī)下拉時(shí)鐘線,至少100μs以抑制鼠標(biāo)的通信
  55.         delayus(200);
  56.         mouse_SDA=0;   // 然后下拉數(shù)據(jù)線,等于起始位
  57.         delayus(40);
  58.         mouse_CLK=1;   // 并釋放時(shí)鐘線,鼠標(biāo)檢測(cè)到該序列后會(huì)在10ms內(nèi)產(chǎn)生時(shí)鐘信號(hào)

  59.         // 鼠標(biāo)產(chǎn)生時(shí)鐘后,主機(jī)即可向鼠標(biāo)通過(guò)數(shù)據(jù)線發(fā)送指定的數(shù)據(jù)cmd
  60.         for(i=0;i<=7;i++){
  61.                  while(mouse_CLK==1);  // 等待低,準(zhǔn)備數(shù)據(jù)
  62.                 mouse_SDA=(cmd>>i)&0x01;
  63.                 while(mouse_CLK==0);  // 等待高,發(fā)送數(shù)據(jù)
  64.         }

  65.         while(mouse_CLK==1);
  66.         mouse_SDA=~P; // 發(fā)送奇偶校驗(yàn)位
  67.         while(mouse_CLK==0);

  68.         while(mouse_CLK==1);
  69.         mouse_SDA=1;   // 發(fā)送停止位
  70.         while(mouse_CLK==0);
  71.        
  72.         while(mouse_CLK==1);
  73.         //ACK=mouse_SDA;  // 接收應(yīng)答位,此時(shí)時(shí)鐘處于低
  74.         while(mouse_CLK==0);

  75.         EX1=1;
  76. }



  77. /**
  78. * 奇校驗(yàn),正確返回1,否則返回0
  79. */
  80. uchar Checkout(){
  81.         ACC=mouse_byte;
  82.         if(~P==mouse_buffer[9])
  83.                 return 1;
  84.         else
  85.                 return 0;
  86. }

  87. /**
  88. * 分析收到的數(shù)據(jù)
  89. */
  90. void data_analyse(){

  91.         // 將收到的11位信號(hào)中截取8位數(shù)據(jù)存放到mouse_byte字節(jié)中
  92.         mouse_byte_bit0=mouse_buffer[1];
  93.         mouse_byte_bit1=mouse_buffer[2];
  94.         mouse_byte_bit2=mouse_buffer[3];
  95.         mouse_byte_bit3=mouse_buffer[4];
  96.         mouse_byte_bit4=mouse_buffer[5];
  97.         mouse_byte_bit5=mouse_buffer[6];
  98.         mouse_byte_bit6=mouse_buffer[7];
  99.         mouse_byte_bit7=mouse_buffer[8];


  100.         // 如果校驗(yàn)位正確,則更新新的值,否則原位置不發(fā)生變化
  101.         if(Checkout()){
  102.            if(mouse_pData<3){
  103.                    mouse_data[mouse_pData++]=mouse_byte;
  104.            }
  105.            if(mouse_pData==3){  //  3個(gè)字節(jié)數(shù)據(jù)已經(jīng)收齊

  106.              // 向串口發(fā)送收到的三個(gè)字節(jié)
  107.                  COM_send_hex(mouse_data[0]);
  108.                  COM_send_hex(mouse_data[1]);
  109.                  COM_send_hex(mouse_data[2]);
  110.                  COM_send_char(0x0d);
  111.                  COM_send_char(0x0a);

  112.                     mouse_pData=0;
  113.                  if(mouse_data[0]&0x10){ // 如果"X sign bit"為1,表示鼠標(biāo)向左移
  114.                         move_x-=(256-mouse_data[1]); // x坐標(biāo)減,值為二進(jìn)制補(bǔ)碼
  115.                  }else{
  116.                          move_x+=mouse_data[1];
  117.                  }
  118.                  if(mouse_data[0]&0x20){ // 如果"y sign bit"為1,表示鼠標(biāo)向上移
  119.                         move_y-=(256-mouse_data[2]); // y坐標(biāo)減,值為二進(jìn)制補(bǔ)碼
  120.                  }else{
  121.                          move_y+=mouse_data[2];
  122.                  }
  123.            }
  124.         }
  125. }


  126. /**
  127. * 外部中斷1,下降沿觸發(fā),觸發(fā)后直接可以讀取數(shù)據(jù)。大約每40us中斷一次
  128. */
  129. void ReceiveData(void) interrupt 2{
  130.         if(mouse_pBuffer<=10){    // 收到11位數(shù)據(jù)
  131.                 LED_light(1,1);
  132.                 while(mouse_CLK==1);
  133.                 mouse_buffer[mouse_pBuffer++]=mouse_SDA;  // 接收數(shù)據(jù)
  134.         }
  135.         if(mouse_pBuffer==10){   // 當(dāng)mouse_pBuffer讀到第9位的時(shí)候,就開(kāi)始分析數(shù)據(jù)
  136.             LED_light(1,0);
  137.                 mouse_pBuffer=0;   // 重置偏移值
  138.                  data_analyse();    // 數(shù)據(jù)分析
  139.         }

  140. }

  141. #endif
復(fù)制代碼

謝謝,等回復(fù)。




相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

ID:98930 發(fā)表于 2015-12-12 22:39 | 顯示全部樓層
上位機(jī)顯示從鼠標(biāo)獲取到的數(shù)據(jù)亂七八糟,根本沒(méi)有規(guī)律,不知道怎么回事了,請(qǐng)教....
單片機(jī).jpg
回復(fù)

使用道具 舉報(bào)

ID:59703 發(fā)表于 2015-12-19 05:54 | 顯示全部樓層
學(xué)習(xí)一下,期待大神來(lái)解答。
回復(fù)

使用道具 舉報(bào)

ID:99905 發(fā)表于 2015-12-21 23:25 | 顯示全部樓層
樓主用的哪款芯片?和線纜的長(zhǎng)度等等是否有關(guān)?做ISP下載線時(shí)被線纜的問(wèn)題困擾了好久。再檢查檢查插口定義,祝你成功。
真心希望能夠幫到你。
回復(fù)

使用道具 舉報(bào)

ID:77282 發(fā)表于 2017-3-27 17:32 | 顯示全部樓層
這數(shù)據(jù)應(yīng)該是對(duì)的,
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表