PS2游戏手柄——基于STC15W4K32S4

PS2游戏手柄

1 PS2介绍

在这里插入图片描述
PS2手柄是日本SONY公司的PlayStation2 游戏机的遥控手柄。索尼的 PSX系列游戏主机在全球都很畅销。不知什么时候便有人打起 PS2手柄的主意,破解了通讯协议,使得手柄可以接在其他器件上遥控使用,比如遥控我们熟悉的机器人。突出的特点是这款手柄性价比极高,按键丰富,方便扩展到其它应用中。

2 PS2通讯协议介绍

PS2采用的是SPI通信协议,SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线(DI、DO、CS、CLK),节约了芯片的管脚,同时为PCB的布局上节省空间。
在这里插入图片描述
在这里插入图片描述
PS2接收器上一共有九根引脚,按上图从左往右,依次为:

1.DI/DAT:信号流向,从手柄到主机,此信号是一个8bit 的串行数据,同步传送于时钟的下降沿。信号的读取在时钟由高到低的变化过程中完成。

2.DO/CMD:信号流向,从主机到手柄,此信号和 DI相对,信号是一个 8bit 的串行数据, 同步传送于时钟的下降沿。

3.NC:空端口。

4.GND:电源地。

5.VCC:接收器工作电源,电源范围 3~5V。

6.CS/SEL:用于提供手柄触发信号。在通讯期间,处于低电平。

7.CLK:时钟信号,由主机发出,用于保持数据同步。

8.NC:空端口。

9.ACK:从手柄到主机的应答信号。此信号在每个8bits数据发送的最后一个周期变低并且CS一直保持低电平,如果CS信号不变低,约60微秒PS主机会试另一个外设。在编程时未使用ACK端口。(可以忽略)
在这里插入图片描述
时钟频率 250KHz(4us),如果接收数据不稳定,可以适当的增加频率。 在通讯过中,
一串数据通讯完成后 CS 才会由低转高,不是 1 个字节通讯完成后就由低转高,在通讯期
间,一直处于低电平。

在时钟下降沿时,完成数据(lbit)的发送与接收,发送和接收是同时完成的。当单片
机想读手柄数据或向手柄发送命令时,将会拉低 CS 线电平,并发出一个命令“0x01”;手
柄会回复它的 ID “0x41=绿灯模式,0x73=红灯模式”;在手柄发送 ID 的同时,单片机将
传 送 0x42,请求数据;随后手柄发送出 0x5A,告诉单片机“数据来了”。
idle:数据线空闲,该数据线无数据传送。

一个通讯周期有 9 个字节(8 位),这些数据是依次按位传送。

注意的是:

  1. CS线在通讯期间拉低,通信过程中CS信号线在一串数据(9个字节,每个字节为8位)发送完毕后才会拉高,而不是每个字节发送完拉高。

  2. DO、DI在在CLK时钟的下降沿完成数据的发送和读取。
    下降沿:数字电平从高电平(数字“1”)变为低电平(数字“0”)的那一瞬间叫作下降沿。

  3. CLK的每个周期为12us。若在某个时刻,CLK处于下降沿,若此时DO为高电平则取“1”,低电平则取“0”。连续读8次则得到一个字节byte的数据,连续读9个字节就能得到一次传输周期所需要的数据。DI也是一样的,发送和传输同时进行。

具体的通讯过程如下:
在这里插入图片描述
以STC15为例:

1、首先STC15拉低CS片选信号线,然后在每个CLK的下降沿读一个bit,每读八个bit(即一个byte)CLK拉高一小段时间,一共读九组bit。

2、第一个byte是STC15发给接收器命令“0X01” 。

3、PS2手柄会在第二个byte回复它的ID(0x41=绿灯模式,0x73=红灯模式),同时第二个byte时STC15发给PS2一个0x42请求数据。

红灯模式时:左右摇杆发送模拟值,0x00~0xFF 之间,且摇杆按下的 键值 L3 、 R3 有效;
绿灯模式时:左右摇杆模拟值为无效,推到极限时,对应发送 UP、RIGHT、DOWN、 LEFT、△、○、╳、□,按键 L3 、 R3 无效。

4、第三个byte PS2 会给主机发送 “0x5A” 告诉STC15数据来了。

5、从第四个byte开始全是接收器给主机发送数据,每个byte定义如上图,当有按键按下,对应位为“0 ”,例如当键“SELECT”被按下时, Data[3]=11111110。

对于整个通讯过程,你理解成下面的一段对话:


拉低CS,表示开始数据通信


byte 0 :
STC15(DO) : 0x01 ------------------------- [现在开始通信]
PS2手柄(DI) : 空 ---------------------------- [空]


byte 1 :
STC15(DO) : 0x42 -------------------------- [请求发送数据]
PS2手柄(DI) : 红灯0x73
            绿灯0X41---------------------[现在的ID]


byte 2:
STC15(DO) : 空 ------------------------------ [空]
PS2手柄(DI) : 0X5A ------------------------- [数据来了]


byte 3:
STC15(DO) : 0X00~0XFF ------------------ [右侧小震动电机是否开启]
PS2手柄(DI) : 00000000~11111111 ------- [SELECT、 L3 、 R3、 START 、 UP、 RIGHT、 DOWN、 LEFT 是否被按下,若被按下对应位为0]


byte 4:
STC15(DO) : 0X00~0XFF ------------------ [左侧大震动电机振动幅度]
PS2手柄(DI) : 00000000~11111111 ------- [L2 、 R2、L1 、R1、△、○、╳、□ 是否被按下,若被按下对应位为0]


byte 5:
STC15(DO) : 空 -------------------------------- [空]
PS2手柄(DI) : 0X00~0XFF ------------------ [左侧X轴摇杆模拟量]


byte 6:
STC15(DO) : 空 -------------------------------- [空]
PS2手柄(DI) : 0X00~0XFF ------------------ [左侧Y轴摇杆模拟量]


byte 7:
STC15(DO) : 空 -------------------------------- [空]
PS2手柄(DI) : 0X00~0XFF ------------------ [右侧X轴摇杆模拟量]


byte 8:
STC15(DO) : 空 -------------------------------- [空]
PS2手柄(DI) : 0X00~0XFF ------------------ [右侧Y轴摇杆模拟量]

注意:模拟量只对红灯模式下有效,绿灯模式下摇杆推至极限分别对应 UP、RIGHT、DOWN、 LEFT、△、○、╳、□ 。L3、R3只对红灯模式下有效,在绿灯模式下无效。
在这里插入图片描述
在手柄通信前还需要一系列的初始化(是否启动振动电机、是否进行锁存等),详情可以参考下面代码。当然,不进行初始化也是可以的,手柄会默认之前的配置。
——————————————————————————————

3 代码

主机收到的数据在out[]数组中,在其他文件用到PS2时,只要对out[]数组进行处理和分析即可。

h文件
#ifndef __PS2_H__
#define __PS2_H__
#include "STC15Fxxxx.h"


#define Up_L 0xEF
#define Down_L 0xBF
#define Left_L 0x7F
#define Right_L 0xDF

#define Up_R 0xEF
#define Down_R 0xBF
#define Left_R 0x7F
#define Right_R 0xDF

#define L1 0xFB
#define L2 0xFE
#define L3 0xFD
#define R1 0xF7
#define R2 0xFD
#define R3 0xFB


#define UP_L 0x7F
  • 4
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值