PS2无线手柄怎么玩NES

2019-08-20 15:39发布

成功移植NES到STM32F103VET6,用PS2无线手柄玩NES游戏遇到点问题,无线手柄和有线手柄的读写时序不一样,不能直接使用有线PS2手柄的驱动。
下面的源码是PS2无线手柄的驱动代码,怎么用这个代码去替换原有的有线手柄驱动。

#ifndef __PSTWO_H
#define __PSTWO_H
#include "delay.h"
#include "sys.h"
/*********************************************************
Copyright (C), 2015-2025, YFRobot.
www.yfrobot.com
File:PS2驱动程序
Author:pinggai    Version:1.0     Data:2015/05/16
Description: PS2驱动程序
**********************************************************/     
#define PS2_JOYPAD_DATA   PCin(0)           //PB12  输入
#define PS2_JOYPAD_CMND PCout(1)       //命令位高
#define PS2_JOYPAD_ATT PCout(3)       //CS拉高
#define PS2_JOYPAD_CLOCK PCout(2)      //时钟拉高


//These are our button constants
#define PSB_SELECT      1
#define PSB_L3          2
#define PSB_R3          3
#define PSB_START       4
#define PSB_PAD_UP      5
#define PSB_PAD_RIGHT   6
#define PSB_PAD_DOWN    7
#define PSB_PAD_LEFT    8
#define PSB_L2          9
#define PSB_R2          10
#define PSB_L1          11
#define PSB_R1          12
#define PSB_GREEN       13
#define PSB_RED         14
#define PSB_BLUE        15
#define PSB_PINK        16

#define PSB_TRIANGLE    13
#define PSB_CIRCLE      14
#define PSB_CROSS       15
#define PSB_SQUARE      16

//#define WHAMMY_BAR        8

//These are stick values
#define PSS_RX 5                //右摇杆X轴数据
#define PSS_RY 6
#define PSS_LX 7
#define PSS_LY 8

extern u8 Data[9];
extern u16 MASK[16];
extern u16 Handkey;

void PS2_Init(void);
u8 PS2_RedLight(void);   //判断是否为红灯模式
void PS2_ReadData(void); //读手柄数据
void PS2_Cmd(u8 CMD);          //向手柄发送命令
u8 PS2_DataKey(void);          //按键值读取
u8 PS2_AnologData(u8 button); //得到一个摇杆的模拟量
void PS2_ClearData(void);      //清除数据缓冲区
void PS2_Vibration(u8 motor1, u8 motor2);//振动设置motor1  0xFF开,其他关,motor2  0x40~0xFF

void PS2_EnterConfing(void);     //进入配置
void PS2_TurnOnAnalogMode(void); //发送模拟量
void PS2_VibrationMode(void);    //振动设置
void PS2_ExitConfing(void);         //完成配置
void PS2_SetInit(void);             //配置初始化

#endif


#include "pstwo.h"
#include "usart.h"
/*********************************************************
Copyright (C), 2015-2025, YFRobot.
www.yfrobot.com
File:PS2驱动程序
Author:pinggai    Version:1.0     Data:2015/05/16
Description: PS2驱动程序
**********************************************************/     

u16 Handkey;
u8 Comd[2]={0x01,0x42};    //开始命令。请求数据
u8 Data[9]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //数据存储数组

u16 MASK[]={
    PSB_SELECT,
    PSB_L3,
    PSB_R3 ,
    PSB_START,
    PSB_PAD_UP,
    PSB_PAD_RIGHT,
    PSB_PAD_DOWN,
    PSB_PAD_LEFT,
    PSB_L2,
    PSB_R2,
    PSB_L1,
    PSB_R1 ,
    PSB_GREEN,
    PSB_RED,
    PSB_BLUE,
    PSB_PINK
    };    //按键值与按键明

//手柄接口初始化    输入  DI->PC0
//                  输出  DO->PC1    CS->PC3  CLK->PC2
void PS2_Init(void)
{
  RCC->APB2ENR|=1<<4;//先使能外设PORTC时钟        
    GPIOC->CRL&=0XFFF00000;
    GPIOC->CRL|=0X00083338;     
    GPIOC->ODR|=0x1f<<0;                                                
}

