1. PS2手柄介绍

    PS2手柄由手柄与接收器两部分组成,手柄主要负责发送按键信息;接收器与单片机(也可叫作主机,可直接用在 PS2 游戏机上)相连,用于接收手柄发来的信息,并传递给单片机,单片机也可通过接收器,向手柄发送命令,配置手柄的发送模式。

2.使用说明

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

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

NC:空端口;

GND:电源地;

VDD:接收器工作电源,电源范围3~5V;

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

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

NC:空端口;

ACK:从手柄到主机的应答信号。此信号在每个8bits 数据发送的最后一个周期变低并且CS 一直保持低电平,如果CS 信号不变低,约60 微秒PS 主机会试另一个外设。在编程时未使用ACK 端口。

3.STM32F1测试例程

Main.c文件

#include <stdio.h>
#include "stm32f10x.h"
#include "delay.h"
#include "usart.h"
#include "pstwo.h"
#include "Led_Key.h"//------------接线说明---------------
//PS2接收器--------STM32F1主板1引脚//    VCC     -----------    V3.3
//    GND     -----------    GND
//    DI、DAT      --------- PA3
//    DO、CMD      ----------PA2
//    CS      -----------    PA1
//    CLK     -----------    PA0 int PS2_LX,PS2_LY,PS2_RX,PS2_RY,PS2_KEY;
int main(void)
{ SystemInit(); //======配置系统时钟为72M  delay_init(); //======初始化延时函数uart_init(9600);//======串口初始化delay_ms(1000); //======延时等待初始化稳定PS2_Init();      //======ps2驱动端口初始化PS2_SetInit();  //======ps2配置初始化,配置“红绿灯模式”,并选择是否可以修改delay_ms(1000);while(1){       PS2_LX=PS2_AnologData(PSS_LX);      PS2_LY=PS2_AnologData(PSS_LY);PS2_RX=PS2_AnologData(PSS_RX);PS2_RY=PS2_AnologData(PSS_RY);PS2_KEY=PS2_DataKey();   printf("%d     PS2_LX:",PS2_LX);printf("%d     PS2_LY:",PS2_LY);printf("%d     PS2_RX:",PS2_RX);printf("%d     PS2_RY:",PS2_RY);printf("%d \r\nPS2_KEY:",PS2_KEY);switch(PS2_KEY){case 5:LED2_TOGGLE;break;}delay_ms(150);} }

pstwo.c文件

#include "pstwo.h"
/*********************************************************
**********************************************************/
#define DELAY_TIME  delay_us(5);
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};  /**************************************************************************
函数功能:以下是PS2接收器模块的初始化代码
入口参数:无
返回  值:无
按键值与按键明
手柄接口初始化    输入  DI->PA3 输出  DO->PA2    CS->PA1  CLK->PA0
**************************************************************************/
void PS2_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;                           //定义GPIO_InitStructure结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);           //开启GPIOA时钟GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;                 //复用推挽输出模式GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_0;  //P1.P2.P0口 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;                //50MHZGPIO_Init(GPIOA,&GPIO_InitStructure);                          //GPIOA初始化  PA1 PA2  PA0     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;                     //下拉输入模式GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;                                                   //P3口GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;                //50MHZ  GPIO_Init(GPIOA,&GPIO_InitStructure);                          //GPIOA初始化 PA0
}
/**************************************************************************
函数功能:向手柄发送命令
入口参数:CMD指令
返回  值:无
**************************************************************************/
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_TIME;CLK_L;DELAY_TIME;CLK_H;if(DI)Data[1] = ref|Data[1];}delay_us(16);
}
/**************************************************************************
函数功能:判断是否为红灯模式,0x41=模拟绿灯,0x73=模拟红灯
入口参数:CMD指令
返回  值: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_TIME;CLK_L;DELAY_TIME;CLK_H;if(DI)Data[byte] = ref|Data[byte];}delay_us(16);}CS_H;
}
/**************************************************************************
函数功能:对读出来的PS2的数据进行处理,只处理按键部分
入口参数:CMD指令
返回  值:无
//只有一个按键按下时按下为0, 未按下为1
**************************************************************************/
u8 PS2_DataKey()
{u8 index;PS2_ClearData();PS2_ReadData();Handkey=(Data[4]<<8)|Data[3];     //这是16个按键  按下为0, 未按下为1for(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;
}
/******************************************************
函数功能: 手柄震动函数,
Calls:       void PS2_Cmd(u8 CMD);
入口参数: 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(0x03); //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();      //完成并保存配置
}

pstwo.h文件

#ifndef __PSTWO_H
#define __PSTWO_H
#include "delay.h"
#include "sys.h"
/*******************************************************************************************************************/
#define DI   PAin(3)           //PA0  输入#define DO_H PAout(2)=1        //命令位高
#define DO_L PAout(2)=0        //命令位低#define CS_H PAout(1)=1       //CS拉高
#define CS_L PAout(1)=0       //CS拉低#define CLK_H PAout(0)=1      //时钟拉高
#define CLK_L PAout(0)=0      //时钟拉低//手柄接口初始化    输入  DI->PA0
//                 输出  DO->PA1    CS->PA2  CLK->PA3//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 8extern u8 Data[9];
extern u16 MASK[16];
extern u16 Handkey;void PS2_Init(void);
u8 PS2_RedLight(void);   //判断是否为红灯模式
void PS2_ReadData(void); //读手柄数据
void PS2_Cmd(u8 CMD);         //向手柄发送命令
u8 PS2_DataKey(void);         //按键值读取
u8 PS2_AnologData(u8 button); //得到一个摇杆的模拟量
void PS2_ClearData(void);     //清除数据缓冲区
void PS2_Vibration(u8 motor1, u8 motor2);//振动设置motor1  0xFF开,其他关,motor2  0x40~0xFFvoid PS2_EnterConfing(void);     //进入配置
void PS2_TurnOnAnalogMode(void); //发送模拟量
void PS2_VibrationMode(void);    //振动设置
void PS2_ExitConfing(void);      //完成配置
void PS2_SetInit(void);          //配置初始化#endif

