找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 16861|回复: 3
打印 上一主题 下一主题
收起左侧

PS2无线手柄解码 附单片机程序

[复制链接]
跳转到指定楼层
楼主
本帖最后由 ryuby 于 2017-11-26 09:48 编辑

参考前辈大虾的资料,用Atmega128A对PS2无线手柄进行解码,并在8位数码管上显示按键值

自己总结如下:
蹬蹬蹬。。。主角登场:
无线PS2手柄+遥控接收器+便于接线的转接板



遥控接收器和转接板插接在一起后的样子

转接板上的接线引脚有以下几个:
DAT->手柄到单片机 同步传送于时钟下降沿 时序图中的DI
CMD->单片机到手柄  同步传送于时钟下降沿 时序图中的DO      
CS->提供手柄触发信号,通讯期间处于低电平
CLK->时钟信号,由单片机发出




引用其他资料的说明如下:
1.“通讯过程中, 一串数据通讯完成后 CS 才会由低转高,不是 1 个字节通讯完成后就由低转高,在通讯期间,一直处于低电平。
2.“在时钟下降沿时,完成数据的发送与接收,发送和接收是同时完成的。当单片机想读手柄数据或向手柄发送命令时,将会拉低 CS 线电平,并发出一个命令“0x01”;柄会回复它的 ID 0x41=绿灯模式,0x73=灯模式”;在手柄发送 ID 的同时,单片机将传送 0x42,请求数据;随后手柄发送出 0x5A,告诉单片机‘数据
3.“一个通讯周期有 9 个字节(8 位),这些数据是依次按位传送


  以上说白了就是:
  按照时序图,每次通讯周期,都是先给手柄(也就是单片机给接收器)通过CMD引脚(DO)依次发9组数据,分别是:
  0x01,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00

  与此同时,通过DAT引脚(DI)收到相对位的9组数据,程序中我将收到的数据存在了re_code[ ]这个数组中;
  手柄上的按键码值被存储的位置如下:
  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

没有按键按下时,以上各位数组中的值为FF,按键按下数组值变化,并且支持按键组合键值输出。

当手柄MODE LED灯不亮时,左右摇杆功能等同左四右四按键

当按下MODE键手柄MODE LED红灯亮起


这个时候,左右两个摇杆就能线性输出了,有点像汽车油门有个逐渐变化量
左右摇杆处于中位时的左右值为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 左摇杆从上到下

--------------------------------------------------------------------------------------------------
数码管从左至右每2位对应的分别是
左摇杆的左右值(re_code[7] 里的值)

左摇杆的上下值(re_code[8] 里的值)
左4个按键的键值(re_code[3] 里的值)

右4个按键及侧面LR的键值(re_code[4] 里的值)
正常模式时,如图左侧的小红灯(MODE LED)不亮,头四位数码管不会变化只显示FFFF




按下←键的显示



按下右侧 “×” 键的键值显示



按下【MODE】按钮,小红灯亮起,摇杆处于中间位置时的数码管显示
807F就显示了左侧摇杆位于中位的左右值和上下值



左摇杆被摇动时的线性值显示






程序中柄遥控接收器接口定义:
// DAT->  in  PD0     设置为输入
// CMD-> out PD1   设置为输出        
// 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数据
uchar scan[9]={0x01,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  //存放DI数据
uchar re_code[9];                                             
uint m;

//共阴数码管段码
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)   //向手柄发送命令并接受反馈的子程序
{
    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);                              //这里延时很关键,太多了手柄就反应迟钝了
          if(PIND&0x01) res=res+j;      //这里就开始同步接收DI值了
          j=j<<1;
          clk_set;
          delay(2);                 
    }
    return res;        
}
void Read_PS2(void)        //向手柄发送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小板就是前些日子被我熔丝位写错导致昏迷后又救回来的那位。。。

IMG_20171125_200654R.jpg (379.25 KB, 下载次数: 203)

IMG_20171125_200654R.jpg

IMG_20171125_201018R.jpg (388.8 KB, 下载次数: 194)

IMG_20171125_201018R.jpg

IMG_20171125_202201R.jpg (358.76 KB, 下载次数: 190)

IMG_20171125_202201R.jpg

IMG_20171125_202209R.jpg (366.88 KB, 下载次数: 203)

IMG_20171125_202209R.jpg

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:380304 发表于 2018-7-28 20:29 | 只看该作者
谢谢分享
回复

使用道具 举报

板凳
ID:333428 发表于 2018-7-30 14:38 | 只看该作者
楼主51 能连接这个手柄吗

回复

使用道具 举报

地板
ID:28260 发表于 2021-6-30 10:22 | 只看该作者
拜读了,谢谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表