【STM32F4系列】【HAL库】【自制库】ps2手柄模块驱动

news/2024/11/23 7:25:51/

外观和电气连接

外观

手柄外观如下

在这里插入图片描述

在这里插入图片描述

接收器外观

这是接收器和底座

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4iYzkU5O-1672150811066)(图片/3.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LmF2PFAo-1672150811067)(图片/4.png)]

电气连接

需要4根连接线

单片机输出是CLK DO CS

单片机输入是DI

电源电压是3.3-5v

注意模块和单片机共地

模块不支持高速,最大时钟周期约为4us左右

因此使用软件模拟时序的方式来与模块通信

只需要将模块的4根线与单片机软件中对应的GPIO连接起来就行了

#define PS2_CS_GPIOx GPIOA
#define PS2_CS_Pin GPIO_PIN_4#define PS2_CLK_GPIOx GPIOA
#define PS2_CLK_Pin GPIO_PIN_5#define PS2_DO_GPIOx GPIOA
#define PS2_DO_Pin GPIO_PIN_7#define PS2_DI_GPIOx GPIOA
#define PS2_DI_Pin GPIO_PIN_6

软件设计

HAL初始化

需要 3个推挽输出模式的GPIO 分别是 CLK DO CS

1个上拉输入模式 DI

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mnFxvz6d-1672150811067)(图片/5.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ORM1j06t-1672150811068)(图片/6.png)]

协议分析

cs拉低开始单片机与模块的通信,拉高则通信结束

DO,DI在在CLK时钟的下降沿完成数据的发送和读取

本协议是类似SPI的协议

通信一共9个字节

这里的DODI指的是单片机的GPIO名称

Byte功能
0DO->0x01 DI <-(无意义)
1DO->0x42 DI<-(红灯0x73 无灯0X41)
2DO->0xFF DI<-0X5A
3-8DO->0xFF DI<-(按键数据)

按键数据如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IpAyuWLb-1672150811068)(图片/7.png)]

按键分析

手柄发送来的有两种模式的数据

无灯模式(MOD LED不亮)发送的摇杆是数字量,摇杆左右两侧的四向按键功能和摇杆重合

即如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZTfNvHpV-1672150811069)(图片/8.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wJ8AWDsg-1672150811069)(图片/9.png)]

红灯模式(MODE LED亮红灯)

模块传输的是摇杆的模拟量

外侧大按键独立

代码

为了方便建立了一个结构体来存储按键的数据,代码有注释,请根据设备自行测试是哪个按键即可