可以通过实际使用情况定义修改IO口,如果要修改IO口只需要修改下面相应串口部分:

PS2还是非常方便的!

【STM32】PS2遥控手柄使用和程序移植相关推荐

  1. 对PS2遥控手柄与stm32单片机通信的理解(结合平衡小车之家的说明和程序)

    为了更好地应用PS2遥控手柄,我想尽可能理解一下它与stm32单片机间通信控制的过程,首先看了平衡小车之家给的PS2遥控手柄使用说明,讲解的内容比较简洁,光凭这个说明不能很轻易地理解配套的程序逻辑,接 ...

  2. 单片机右摇杆c语言函数英文,对PS2遥控手柄与stm32单片机通讯的理解(结合平衡小车之家的说明和程序)...

    为了更好地应用PS2遥控手柄,我想尽量理解一下它与stm32单片机间通讯控制的过程,首先看了平衡小车之家给的PS2遥控手柄使用说明,讲解的内容比较简洁,光凭这个说明不能很轻易地理解配套的程序逻辑,接下 ...

  3. STM32F4 高主频引起的PS2遥控手柄协议移植问题

    在STM32F103主板上运行正常的PS2手柄驱动协议,平移到STM32F405的板子上,遇到板子收不到手柄按键信号的情况.各种查找资料,各种测试之后,终于在这篇博文的启发下找到了问题.关于使用STM ...

  4. STM32F103ZET6程序移植为C8T6+C8T6下载程序flash timeout的解决方案

    文章目录 一.程序移植 :程序移植还是蛮简单的 二.程序下载 : 会出现问题 (一)BOOT0和BOOT1 (二)程序下载 1.代码通用 2.状况不断 3.解决办法 (三)STM32F103C8T6下 ...

  5. PS2无线遥控手柄与STM32单片机通信

    PS2无线遥控手柄 接下来要做一个小车玩玩,在网上淘了一个PS2无线遥控手柄,用于控制小车的前进.后退等功能. 实物图如下: 其中有两个PS2游戏摇杆,对应的驱动原理参见下文: PS2游戏摇杆原理及控 ...

  6. 基于STM32F103的树莓派ROS小车——PS2遥控程序解析

    基于STM32F103ZET6的PS2遥控ROS小车程序解析 序言 1. PS手柄介绍 2. 使用说明 2.1 引脚说明 2.2 时序图分析 3. 手柄测试 4. 程序解析 5. 仿真 6. 源码链接 ...

  7. 基于STM32标准库的MS5837程序移植

    基于STM32标准库的MS5837程序移植 一.准备工作 1. 硬件电路 2. 新建工程 二.开始移植 1. IIC底层模拟 2. MS5837移植 3. 主函数编写 4. 代码调试结果 三.源代码下 ...

  8. stm32f103各个型号芯片之间程序移植(stm32的兼容问题)

    stm32f103各个型号芯片之间程序移植(stm32的兼容问题) 1.stm32f103系列的各个型号的芯片差别一般不大,都是一些flash大小不一样,一般是向下兼容(大容量芯片兼容中容量芯片)还有 ...

  9. esp8266时钟_ESP8266(Non-OS SDK) 驱动 waveshare 2.9 寸墨水屏(二)- 程序移植、修改与测试

    开始移植 上一篇文章简单介绍了了墨水屏原理.例程代码以及移植工作的可行性.这一步的目的是把前面在 STM32 跑的程序,完整地搬到 esp8266 上,达到相同的运行显示效果,Let's get st ...

  10. 玩转X-CTR100 l STM32F4 l PS2无线手柄-4WD智能小车

    我造轮子,你造车,创客一起造起来!更多塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 前面已介绍X-CTR100控制器解码PS2无线手 ...

