基于PS2索尼游戏手柄开发
最近师妹拿了个PS2手柄给我

安排!!!!
代码下载链接

在32上面 成功用PS2 控制显示屏输出
PS2是一个很好学习通讯时序的的工具
这里写下他的实现代码和我的学习思路
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|
DI/DAT | DO/CMD | NC | VDD | GND | CS/SEL | CLK | NC | ACK |
我们不使用 NC NC ACK 这三个端口
NC:空端口;
ACK:从手柄到主机的应答信号。
此信号在每个 8bits 数据发送的最后一个周期变低
并且 CS 一直保持低电平,如
果CS 信号不变低,
约 60 微秒 PS 主机会试另一个外设。
在编程时未使用 ACK 端口。
我们接线如下
DI PB12 浮空输入 输入 数据
DO PB13 推挽输出 输出 数据
CS PB14 推挽输出 输出 数据
CLK PB15 推挽输出 输出 数据
首先是PS2 初始化 我们将IO配置成对应的模式
void PS2_Init(void) //PB12 ÊäÈëÏÂÀ ÆäËûµÄÍÆÍìÊä³ö
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPD;
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_12;
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode= GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
}
然后 我们宏定义了一堆指令 为了简化我们后续的代码
这里用到了正点原子给的 sys.h 的32库
`#define DI PBin(12) //PB12 (DI 数据输入位)输入
#define DO_H PBout(13)=1 //令PB13 (DO 命令位/数据输出位) 输出高电平
#define DO_L PBout(13)=0 //令PB13 (DO 命令位/数据输出位)输出低电平
#define CS_H PBout(14)=1 //令PB14 (CS 使能位)输出拉高
#define CS_L PBout(14)=0 //令PB14 (CS 使能位)输出拉低
#define CLK_H PBout(15)=1 //令PB15 (CLK)输出拉高
#define CLK_L PBout(15)=0 //令PB15 (CLK)输出拉低
//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 26
//#define WHAMMY_BAR 8
//These are stick values
#define PSS_RX 5 右遥控数据
#define PSS_RY 6
#define PSS_LX 7
#define PSS_LY 8
`
再开始命令之前
我们定义一个数组存放我们要发的数据
u16 Handkey;
u8 Comd[2]={
0x01,0x42};
u8 Data[9]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
然后我们根据时序图设置我们要发送的代码
DI 是发送 DO 是接收 可以看出
DI DO 一次发送过程有8位 数据
发送的过程中 CS一直处于 低电平
而CLK是每发送一个数据 则发送出一个脉冲 (低电平——高电平)
所以我们根据时序规律写出代码
Tips:volatile是易变型变量,是防止编译器优化代码时假设这个变量的值,保证每次小心地重新读取值。
void PS2_Cmd(u8 CMD)
{
volatile u16 ref=0x01;// 定义一个
Data[1] = 0; //令数据位1 为0
for(ref=0x01;ref<0x0100;ref<<=1) //发送一个8位的数据
{
if(ref&CMD) //输入你要发送的数据 如果不是发送为0x00 则拉高电平 准备发送状态
DO_H;
else DO_L; //否则拉低电平
CLK_H; //每发送一个指令 给CLK一个>50us电平脉冲
delay_us(50);
CLK_L;
delay_us(50);
CLK_H;
if(DI) //如果输入得到了高电平
Data[1] = ref|Data[1];