ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-05-15 17:31:26  阅读:222  来源: 互联网

标签:GCC 手柄 PSB 合泰 Cmd DELAY PS2 void


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--);
}

标签:GCC,手柄,PSB,合泰,Cmd,DELAY,PS2,void
来源: https://blog.csdn.net/weixin_39899831/article/details/116853086

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有