HAL库控制PS2手柄「建议收藏」

HAL库控制PS2手柄「建议收藏」通过hal库配置SPI,并完成和PS2的通信

大家好,又见面了,我是你们的朋友全栈君。

吐槽一下

最近买了个ps2手柄,结果买家发的例程全都是好几年前的库函数版本,尝试移植基本没啥可能。虽然PS2手柄已经被开发很久了,不过我看网上用hal库来写控制的很少,例程也都是用库函数写的,因此写篇文章来帮助刚开始接触PS2又懒得用库函数的同学。

SPI通信协议

提一下,方便理解代码

这个已经被破解很久了,具体的时序就这样。PS2手柄开启,接收器正常工作并接受以后,数据可以通过spi通信来发送接受,然后就可以通过单片机来完成数据接收和发送。

  • SPI, serial peripheral interface, 串行外围设备接口。高速的,全双工的,同步通信总线。有四个引脚。需要注意的是,可能有的人被串口通信坑过,于是就把主机和从机的收发接口反接,SPI通信是一一对应的连接。DO借DO,DI接DI,时钟和CS引脚也是如此。

HAL库控制PS2手柄「建议收藏」

 很明显可以看到是一一对应。

  • 连接好后,CS引脚维持高电平,通信开始时把CS电平拉低(当然你也可以反过来,平时维持低电平通信高电平)每次发送接受数据时,时钟(CLK,SCLK等)引脚如下图变换,此时DO和DI口开始交换数据(沿时钟上升沿或下降沿,可以在cubemx里设置)

HAL库控制PS2手柄「建议收藏」

( 当然你也可以选择同步接受和发送,spi是支持的)

PS2通信协议

这个网上资料也很多了,我就大概提一下,提到编程需要知道的程度。

在连接好PS2手柄和接收器以后,接收器绿灯常亮(一般可以先试试只接电源,开启手柄,看能否配对成功),硬件没问题的情况下就可以开始编程了。

  • 首先用单片机给PS2发送一个0x01,然后PS2会给你返回一个ID(说明此时是绿灯mode还是红灯mode),单片机再给他发送一个0x42(请求接受数据),PS2返回0x5a(表示可以开始传输数据),剩下的就是接受他的摇杆和按键数据了,下面这个图可以十分精确的说明。

HAL库控制PS2手柄「建议收藏」

 接受完数据以后就是处理数据,然后用在你想用的地方就好了。

配置cubemx

我这边用的是st的nucleo-f104开发板,只要你的开发板支持SPI和串口通信就好了。

  • 首先是配置时钟,没啥好说的。

HAL库控制PS2手柄「建议收藏」

  •  配置SPI,选几个你插着舒服的引脚就好了。

根据PS2硬件资料,这里的SPI不能乱配置,需要注意的地方如下

  1. 全双工模式,主机
  2. 不使能硬件nss,自己多设置一个输出引脚当CS就好
  3. LSB先输出
  4. CPOL设置为High
  5. CPHA设置为第一个边沿
  6. 64分频(非常重要,PS2支持的通信频率只有250khz,要是你单片机通信频率过高会造成PS2只返回给你0xff,就是一直给你拉高电平)

HAL库控制PS2手柄「建议收藏」

 串口自己设置就好,能证明你正常接收到数据就行。

  • 主程序非常简单,就是上面说的先拉低CS脚,发送一个0x01,等10us,然后发送0x42,并且接收data[1],就是手柄的ID(绿灯模式是0x41),然后再发送接收,根据接收到的数据判断哪一位按下(按下为0,否则为1)。具体时序网上都有。
uint8_t cmd[3] = {0x01,0x42,0x00};  // 请求接受数据
uint8_t PS2data[9] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};   //存储手柄返回数据