typedef struct
{uint8_t A_D;                                       //模拟(红灯)为1 数字(无灯)为0int8_t Rocker_RX, Rocker_RY, Rocker_LX, Rocker_LY; //摇杆值(模拟状态为实际值0-0xFF)(数字态为等效的值0,0x80,0xFF)//按键值0为未触发,1为触发态uint8_t Key_L1, Key_L2, Key_R1, Key_R2;                //后侧大按键uint8_t Key_L_Right, Key_L_Left, Key_L_Up, Key_L_Down; //左侧按键uint8_t Key_R_Right, Key_R_Left, Key_R_Up, Key_R_Down; //右侧按键uint8_t Key_Select;                                    //选择键uint8_t Key_Start;                                     //开始键uint8_t Key_Rocker_Left, Key_Rocker_Right;             //摇杆按键} PS2_TypeDef;
extern PS2_TypeDef PS2_Data;
#include "PS2.h"
uint8_t PS2_RawData[9] = {0};
PS2_TypeDef PS2_Data = {0};
void PS2_CS(uint8_t Val)
{if (Val)HAL_GPIO_WritePin(PS2_CS_GPIOx, PS2_CS_Pin, GPIO_PIN_SET);elseHAL_GPIO_WritePin(PS2_CS_GPIOx, PS2_CS_Pin, GPIO_PIN_RESET);
}
void PS2_CLK(uint8_t Val)
{if (Val)HAL_GPIO_WritePin(PS2_CLK_GPIOx, PS2_CLK_Pin, GPIO_PIN_SET);elseHAL_GPIO_WritePin(PS2_CLK_GPIOx, PS2_CLK_Pin, GPIO_PIN_RESET);
}
void PS2_DO(uint8_t Val)
{if (Val)HAL_GPIO_WritePin(PS2_DO_GPIOx, PS2_DO_Pin, GPIO_PIN_SET);elseHAL_GPIO_WritePin(PS2_DO_GPIOx, PS2_DO_Pin, GPIO_PIN_RESET);
}
uint8_t PS2_Read_DI()
{return HAL_GPIO_ReadPin(PS2_DI_GPIOx, PS2_DI_Pin);
}
void PS2_Delay()
{for (int i = 0; i < 0xBf; i++)__nop();
}
uint8_t PS2_ReadWrite_Byte(uint8_t TxData)
{uint8_t TX = TxData;uint8_t RX = 0;for (int i = 0; i < 8; i++){if (TX & 0x01)PS2_DO(1);elsePS2_DO(0);TX >>= 1;PS2_CLK(1);PS2_Delay();PS2_CLK(0);RX >>= 1;RX |= (PS2_Read_DI() << 7);PS2_Delay();PS2_CLK(1);PS2_Delay();}return RX;
}void PS2_Decode()
{if (PS2_RawData[2] == 0x5A){PS2_Data.Key_Select = (~PS2_RawData[3] >> 0) & 0x01; //选择键PS2_Data.Key_Start = (~PS2_RawData[3] >> 3) & 0x01;  //开始键//左侧按键PS2_Data.Key_L_Up = (~PS2_RawData[3] >> 4) & 0x01;PS2_Data.Key_L_Right = (~PS2_RawData[3] >> 5) & 0x01;PS2_Data.Key_L_Down = (~PS2_RawData[3] >> 6) & 0x01;PS2_Data.Key_L_Left = (~PS2_RawData[3] >> 7) & 0x01;//后侧按键PS2_Data.Key_L2 = (~PS2_RawData[4] >> 0) & 0x01;PS2_Data.Key_R2 = (~PS2_RawData[4] >> 1) & 0x01;PS2_Data.Key_L1 = (~PS2_RawData[4] >> 2) & 0x01;PS2_Data.Key_R1 = (~PS2_RawData[4] >> 3) & 0x01;//右侧按键PS2_Data.Key_R_Up = (~PS2_RawData[4] >> 4) & 0x01;PS2_Data.Key_R_Right = (~PS2_RawData[4] >> 5) & 0x01;PS2_Data.Key_R_Down = (~PS2_RawData[4] >> 6) & 0x01;PS2_Data.Key_R_Left = (~PS2_RawData[4] >> 7) & 0x01;if (PS2_RawData[1] == 0x41){ //无灯模式(摇杆值八向)PS2_Data.Rocker_LX = 127 * (PS2_Data.Key_L_Right - PS2_Data.Key_L_Left);PS2_Data.Rocker_LY = 127 * (PS2_Data.Key_L_Up - PS2_Data.Key_L_Down);PS2_Data.Rocker_RX = 127 * (PS2_Data.Key_R_Right - PS2_Data.Key_R_Left);PS2_Data.Rocker_RY = 127 * (PS2_Data.Key_R_Up - PS2_Data.Key_R_Down);}else if (PS2_RawData[1] == 0x73){ //红灯模式(摇杆值模拟)//摇杆按键PS2_Data.Key_Rocker_Left = (~PS2_RawData[3] >> 1) & 0x01;PS2_Data.Key_Rocker_Right = (~PS2_RawData[3] >> 2) & 0x01;//摇杆值PS2_Data.Rocker_LX = PS2_RawData[7] - 0x80;PS2_Data.Rocker_LY = -1 - (PS2_RawData[8] - 0x80);PS2_Data.Rocker_RX = PS2_RawData[5] - 0x80;PS2_Data.Rocker_RY = -1 - (PS2_RawData[6] - 0x80);}}
}
void PS2_Read_Data(void)
{PS2_CS(0);PS2_RawData[0] = PS2_ReadWrite_Byte(0x01); // 0PS2_RawData[1] = PS2_ReadWrite_Byte(0x42); // 1for (int i = 2; i < 9; i++)PS2_RawData[i] = PS2_ReadWrite_Byte(0xff);PS2_CS(1);PS2_Decode();
}

手柄的效果还可以,对得起25元的价格

可以二次开发做成遥控车遥控器或者电脑手柄

成品

Github


http://www.ppmy.cn/news/245962.html

相关文章

我对测试行业发展和自我价值诉求的思考

测试圈子生态的思考 其实测试的生态&#xff0c;说起来蛮简单的&#xff0c;一个词语概括就是两极分化。有个梗&#xff1a;hand hands&#xff0c;load loads&#xff0c;太贴切了。 两极分化这个词&#xff0c;可以从下面三个维度来看&#xff1a; 薪资 我认识的测试也算不少…

浏览器的回流与重绘与事件循环

浏览器的回流与重绘和事件循环 浏览器回流浏览器重绘事件循环 浏览器回流 什么是浏览器回流&#xff1f; 回流是通过JS代码让布局或者几何属性改变&#xff0c;使部分页面或者整个页面更新的过程 浏览器重绘 剩下的是浏览器重绘&#xff1a;比如改变div的visibility, color、…

MyBatis Generator自动生成MyBatis的mapper接口、XML映射文件以及实体类的代码生成工具

1.pom.xml中添加如下依赖&#xff1a; <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.4.0</version> </dependency> 2.在pom.xml中添加MyBatis G…

Linux文件基础IO

目录 C文件IO相关操作 介绍函数 文件相关系统调用接口 接口介绍 fd文件描述符 重定向 缓冲区 inode 软硬链接 动静态库 库的制作 制作静态库 制作动态库 使用库 使用静态库 使用动态库 C文件IO相关操作 介绍函数 打开文件 参数介绍&#xff1a; const char*…

MongoDB简单快速入门

MongoDB简单快速入门 简单介绍应用场景安装与启动基础操作SpringBoot整合MongoDB 简单介绍 MongoDB是一个开源、高性能、无模式的文档型数据库。NoSQL数据库产品中的一种&#xff0c;是最想关系型数据库的非关系型数据库 应用场景 安装与启动 直接将安装的压缩包进行解压&…

老年人学摄影,装备该如何选择?

主要是根据自己的身体状况和你选择所要拍摄的题材来决定你选择的装备。就目前来看&#xff0c;老年人多选两种拍摄题材&#xff0c;比如北方的老年摄影爱好者&#xff0c;一是拍摄人像&#xff0c;二是拍摄小鸟。南方的老年摄影爱好者&#xff0c;多选拍摄风光为题材的。如果是…

人人都是摄影师

人人都是摄影师 变焦 焦距 等效焦距_个人渣记录仅为自己搜索用的博客-CSDN博客 相机 感光度iso,焦距,光圈,ccd 和 噪点, 景深关系表格 - fei33423 - 博客园 18 50 f2.8镜头 大三元&#xff08;相机变焦镜头&#xff09;_百度百科

猿说摄影(上)--入坑指南

最近师弟师妹们以及复读的童鞋临近毕业&#xff0c;有的想买相机拍拍毕业照&#xff0c;记录一下旅行毕业游之类的。五一放假&#xff0c;咱就先不聊技术&#xff0c;聊一下摄影&#xff0c;不过摄影也是一个技术活&#xff0c;而且烧钱。摄影穷三代&#xff0c;单反毁一生。相…