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

QQ登錄

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

搜索
查看: 18061|回復(fù): 3
收起左側(cè)

PS2無(wú)線手柄解碼 附單片機(jī)程序

[復(fù)制鏈接]
ID:123816 發(fā)表于 2017-11-25 21:34 | 顯示全部樓層 |閱讀模式
本帖最后由 ryuby 于 2017-11-26 09:48 編輯

參考前輩大蝦的資料,用Atmega128A對(duì)PS2無(wú)線手柄進(jìn)行解碼,并在8位數(shù)碼管上顯示按鍵值

自己總結(jié)如下:
蹬蹬蹬。。。主角登場(chǎng):
無(wú)線PS2手柄+遙控接收器+便于接線的轉(zhuǎn)接板
PSII.jpg


遙控接收器和轉(zhuǎn)接板插接在一起后的樣子 IMG_20171125_200939R.jpg

轉(zhuǎn)接板上的接線引腳有以下幾個(gè):
DAT->手柄到單片機(jī) 同步傳送于時(shí)鐘下降沿 時(shí)序圖中的DI
CMD->單片機(jī)到手柄  同步傳送于時(shí)鐘下降沿 時(shí)序圖中的DO      
CS->提供手柄觸發(fā)信號(hào),通訊期間處于低電平
CLK->時(shí)鐘信號(hào),由單片機(jī)發(fā)出

時(shí)序圖.jpg


引用其他資料的說(shuō)明如下:
1.“通訊過(guò)程中, 一串?dāng)?shù)據(jù)通訊完成后 CS 才會(huì)由低轉(zhuǎn)高,不是 1 個(gè)字節(jié)通訊完成后就由低轉(zhuǎn)高,在通訊期間,一直處于低電平。
2.“在時(shí)鐘下降沿時(shí),完成數(shù)據(jù)的發(fā)送與接收,發(fā)送和接收是同時(shí)完成的。當(dāng)單片機(jī)想讀手柄數(shù)據(jù)或向手柄發(fā)送命令時(shí),將會(huì)拉低 CS 線電平,并發(fā)出一個(gè)命令“0x01”;柄會(huì)回復(fù)它的 ID 0x41=綠燈模式,0x73=燈模式”;在手柄發(fā)送 ID 的同時(shí),單片機(jī)將傳送 0x42,請(qǐng)求數(shù)據(jù);隨后手柄發(fā)送出 0x5A,告訴單片機(jī)‘數(shù)據(jù)來(lái)
3.“一個(gè)通訊周期有 9 個(gè)字節(jié)(8 位),這些數(shù)據(jù)是依次按位傳送


  以上說(shuō)白了就是:
  按照時(shí)序圖,每次通訊周期,都是先給手柄(也就是單片機(jī)給接收器)通過(guò)CMD引腳(DO)依次發(fā)9組數(shù)據(jù),分別是:
  0x01,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00

  與此同時(shí),通過(guò)DAT引腳(DI)收到相對(duì)位的9組數(shù)據(jù),程序中我將收到的數(shù)據(jù)存在了re_code[ ]這個(gè)數(shù)組中;
  手柄上的按鍵碼值被存儲(chǔ)的位置如下:
  re_code[3]==0xEF  //左4個(gè)按鍵的 上
  re_code[3]==0xBF  //左4個(gè)按鍵的 下
  re_code[3]==0x7F  //左4個(gè)按鍵的 左
  re_code[3]==0xDF  //左4個(gè)按鍵的 右

  re_code[3]==0xFE  //SELECT鍵
  re_code[3]==0xF7  //START鍵

  re_code[4]==0xEF  //右4個(gè)按鍵的 △
  re_code[4]==0xBF  //右4個(gè)按鍵的 ×
  re_code[4]==0x7F  //右4個(gè)按鍵的 □
  re_code[4]==0xDF  //右4個(gè)按鍵的 ○

  re_code[4]==0xFB  //左1,2個(gè)按鍵的 L1
  re_code[4]==0xFE  //左1,2個(gè)按鍵的 L2
  re_code[4]==0xF7  //右1,2個(gè)按鍵的 R1
  re_code[4]==0xFD  //右1,2個(gè)按鍵的 R2

沒(méi)有按鍵按下時(shí),以上各位數(shù)組中的值為FF,按鍵按下數(shù)組值變化,并且支持按鍵組合鍵值輸出。

當(dāng)手柄MODE LED燈不亮?xí)r,左右搖桿功能等同左四右四按鍵

當(dāng)按下MODE鍵手柄MODE LED紅燈亮起
IMG_20171125_200634R.jpg

這個(gè)時(shí)候,左右兩個(gè)搖桿就能線性輸出了,有點(diǎn)像汽車(chē)油門(mén)有個(gè)逐漸變化量
左右搖桿處于中位時(shí)的左右值為80,上下值為7F

  re_code[5] 00——80——FF 右搖桿從左到右
  re_code[6] 00——7F——FF 右搖桿從上到下
  re_code[7] 00——80——FF 左搖桿從左到右
  re_code[8] 00——7F——FF 左搖桿從上到下

--------------------------------------------------------------------------------------------------
數(shù)碼管從左至右每2位對(duì)應(yīng)的分別是
左搖桿的左右值(re_code[7] 里的值)