最新文章

  1. 使用acme.sh撸一个免费且自动更新的HTTPS证书
  2. python 数据可视化 -- 读取数据
  3. 如何理解java中String的不可变性
  4. flex上传图片到java服务器
  5. JAVA多线程互斥同步例子
  6. oracle怎么判断地址相似,如何查看oracle数据文件的地址
  7. H3C三层交换机划分VLAN示例
  8. 前端ajax数据提交到服务器_详解前端如何让服务器主动向浏览器推送数据
  9. c++将小数化为二进制_C++中的float内存存储、与十进制的转换
  10. Kubernetes 是什么?为什么也称为 K8S?| 科普
  11. wpf-AvalonDock-使用技巧总结
  12. 速读《现代软件工程——构建之法》有感
  13. 详细Ubuntu系统修改默认软件下载源
  14. Facebook,Twitter,Linkedin分享
  15. 浪潮服务器如何安装win7系统,WIN7旗舰版操作系统中浪潮ERP-GS5.2安装说明.doc
  16. 电脑主板资料库 07【转至www.ongood.com.tw】【FreeXploiT收集整理】
  17. python爬取微博热搜榜
  18. 从k8s集群主节点数量为什么是奇数来聊聊分布式系统
  19. 存款买房python
  20. 12位早起的IT大佬们让小伙伴们都惊呆了

热门文章

  1. Blender 常用快捷键记录 (二)
  2. 如何减小电压跟随器输出电阻_河南安全型耦合器生产厂家-作用_华锐矿机
  3. LM358运放(比较器、跟随器)输出最高电压问题的探讨
  4. HCIA-Storage 存储工程师学习笔记——1. 存储技术趋势
  5. WlMAP:突破内网端口转发映射工具
  6. 查看浏览器保存的密码
  7. 不明白如何将批量图片格式转换?2招教你们快速搞定
  8. 科学软件编辑器在科研项目中的应用感想
  9. 天堂 heaven
  10. 北京内推 | 微软亚洲研究院机器学习组招聘NLP/语音合成等方向全职研究员