基于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 为0for(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]; //与上一段的数据进行赋值处理}
}

发送数据之后我们紧接着来读取PS2的数据表


这个数据意义顺序对照表的含义是 数据 一共 有 (9位)
首先 我们明白 英文含义 idle 空置 data 数据位置
DO 代表输出 输出指向手柄 (遥控)输出 DI 代表 向手柄接收器输入

    我们先从 DO来看 第一位: 向遥控输出 0x01第二位: 向遥控输出 0x42第三位: 向遥控输出  0x00 既 NULL 、空 、 闲置第四位: 向遥控输出  左电机参数第五位: 向遥控输出  右电机参数第六位: 向遥控输出  0x00 既 NULL 、空 、 闲置第七位: 向遥控输出  0x00 既 NULL 、空 、 闲置第八位: 向遥控输出  0x00 既 NULL 、空 、 闲置第九位: 向遥控输出  0x00 既 NULL 、空 、 闲置然后再从 DI来看 第一位: 接收器得到    0x00 既 NULL 、空 、 闲置第二位: 接收器得到    接收器得到遥控器上面的ID第三位: 接收器得到  0X5A ...(未知这个数据有什么用)第四位: 接收器得到   SELECT L3 R3 START  UP RIGHT DOWN LEFT  这8个按键的数值 (正好8个 对应8个数据位置)第五位: 接收器得到  L3 R2 L1 R1  三角形 圆形  X 正方形  这8个按键的数值 (正好8个 对应8个数据位置)第六位: 接收器得到   右遥杆 X值的坐标 可以看到 0X00 是指左边  0XFF 指指向右边  从左到右边 分了 0 ~255 个数值第七位: 接收器得到   右遥杆 Y值的坐标 可以看到 0X00 是指上边  0XFF 指指向下边  从上到下边 分了 0 ~255 个数值第八位: 接收器得到  左遥杆 X值的坐标 可以看到 0X00 是指左边  0XFF 指指向右边  从左到右边 分了 0 ~255 个数值第九位: 接收器得到   左 遥杆 Y值的坐标 可以看到 0X00 是指上边  0XFF 指指向下边  从左到右边 分了 0 ~255 个数值
void PS2_ReadData(void)
{volatile u8 byte=0;volatile u16 ref=0x01;CS_L;  //拉低电平表示准备要来数据了PS2_Cmd(Comd[0]);   //0X01PS2_Cmd(Comd[1]);   //0X02for(byte=2;byte<9;byte++)     //发送6次 从2开始是因为指引数组{for(ref=0x01;ref<0x100;ref<<=1)   //循环8次 不断左移 1 位{CLK_H;    //脉冲CLK_L;delay_us(50);CLK_H;if(DI)  //收到DI的数据Data[byte] = ref|Data[byte];  //把脉冲数据保存下来}delay_us(50);}CS_H;
}

判断PS2是否为红灯状态 (红灯状态不工作)

u8 PS2_RedLight(void)
{CS_L;  //低电平 告诉 PS2_Cmd(Comd[0]);  //发送第一个通信码PS2_Cmd(Comd[1]);  //发送第二个通信码CS_H;if( Data[1] == 0X73)   return 0 ; //0X41 表示绿灯 0X73表示红灯else return 1
}

读取手柄数据

void PS2_ReadData(void)
{volatile u8 byte=0; //  volatile防止比特位数据被修改 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)  //循环8次 每一次 脉冲一个字节{CLK_H;     DELAY_TIME;CLK_L;DELAY_TIME;CLK_H;if(DI)Data[byte] = ref|Data[byte];//存储数据}delay_us(16);  //接收数据处理时间}CS_H; //高电平
}

得到摇杆值的模拟量 范围 0 ~ 255

u8 PS2_AnologData(u8 button)
{return Data[button];
}

清空数据缓冲区

void PS2_ClearData()   //将数组的数据全部清理为0
{u8 a;for(a=0;a<9;a++)Data[a]=0x00;
}

手柄振动函数
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);
}

完成并保存配置

