索尼的 PS2游戏手柄, 通过上下左右4个按键来控制 单片机的4个灯亮灭。 同时 也可以控制 游戏手柄的震动
串口打印
源程序如下:
- # include "public.h"
- # include "printf.h"
- # include "systick.h"
- # include "ps2.h"
- # include "led.h"
- int main()
- {
- u8 key;
- LED_Init();
- printf_init(); //printf串口初始化
- PS2_Init();
- led_display();
- //PS2_SetInit(); //配配置初始化,配置“红绿灯模式”,并选择是否可以修改
- //开启震动模式
- printf(" 已开启游戏手柄\r\n");
- /*
- while(1)
- {
- key=PS2_DataKey();
- if(key!=0) //有按键按下
- {
- printf(" \r\n %d is light \r\n",Data[1]);//ID
- printf(" \r\n %d is pressed \r\n",key);
- if(key == 11)
- {
- PS2_Vibration(0xFF,0x00); //发出震动后必须有延时 delay_ms(1000);
- delay_ms(500);
- }
- else if(key == 12)
- {
- PS2_Vibration(0x00,0xFF); //发出震动后必须有延时 delay_ms(1000);
- delay_ms(500);
- }
- else
- PS2_Vibration(0x00,0x00);
- }
- printf(" %5d %5d %5d %5d\r\n",PS2_AnologData(PSS_LX),PS2_AnologData(PSS_LY),
- PS2_AnologData(PSS_RX),PS2_AnologData(PSS_RY) );
- delay_ms(60000);
- }
- */
- while (1)
- {
- key=PS2_DataKey();
- if(key!=0) //有按键按下
- {
- printf(" \r\n %d is light \r\n",Data[1]);//ID
- printf(" \r\n %d is pressed \r\n",key);
- if(key == 5)
- {
- printf(" 按键向上 !\r\n");
- led1();
- }
- else if(key == 7)
- {
- printf(" 按键向下 !\r\n");
- led2();
- }
- else if(key == 6)
- {
- printf(" 按键向右 !\r\n");
- led3();
- }
- else if(key == 8)
- {
- printf(" 按键向左 !\r\n");
- led4();
- }
- printf(" 输入成功!\r\n");
- }
- delay_us(60000);
- }
-
- }
复制代码- #include "ps2.h"
- #include "systick.h"
- 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->PB12
- // 输出 DO->PB13 CS->PB14 CLK->PB15
- void PS2_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能GPIOF时钟
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//普通输出模式
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
-
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//普通输出模式
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
- }
- //向手柄发送命令
- void PS2_Cmd(u8 CMD)
- {
- volatile u16 ref=0x01;
- Data[1] = 0;
- for(ref=0x01;ref<0x0100;ref<<=1)
- {
- if(ref&CMD)
- {
- DO_H; //输出一位控制位
- }
- else DO_L;
- CLK_H; //时钟拉高
- delay_us(10);
- CLK_L;
- delay_us(10);
- CLK_H;
- if(DI)
- Data[1] = ref|Data[1];
- }
- delay_us(16);
- }
- //判断是否为红灯模式,0x41=模拟绿灯,0x73=模拟红灯
- //返回值;0,红灯模式
- // 其他,其他模式
- u8 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 u8 byte=0;
- volatile u16 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;
- delay_us(10);
- CLK_L;
- delay_us(10);
- CLK_H;
- if(DI)
- Data[byte] = ref|Data[byte];
- }
- delay_us(16);
- }
- CS_H;
- }
- //对读出来的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)
- {
- CS_L;
- 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);
- CS_H;
- delay_us(16);
- }
- //short poll
- void PS2_ShortPoll(void)
- {
- CS_L;
- delay_us(16);
- PS2_Cmd(0x01);
- PS2_Cmd(0x42);
- PS2_Cmd(0X00);
- PS2_Cmd(0x00);
- PS2_Cmd(0x00);
- CS_H;
- delay_us(16);
- }
- //进入配置
- void PS2_EnterConfing(void)
- {
- CS_L;
- 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);
- CS_H;
- delay_us(16);
- }
- //发送模式设置
- void PS2_TurnOnAnalogMode(void)
- {
- CS_L;
- 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);
- CS_H;
- delay_us(16);
- }
- //振动设置
- void PS2_VibrationMode(void)
- {
- CS_L;
- delay_us(16);
- PS2_Cmd(0x01);
- PS2_Cmd(0x4D);
- PS2_Cmd(0X00);
- PS2_Cmd(0x00);
- PS2_Cmd(0X01);
- CS_H;
- delay_us(16);
- }
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
全部资料51hei下载地址:
PS2 震动+上下左右按键.rar
(910.7 KB, 下载次数: 68)
|