PS2手柄代码移植-合泰平台

PS2手柄代码移植-合泰平台

1、PS2手柄端口及通讯协议

PS2手柄的通讯协议是SPI协议是一种高速的、全双工、同步的通信总线,并且在芯片的管脚上只占用四根线(DI、DO、CS、CLK),PS2手柄的通讯协议破解后在C51、STM32、Arduino、FPGA等平台上均有应用,其端口、通讯协议及使用方法的介绍在网上一搜一大堆,大家自行下载即可。

博主本科期间由于项目需求,需要在合泰芯片上实现ps2手柄控制的代码。于是将ps2的代码从别的平台上移植到合泰芯片平台上,具体型号为合泰HT66F70A(好像是开发板型号,不一定是芯片型号),如今整理出来,希望能帮助到有需要的朋友。

PS2手柄代码移植-合泰平台

2、移植代码:文件主要包括三份:ps2.c、ps2.h、main.c

  • ps2.c

#include "PS2.h"
#include "HT66F70A.h"

//全局变量区
unsigned short int Handkey;
unsigned char Comd[2] = {0x01,0x42};//开始命令。请求数据
unsigned char Data[9] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //数据存储数组
unsigned short int 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->PB12 
//                  输出  DO->PB13    CS->PB14  CLK->PB15    
void PS2_INIT(void)
{
	//输入 DI->PB2
	_pcc4 = 1;//PB12设置成输入	默认下拉 
	_pcpu4 = 0;
	//DO->PB3 CS->PB4 CLK->PB5
	_pcc5 = 0;//PB3、PB4、PB5 推挽输出
	_pcc6 = 0;
	_pcc7 = 0;
	_pcpu5 = 0;
	_pcpu6 = 0;
	_pcpu7 = 0;
}
	
void PS2_Cmd(unsigned char CMD)
{
	volatile unsigned short int ref = 0x01;
	Data[1] = 0;
	for(ref=0x01;ref<0x0100;ref<<=1)
	{
		if(ref&CMD)
		{
			DO_H;                   //输出以为控制位
		}
		else DO_L;

		CLK_H;                        //时钟拉高
		GCC_DELAY(5);//delay_us(50);
		CLK_L;
		GCC_DELAY(5);//delay_us(50);
		CLK_H;
		if(DI)
			Data[1] = ref|Data[1];
	}
	GCC_DELAY(16);
}	

//判断是否为红灯模式
//返回值;0,红灯模式
//		  其他,其他模式
unsigned char PS2_RedLight(void)
{
	CS_L;
	PS2_Cmd(Comd[0]);  //开始命令
	PS2_Cmd(Comd[1]);  //请求数据
	CS_H;
	if( Data[1] == 0X73)   return 0 ;
	else return 1;
}

//读取手柄数据
void PS2_ReadData(void)
{
	volatile unsigned char byte=0;
	volatile unsigned short int ref=0x01;

	CS_L;

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

	for(byte=2;byte<9;byte++)          //开始接受数据
	{
		for(ref=0x01;ref<0x100;ref<<=1)
		{
			CLK_H;
			GCC_DELAY(5);
			CLK_L;
			GCC_DELAY(5);//delay_us(50);
			CLK_H;
		      if(DI)
		      Data[byte] = ref|Data[byte];
		}
        GCC_DELAY(16);//delay_us(16);
	}
	CS_H;	

}

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

	PS2_ClearData();
	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
unsigned char PS2_AnologData(unsigned char button)
{
	return Data[button];
}

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

//short poll
void PS2_ShortPoll(void)
{
	CS_L;
	GCC_DELAY(16);//delay_us(16);
	PS2_Cmd(0x01);
	PS2_Cmd(0x42);
	PS2_Cmd(0x00);
	PS2_Cmd(0x00);
	PS2_Cmd(0x00);
	CS_H;
	GCC_DELAY(16);
}

//进入配置
void PS2_EnterConfig(void)
{
	CS_L;
	GCC_DELAY(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);
	CS_H;
	GCC_DELAY(16);
}

//发送模式设置
void PS2_TurnOnAnalogMode(void)
{
	CS_L;
	//GCC_DELAY(16);
	PS2_Cmd(0x01);
	PS2_Cmd(0x44);
	PS2_Cmd(0x00);
	PS2_Cmd(0x01);//analog=0x01;digital=0x00  软件设置发送模式
	PS2_Cmd(0xEE);//0x03锁存设置,即不可通过按键"MODE"设置模式
	              //0xEE不锁存软件设置,可通过按键"MODE"设置模式
	PS2_Cmd(0x00);
	PS2_Cmd(0x00);
	PS2_Cmd(0x00);
	PS2_Cmd(0x00);
	CS_H;
	GCC_DELAY(16);	              
}

//震动设置
void PS2_VibrationMode(void)
{
	CS_L;
	GCC_DELAY(16);
	PS2_Cmd(0x01);
	PS2_Cmd(0x4D);
	PS2_Cmd(0x00);
	PS2_Cmd(0x00);
	PS2_Cmd(0x01);
    CS_H;
    GCC_DELAY(16);
}