void PS2_ExitConfing(void)
{CS_L;delay_us(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;delay_us(16);
}

手柄配置 初始化

//ÊÖ±úÅäÖóõʼ»¯
void PS2_SetInit(void)
{PS2_ShortPoll();PS2_ShortPoll();PS2_ShortPoll();PS2_EnterConfing();        //进入配置模式PS2_TurnOnAnalogMode(); //红绿灯配置模式 能否初始化PS2_VibrationMode(); //开启震动模式PS2_ExitConfing();      //完成并且保存配置

分割线
下面是 我的主函数

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"
#include "pstwo.h"u8 x=0;int main(void){  u8 angle=0;  u8 key=0;u8 lcd_id[12];         delay_init();       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); uart_init(115200);   LED_Init();              LCD_Init();LCD_Clear(BLACK);PS2_Init();    sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);LED1=1;LED0=1;   PS2_SetInit(); while(1) {       sprintf((char*)lcd_id,"KEY :%04X",key);LCD_ShowString(30,40,210,24,24,"SHOW TIME !! "); x  = key%10;switch(x){case 0:LCD_Clear(WHITE);delay_ms(10);;break;case 1:LCD_Clear(BLACK);delay_ms(10);break;case 2:LCD_Clear(BLUE);delay_ms(10);break;case 3:LCD_Clear(RED);delay_ms(10);break;case 4:LCD_Clear(MAGENTA);delay_ms(10);break;case 5:LCD_Clear(GREEN);delay_ms(10);break;case 6:LCD_Clear(CYAN);delay_ms(10);break;case 8:LCD_Clear(YELLOW);delay_ms(10);break;case 9:LCD_Clear(BRRED);delay_ms(10);break;case 10:LCD_Clear(GRAY);delay_ms(10);break;case 11:LCD_Clear(LGRAY);delay_ms(10);break;}key=PS2_DataKey();sprintf((char*)lcd_id,"PS2::%04X",key); POINT_COLOR=RED;    LCD_ShowString(30,110,200,16,16,lcd_id);       PS2_ReadData();  angle = (PS2_AnologData(PSS_RX)/5)*3+15; delay_ms(1);if(key!=0)LED1=!LED1;}
}

【STM32 嵌入式设计】PS2索尼游戏手柄解析和代码开发相关推荐

  1. STM32嵌入式系统FreeRTOS使用cJSON解析和构建JSON

    一.环境 控制器STM32F407+MDK5.34+cJSON1.7.7 二.安装cJSON MDK中打开Pack Install,选择Generic下边MDK-Pack::cJSON,点击安装Ins ...

  2. 索尼游戏手柄SP2的开发体会

    索尼游戏手柄SP2的开发体会 1.PS手柄介绍 接收器引脚输出: 通信时序: 2.代码解读 3.库文件解读 ps2手柄是索尼的PlayStation2游戏机的遥控手柄. 该款手柄的通讯协议被游戏爱好者 ...

  3. verilog实例_Verilog设计与逻辑综合实例解析(含代码)(Tasks amp;Functions)

    1.function中的逻辑被综合成了什么? 由于function中没有任何时序结构,function只能综合出组合逻辑. 例如,以下function有2个输入信号和一个控制信号,输出算术运算结果. ...

  4. 计算机三级嵌入式试题讲解,计算机三级嵌入式系统操作题及解析.docx

    PAGE PAGE # 计算机三级嵌入式系统操作题及解析 操作题(一) 1地铁进出站闸机的控制器以 S3C2410芯片为核心,并外加其他功能电 路来进行设计,其基本功能描述如下: a闸机能够识别本地铁 ...

  5. 蓝桥杯嵌入式设计与开发历届客观题答案

    该页面由pdf转换而来,阅读效果不佳,你可以在这里下载pdf原件:https://download.csdn.net/download/dvs_dn/85085622 你也可以在百度文库免费下载该文档 ...

  6. 第十二届省赛嵌入式设计与开发《停车计费系统》

    前言 刷了几套蓝桥杯省赛程序题目,心有所感,故写下文章记录一下,本篇文章记录的是第十二届省赛嵌入式设计与开发程序设计题目. 这套题的考察重点和难点在STM32的串口和字符串的处理,难点在于细节方面,对 ...

  7. c语言自定义函数程序设计,ch3自定义函数设计 C语言 《解析C程序设计》.ppt

    ch3自定义函数设计 C语言 <解析C程序设计> 全局变量--外部变量 在函数外定义的变量 有效范围:从定义变量的位置开始到本源文件结束,及有extern声明的其它源文件 存储类型:缺省e ...

  8. Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战

    Java生鲜电商平台-秒杀系统微服务架构设计与源码解析实战 Java生鲜电商平台-  什么是秒杀 通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动 比如说京东秒杀,就是一种定时定量秒杀,在规定 ...

  9. Java生鲜电商平台-促销系统的架构设计与源码解析

    Java生鲜电商平台-促销系统的架构设计与源码解析 说明:本文重点讲解现在流行的促销方案以及源码解析,让大家对促销,纳新有一个深入的了解与学习过程. 促销系统是电商系统另外一个比较大,也是比较复杂的系 ...

最新文章

  1. 《学习vi编辑器》的学习笔记1
  2. SQL Server自带备份整个数据库脚本工具
  3. 这个项目团队能少了谁?
  4. [技术分享]利用MSBuild制作msf免杀的后门
  5. SpringMvc的服务器端跳转和客户端跳转
  6. python_day6 shutil模块
  7. jsf 项目_您将在下一个项目中使用JSF吗?
  8. 超级强大的socket工具ss,替代netstat
  9. accept 返回0_使用Vue3.0新特性造轮子 WidgetUI3.0 (Upload上传文件组件)
  10. python3.5安装教程及环境配置_Python安装和环境配置教程
  11. gophp解释器_go语言环境搭建、基本使用
  12. 大数据杀熟,是真的吗?
  13. 除了人工智能,霍金还担心“游牧外星人”会摧毁人类
  14. 估计的商是什么意思_商是什么意思,商的繁体字,商有几笔,商字几画
  15. php开发中控考勤机,中控考勤机
  16. 快速入门一个简单的情感分类项目
  17. tvp5150 gm7150配置
  18. (一)理解word2vec:原理篇
  19. 对自动变速器的控制器建模
  20. JAVA毕业设计web家教管理系统计算机源码+lw文档+系统+调试部署+数据库

热门文章

  1. mysql gtid 主备搭建
  2. 【深度学习目标检测】一、基于yolov3的水果商品检测分类
  3. 测试身体素质健康的软件,鼎慧信体质健康测试管理系统
  4. 生肖猪鼠年运程面面观
  5. 中国流动人口动态监测调查数据
  6. d校车管理系统c语言,客车班车校车车辆定位管理系统APP功能开发
  7. 2020省赛->棋盘放麦子
  8. acdsee 看不到缩略图不能批量查看的解决方法!哈哈!
  9. 《白话大数据与机器学习》读书笔记2
  10. SIMCOM7600CE TCP通信