左搖桿的上下值(re_code[8] 里的值)
左4個(gè)按鍵的鍵值(re_code[3] 里的值)

右4個(gè)按鍵及側(cè)面LR的鍵值(re_code[4] 里的值)
正常模式時(shí),如圖左側(cè)的小紅燈(MODE LED)不亮,頭四位數(shù)碼管不會(huì)變化只顯示FFFF

IMG_20171125_202059R.jpg


按下←鍵的顯示
IMG_20171125_202113R.jpg


按下右側(cè) “×” 鍵的鍵值顯示
IMG_20171125_202142R.jpg


按下【MODE】按鈕,小紅燈亮起,搖桿處于中間位置時(shí)的數(shù)碼管顯示
807F就顯示了左側(cè)搖桿位于中位的左右值和上下值
IMG_20171125_202046R.jpg


左搖桿被搖動(dòng)時(shí)的線性值顯示
IMG_20171125_202157R.jpg

IMG_20171125_202206R.jpg



程序中柄遙控接收器接口定義:
// DAT->  in  PD0     設(shè)置為輸入
// CMD-> out PD1   設(shè)置為輸出        
// CS->    out PD2
// CLK->  out PD3



這個(gè)PS2手柄還有震動(dòng)功能,本次沒(méi)有弄出來(lái),還請(qǐng)哪位大蝦指點(diǎn)一二。
為了不浪費(fèi)大家的黑幣(我的黑幣就總不夠用),我就直接將程序貼出來(lái)了,如下,不對(duì)的地方還請(qǐng)指正——————————————————————————————————————————————————————
#include <iom128v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int

#define cmd_set     (PORTD |=(1<<PD1))
#define cmd_clr     (PORTD &=~(1<<PD1))
#define cs_set        (PORTD |=(1<<PD2))
#define cs_clr        (PORTD &=~(1<<PD2))
#define clk_set       (PORTD |=(1<<PD3))
#define clk_clr       (PORTD &=~(1<<PD3))

  //DO數(shù)據(jù)
uchar scan[9]={0x01,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  //存放DI數(shù)據(jù)
uchar re_code[9];                                             
uint m;

//共陰數(shù)碼管段碼
uchar ddd[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
//位碼
uchar www[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};                                                                                

void port_init(void)
{
  DDRE=0xff;
  PORTE=0x00;  //段選

  DDRB=0xff;
  PORTB=0xff;  //位選        
        
  //PD0->DAT輸入;PD1->CMD輸出;PD2->CS輸出;PD3->CLK輸出
  DDRD  =(0<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD3) ;
  PORTD =0;
}

void delay(uint n)
{
        uint i;
        for(i=0;i<n;i++);
}

uchar scanout(uchar command)   //向手柄發(fā)送命令并接受反饋的子程序
{
    uchar i,j=1;
    uchar res=0;
    for(i=0;i<8;i++)     //逐位接收     
    {
          if(command&0x01)      cmd_set;
          else                            cmd_clr;
          command=command>>1;
          delay(1);
          clk_clr;
          delay(1);                              //這里延時(shí)很關(guān)鍵,太多了手柄就反應(yīng)遲鈍了
          if(PIND&0x01) res=res+j;      //這里就開(kāi)始同步接收DI值了
          j=j<<1;
          clk_set;
          delay(2);                 
    }
    return res;        
}
void Read_PS2(void)        //向手柄發(fā)送DO并將反饋DI存入re_code[ ]中
{
         uchar i;
         cs_clr;
         for(i=0;i<9;i++)        re_code=scanout(scan);
         cs_set;        
}                                             
void main(void)
{
        port_init();
        delay(50);
  while(1)
         {
         Read_PS2();
         delay(200);
         
         m=re_code[3]*256+re_code[4];
                 
         PORTE=ddd[m/256/16];
         PORTB=www[3];
         delay(50);
         PORTE=ddd[m/256%16];
         PORTB=www[2];
         delay(50);
         PORTE=ddd[m%256/16];
         PORTB=www[1];
         delay(50);
         PORTE=ddd[m%256%16];
         PORTB=www[0];
         delay(50);
                 
         PORTE=ddd[out[7]/16];
         PORTB=www[7];
         delay(50);
         PORTE=ddd[out[7]%16];
         PORTB=www[6];
         delay(50);
         PORTE=ddd[out[8]/16];
         PORTB=www[5];
         delay(50);
         PORTE=ddd[out[8]%16];
         PORTB=www[4];
         delay(50);        
        }
}

下面圖片中那個(gè)紅色的atmega128小板就是前些日子被我熔絲位寫(xiě)錯(cuò)導(dǎo)致昏迷后又救回來(lái)的那位。。。

IMG_20171125_200654R.jpg
IMG_20171125_201018R.jpg
IMG_20171125_202201R.jpg
IMG_20171125_202209R.jpg

評(píng)分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:380304 發(fā)表于 2018-7-28 20:29 | 顯示全部樓層
謝謝分享
回復(fù)

使用道具 舉報(bào)

ID:333428 發(fā)表于 2018-7-30 14:38 | 顯示全部樓層
樓主51 能連接這個(gè)手柄嗎

回復(fù)

使用道具 舉報(bào)

ID:28260 發(fā)表于 2021-6-30 10:22 | 顯示全部樓層
拜讀了,謝謝!
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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