//完成并保存配置
void PS2_ExitConfig(void)
{
	CS_L;
	GCC_DELAY(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);
	CS_H;
	GCC_DELAY(16);
}

//手柄配置初始化
void PS2_SetInit(void)
{
	PS2_ShortPoll();
	PS2_ShortPoll();
	PS2_ShortPoll();
	PS2_EnterConfig();//进入配置模式
	PS2_TurnOnAnalogMode();//"红绿灯"配置模式,并选择是否保存
	PS2_VibrationMode();//开启震动模式
	PS2_ExitConfig();//完成并保存配置
}

//只有PS2_VibrationMode();开启之后可用
//motor1:右侧小振动电机 0x00关,其他开
//motor2:左侧大震动电机 0x40~0xFF 电机开,值越大,震动越大
void PS2_Vibration(unsigned char motor1,unsigned char motor2)
{
	CS_L;
	GCC_DELAY(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);
	CS_H;
	GCC_DELAY(16);
}
  • ps2.h

#ifndef _PS2_H_
#define _PS2_H_

#define DI   _pc4           //PB2  输入
#define DO_H  _pc5=1        //命令位高
#define DO_L  _pc5=0        //命令位低
#define CS_H  _pc6=1        //CS拉高
#define CS_L  _pc6=0        //CS拉低
#define CLK_H  _pc7=1       //时钟拉高
#define CLK_L  _pc7=0       //时钟拉低

//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 unsigned char Data[9];
extern unsigned short int MASK[16];
extern unsigned short int Handkey;

void PS2_INIT(void);//PS2初始化
unsigned char PS2_RedLight(void);//判断是否为红灯模式
void PS2_ReadData(void);//
void PS2_Cmd(unsigned char CMD);//
unsigned char PS2_DataKey(void);//键值读取
unsigned char PS2_AnologData(unsigned char button); //得到一个摇杆的模拟量
void PS2_ClearData(void);//清除数据缓冲区
void PS2_ShortPoll(void);//short poll
void PS2_EnterConfig(void);//进入配置
void PS2_TurnOnAnalogMode(void);//发送模式设置
void PS2_VibrationMode(void);//震动设置
void PS2_ExitConfig(void);//完成并保存配置
void PS2_SetInit(void);//手柄配置初始化
void PS2_Vibration(unsigned char motor1,unsigned char motor2);//

#endif
  • main.c

#include "HT66F70A.h"
#include "Interrupt.h"
#include "TM.h"
#include "UART.h"
#include "PS2.h"
#include "Motor.h"

//全局变量区
extern char buff[num];
extern char Buff[32];
extern unsigned int count;

//函数声明区
void delay1s(void);

//主程序入口
void main()
{
	//初始化区
    _wdtc = 0xab;//看门狗失能
    unsigned char key;
    UART_INIT();
    PS2_INIT();
    MOTOR_INIT();

    //TO DO  
    while(1)
    {
        key = PS2_DataKey(); 
        GCC_DELAY(16);	
    	switch(key)
    	{
    		case  1:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  1) Send( "1\r\n");  break;
    		case  2:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  2) Send( "2\r\n");break;
    		case  3:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  3) Send( "3\r\n");break;
    		case  4:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  4) Send( "4\r\n");break;
    		case  5:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  5) Send( "5\r\n");Motor(1,1,300);break;
    		case  6:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  6) Send( "6\r\n");Motor(1,1,300);break;
    		case  7:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  7) Send( "7\r\n");Motor(1,1,1000);break;
    		case  8:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  8) Send( "8\r\n");Motor(1,0,1000);break;
    		case  9:GCC_DELAY(2000); if((key = PS2_DataKey()) ==  9) Send( "9\r\n");break;
    		case 10:GCC_DELAY(2000); if((key = PS2_DataKey()) == 10) Send("10\r\n");break;
    		case 11:GCC_DELAY(2000); if((key = PS2_DataKey()) == 11) Send("11\r\n");break;
    		case 12:GCC_DELAY(2000); if((key = PS2_DataKey()) == 12) Send("12\r\n");break;
    		case 13:GCC_DELAY(2000); if((key = PS2_DataKey()) == 13) Send("13\r\n");break;
    		case 14:GCC_DELAY(2000); if((key = PS2_DataKey()) == 14) Send("14\r\n");break;
    		case 15:GCC_DELAY(2000); if((key = PS2_DataKey()) == 15) Send("15\r\n");break;
    		case 16:GCC_DELAY(2000); if((key = PS2_DataKey()) == 16) Send("16\r\n");Motor_Stop(1);break;
    		default:break;
    	}
    }	
    	   
}

void delay1s(void)   //误差 -1us
{
    unsigned char a,b,c,n;
    for(c=205;c>0;c--)
        for(b=171;b>0;b--)
            for(a=8;a>0;a--);
    for(n=1;n>0;n--);
}
上一篇:实验十卫星网络系统仿真实验


下一篇:mysql5.6以上主从延迟设置