void PS2_Get(void)    //接受ps2数据
{
	uint8_t i = 0;
	
	HAL_GPIO_WritePin(ENABLE_GPIO_Port,ENABLE_Pin,GPIO_PIN_RESET);  //拉高,开始通讯
		
	HAL_SPI_TransmitReceive(&hspi1,&cmd[0],&PS2data[0],1,0xffff); // 发送0x01,请求接受数据
	delay_us(10);
	HAL_SPI_TransmitReceive(&hspi1,&cmd[1],&PS2data[1],1,0xffff); // 发送0x42,接受0x01(PS2表示开始通信)
	delay_us(10);
	HAL_SPI_TransmitReceive(&hspi1,&cmd[2],&PS2data[2],1,0xffff); // 发送0x00,接受ID(红绿灯模式)
	delay_us(10);
	for(i = 3;i <9;i++)
	{
		HAL_SPI_TransmitReceive(&hspi1,&cmd[2],&PS2data[i],1,0xffff); // 接受数据
		delay_us(10);
		
	}
	
	HAL_GPIO_WritePin(ENABLE_GPIO_Port,ENABLE_Pin,GPIO_PIN_SET);  //拉低,准备下次通讯
	
}

 这样子就能将数据存储在单片机里了。

数据处理

我估计反正也没人看,就随便提一嘴。

按键的话,定义存储的结构是uint8_t,没有按键按下的时候返回值(二进制看)11111111,有一个按键按下时就会有对应一个1变成0,比如10111111,具体测试一下就知道了。通过位运算就可以很简单的把所有按键值提取出来,做到全按键无冲突。

摇杆我个人习惯时1-1000范围均匀变化,手柄返回的值是0-255变化,这个强制转换也就很简单可以完成了。建议一直开着红灯模式,不然摇杆不返回模拟值,调小车占空比也是这个范围嘛。

附个一个周期正常传输数据的图(逻辑分析仪)

HAL库控制PS2手柄「建议收藏」

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/131134.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • pycharm使用anaconda虚拟环境_conda和anaconda

    pycharm使用anaconda虚拟环境_conda和anacondapycharm加载anconda创建的虚拟环境一、环境​ 1、虚拟环境为xy01,python版本为3.7。二、流程​ 1、首先点击pycharm左上方File->settings,得到如下界面,再点击右上方红框,再点击add。​ 2、得到如下界面,点击左边的condaenvironment,选择existingenvironment,再选择创建的虚拟环境,最后点击OK,则pycharm已经加载新创建的conda虚拟环境。…

  • golang 激活码 2021[在线序列号][通俗易懂]

    golang 激活码 2021[在线序列号],https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • 21位数激活码生成[最新免费获取]「建议收藏」

    (21位数激活码生成)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html…

  • 集合:映射,单射,满射,双射

    集合:映射,单射,满射,双射这些概念太重要了,虽然很不起眼,但是几乎所有地方都要用,一旦不清楚,会对一个问题审视错误。集合:元素汇聚在一起,就构成了一个集合。假设有集合A和集合B。映射:将A中的每一个元素,根据一个规则,对应到B中的一个元素去,比如A中是一些儿女,B中是他们的父亲,那么每一个A中的元素都可以对应到B中的唯一一个元素,这就是一种规则,即映射。因为一个人的爸爸只有一个,但是反之未必,因为一个爸爸可能有多个儿女。我们发现,这个和函数的概念非常相似,集合A相当于定义域,映射相当于f。但是集合的概念更加宽泛,正如前面所有

  • PyTorch基础——使用pytorch加载cifar10数据集

    PyTorch基础——使用pytorch加载cifar10数据集使用torchvision.datasets模块可以加载cifar10数据集,涉及函数为torchvision.datasets.CIFAR10(root,train,download)root:cifar10数据集存放目录train:True,表示加载训练数据集,False,表示加载验证数据集download:True,表示cifar10数据集在root指定的文件夹不存在时,会自动下载,False,表示不管root指定文件夹是否存在cifar10数据集,都不会自动下载cifar10数据集

  • Linux SIGPIPE信号产生原因与解决方法

    Linux SIGPIPE信号产生原因与解决方法TCP四次握手产生SIGPIPE的原因SIGPIPE信号产生的原因:简单来说,就是客户端程序向服务器端程序发送了消息,然后关闭客户端,服务器端返回消息的时候就会收到内核给的SIGPIPE信号。TCP的全双工信道其实是两条单工信道,client端调用close的时候,虽然本意是关闭两条信道,但是其实只能关闭它发送的那一条单工信道,还是可以接受数据,server端还是可以发送…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号