//向手柄发送命令
void PS2_Cmd(u8 CMD)
{
    volatile u16 ref=0x01;
    Data[1] = 0;
    for(ref=0x01;ref<0x0100;ref<<=1)
    {
        if(ref&CMD)
        {
            PS2_JOYPAD_CMND = 1;                   //输出以为控制位
        }
        else PS2_JOYPAD_CMND = 0;

        PS2_JOYPAD_CLOCK = 1;                        //时钟拉高
        delay_us(5);
        PS2_JOYPAD_CLOCK = 0;
        delay_us(5);
        PS2_JOYPAD_CLOCK = 1;
        if(PS2_JOYPAD_DATA)
            Data[1] = ref|Data[1];
    }
    delay_us(16);
}
//判断是否为红灯模式
//返回值;0,红灯模式
//          其他,其他模式
u8 PS2_RedLight(void)
{
    PS2_JOYPAD_ATT = 0;
    PS2_Cmd(Comd[0]);  //开始命令
    PS2_Cmd(Comd[1]);  //请求数据
    PS2_JOYPAD_ATT = 1;
    if( Data[1] == 0X73)   return 0 ;
    else return 1;

}
//读取手柄数据
void PS2_ReadData(void)
{
    volatile u8 byte=0;
    volatile u16 ref=0x01;

    PS2_JOYPAD_ATT = 0;

    PS2_Cmd(Comd[0]);  //开始命令
    PS2_Cmd(Comd[1]);  //请求数据

    for(byte=2;byte<9;byte++)          //开始接受数据
    {
        for(ref=0x01;ref<0x100;ref<<=1)
        {
            PS2_JOYPAD_CLOCK = 1;
            delay_us(5);
            PS2_JOYPAD_CLOCK = 0;
            delay_us(5);
            PS2_JOYPAD_CLOCK = 1;
              if(PS2_JOYPAD_DATA)
              Data[byte] = ref|Data[byte];
        }
        delay_us(16);
    }
    PS2_JOYPAD_ATT = 1;   
}

//对读出来的PS2的数据进行处理      只处理了按键部分         默认数据是红灯模式  只有一个按键按下时
//按下为0, 未按下为1
u8 PS2_DataKey()
{
    u8 index;

    PS2_ClearData();
    PS2_ReadData();

    Handkey=(Data[4]<<8)|Data[3];     //这是16个按键  按下为0, 未按下为1
    for(index=0;index<16;index++)
    {        
        if((Handkey&(1<<(MASK[index]-1)))==0)
        return index+1;
    }
    return 0;          //没有任何按键按下
}

//得到一个摇杆的模拟量     范围0~256
u8 PS2_AnologData(u8 button)
{
    return Data[button];
}

//清除数据缓冲区
void PS2_ClearData()
{
    u8 a;
    for(a=0;a<9;a++)
        Data[a]=0x00;
}


/******************************************************
Function:    void PS2_Vibration(u8 motor1, u8 motor2)
Description: 手柄震动函数,
Calls:         void PS2_Cmd(u8 CMD);
Input: motor1:右侧小震动电机 0x00关,其他开
       motor2:左侧大震动电机 0x40~0xFF 电机开,值越大 震动越大
******************************************************/
void PS2_Vibration(u8 motor1, u8 motor2)
{
    PS2_JOYPAD_ATT = 0;
    delay_us(16);
  PS2_Cmd(0x01);  //开始命令
    PS2_Cmd(0x42);  //请求数据
    PS2_Cmd(0X00);
    PS2_Cmd(motor1);
    PS2_Cmd(motor2);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_JOYPAD_ATT = 1;
    delay_us(16);  
}
//short poll
void PS2_ShortPoll(void)
{
    PS2_JOYPAD_ATT = 0;
    delay_us(16);
    PS2_Cmd(0x01);  
    PS2_Cmd(0x42);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x00);
    PS2_Cmd(0x00);
    PS2_JOYPAD_ATT = 1;
    delay_us(16);   
}
//进入配置
void PS2_EnterConfing(void)
{
  PS2_JOYPAD_ATT = 0;
    delay_us(16);
    PS2_Cmd(0x01);  
    PS2_Cmd(0x43);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x01);
    PS2_Cmd(0x00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_JOYPAD_ATT = 1;
    delay_us(16);
}
//发送模式设置
void PS2_TurnOnAnalogMode(void)
{
    PS2_JOYPAD_ATT = 0;
    PS2_Cmd(0x01);  
    PS2_Cmd(0x44);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x01); //analog=0x01;digital=0x00  软件设置发送模式
    PS2_Cmd(0xEE); //Ox03锁存设置,即不可通过按键“MODE”设置模式。
                   //0xEE不锁存软件设置,可通过按键“MODE”设置模式。
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_JOYPAD_ATT = 1;
    delay_us(16);
}
//振动设置
void PS2_VibrationMode(void)
{
    PS2_JOYPAD_ATT = 0;
    delay_us(16);
    PS2_Cmd(0x01);  
    PS2_Cmd(0x4D);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x00);
    PS2_Cmd(0X01);
    PS2_JOYPAD_ATT = 1;
    delay_us(16);   
}
//完成并保存配置
void PS2_ExitConfing(void)
{
    PS2_JOYPAD_ATT = 0;
    delay_us(16);
    PS2_Cmd(0x01);  
    PS2_Cmd(0x43);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x00);
    PS2_Cmd(0x5A);
    PS2_Cmd(0x5A);
    PS2_Cmd(0x5A);
    PS2_Cmd(0x5A);
    PS2_Cmd(0x5A);
    PS2_JOYPAD_ATT =1;
    delay_us(16);
}
//手柄配置初始化
void PS2_SetInit(void)
{
    PS2_ShortPoll();
    PS2_ShortPoll();
    PS2_ShortPoll();
    PS2_EnterConfing();        //进入配置模式
    PS2_TurnOnAnalogMode();    //“红绿灯”配置模式,并选择是否保存
    PS2_VibrationMode();    //开启震动模式
    PS2_ExitConfing();        //完成并保存配置
}





0条回答

一周热门 更多>