|
本帖最后由 ryuby 于 2017-11-26 09:48 編輯
參考前輩大蝦的資料,用Atmega128A對PS2無線手柄進行解碼,并在8位數(shù)碼管上顯示按鍵值
自己總結(jié)如下:
蹬蹬蹬。。。主角登場:
無線PS2手柄+遙控接收器+便于接線的轉(zhuǎn)接板
PSII.jpg (36.13 KB, 下載次數(shù): 145)
下載附件
2017-11-25 20:49 上傳
遙控接收器和轉(zhuǎn)接板插接在一起后的樣子
IMG_20171125_200939R.jpg (380.25 KB, 下載次數(shù): 141)
下載附件
2017-11-25 20:34 上傳
轉(zhuǎn)接板上的接線引腳有以下幾個:
DAT->手柄到單片機 同步傳送于時鐘下降沿 時序圖中的DI
CMD->單片機到手柄 同步傳送于時鐘下降沿 時序圖中的DO
CS->提供手柄觸發(fā)信號,通訊期間處于低電平
CLK->時鐘信號,由單片機發(fā)出
時序圖.jpg (35.4 KB, 下載次數(shù): 150)
下載附件
2017-11-25 20:51 上傳
引用其他資料的說明如下:
1.“通訊過程中, 一串?dāng)?shù)據(jù)通訊完成后 CS 才會由低轉(zhuǎn)高,不是 1 個字節(jié)通訊完成后就由低轉(zhuǎn)高,在通訊期間,一直處于低電平。”
2.“在時鐘下降沿時,完成數(shù)據(jù)的發(fā)送與接收,發(fā)送和接收是同時完成的。當(dāng)單片機想讀手柄數(shù)據(jù)或向手柄發(fā)送命令時,將會拉低 CS 線電平,并發(fā)出一個命令“0x01”;手 柄會回復(fù)它的 ID “0x41=綠燈模式,0x73=紅燈模式”;在手柄發(fā)送 ID 的同時,單片機將傳送 0x42,請求數(shù)據(jù);隨后手柄發(fā)送出 0x5A,告訴單片機‘數(shù)據(jù)來了’”
3.“一個通訊周期有 9 個字節(jié)(8 位),這些數(shù)據(jù)是依次按位傳送”
以上說白了就是:
按照時序圖,每次通訊周期,都是先給手柄(也就是單片機給接收器)通過CMD引腳(DO)依次發(fā)9組數(shù)據(jù),分別是:
0x01,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00
與此同時,通過DAT引腳(DI)收到相對位的9組數(shù)據(jù),程序中我將收到的數(shù)據(jù)存在了re_code[ ]這個數(shù)組中;
手柄上的按鍵碼值被存儲的位置如下:
re_code[3]==0xEF //左4個按鍵的 上
re_code[3]==0xBF //左4個按鍵的 下
re_code[3]==0x7F //左4個按鍵的 左
re_code[3]==0xDF //左4個按鍵的 右
re_code[3]==0xFE //SELECT鍵
re_code[3]==0xF7 //START鍵
re_code[4]==0xEF //右4個按鍵的 △
re_code[4]==0xBF //右4個按鍵的 ×
re_code[4]==0x7F //右4個按鍵的 □
re_code[4]==0xDF //右4個按鍵的 ○
re_code[4]==0xFB //左1,2個按鍵的 L1
re_code[4]==0xFE //左1,2個按鍵的 L2
re_code[4]==0xF7 //右1,2個按鍵的 R1
re_code[4]==0xFD //右1,2個按鍵的 R2
沒有按鍵按下時,以上各位數(shù)組中的值為FF,按鍵按下數(shù)組值變化,并且支持按鍵組合鍵值輸出。
當(dāng)手柄MODE LED燈不亮?xí)r,左右搖桿功能等同左四右四按鍵
當(dāng)按下MODE鍵手柄MODE LED紅燈亮起
IMG_20171125_200634R.jpg (396.25 KB, 下載次數(shù): 144)
下載附件
2017-11-25 20:34 上傳
這個時候,左右兩個搖桿就能線性輸出了,有點像汽車油門有個逐漸變化量
左右搖桿處于中位時的左右值為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位對應(yīng)的分別是
左搖桿的左右值(re_code[7] 里的值)
左搖桿的上下值(re_code[8] 里的值)
左4個按鍵的鍵值(re_code[3] 里的值)
右4個按鍵及側(cè)面LR的鍵值(re_code[4] 里的值)
正常模式時,如圖左側(cè)的小紅燈(MODE LED)不亮,頭四位數(shù)碼管不會變化只顯示FFFF
IMG_20171125_202059R.jpg (322.1 KB, 下載次數(shù): 180)
下載附件
2017-11-25 20:34 上傳
按下←鍵的顯示
IMG_20171125_202113R.jpg (380.35 KB, 下載次數(shù): 150)
下載附件
2017-11-25 20:34 上傳
按下右側(cè) “×” 鍵的鍵值顯示
IMG_20171125_202142R.jpg (359 KB, 下載次數(shù): 151)
下載附件
2017-11-25 20:34 上傳
按下【MODE】按鈕,小紅燈亮起,搖桿處于中間位置時的數(shù)碼管顯示
807F就顯示了左側(cè)搖桿位于中位的左右值和上下值
IMG_20171125_202046R.jpg (308.06 KB, 下載次數(shù): 163)
下載附件
2017-11-25 20:34 上傳
左搖桿被搖動時的線性值顯示
IMG_20171125_202157R.jpg (359.14 KB, 下載次數(shù): 148)
下載附件
2017-11-25 20:34 上傳
IMG_20171125_202206R.jpg (360.53 KB, 下載次數(shù): 156)
下載附件
2017-11-25 20:34 上傳
程序中柄遙控接收器接口定義:
// DAT-> in PD0 設(shè)置為輸入
// CMD-> out PD1 設(shè)置為輸出
// CS-> out PD2
// CLK-> out PD3
這個PS2手柄還有震動功能,本次沒有弄出來,還請哪位大蝦指點一二。
為了不浪費大家的黑幣(我的黑幣就總不夠用 ),我就直接將程序貼出來了,如下,不對的地方還請指正——————————————————————————————————————————————————————
#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); //這里延時很關(guān)鍵,太多了手柄就反應(yīng)遲鈍了
if(PIND&0x01) res=res+j; //這里就開始同步接收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);
}
}
下面圖片中那個紅色的atmega128小板就是前些日子被我熔絲位寫錯導(dǎo)致昏迷后又救回來的那位。。。
|
評分
-
查看全部評分
|