PS2无线手柄控制模块
PS2 手柄兼容索尼的 PlayStation2 游戏机的遥控手柄。索尼的 psx 系列游戏主机在全球很是畅销。不知什么时候便有人打起 PS2 手柄的主意,破解了通讯协议,使得手柄可以接在其他器件上遥控使用,比如遥控我们熟悉的机器人。突出的特点是这款手柄性价比极高,按键丰富,方便扩展到其它应用中。
模块来源
采购链接:
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-19589090137.10.257136b4kQus88&id=559076487258
资料下载链接:
https://pan.baidu.com/s/15WcgkOqKLfXpQpZ4qv3rJA
资料提取码:3qdg
规格参数
手柄工作电压:两节7号电池供电
接收器工作电压:3~5V
遥控距离:15米左右
控制方式:串行通信
管脚数量:6 Pin
移植过程
我们的目标是在【立创开发板GD32E230C8T6】上能够实现读取PS2手柄上的哪一个按键被按下和读取遥感的AD值的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
查看资料
PS2 手柄由手柄与接收器两部分组成,手柄主要负责发送按键信息;接收器与单片机 (也可叫作主机,可直接用在 PS2 游戏机上)相连,用于接收手柄发来的信息,并传递给单片机,单片机也可通过接收器,向手柄发送命令,配置手柄的发送模式。 特别声明:因批次不同或代工厂家不同,手柄和接收器的外观会有所区别(接收器上 都有指示灯,但一种接收器上有电源灯,另一种没有电源灯),但是接收器的引脚定义是一样的,解码方式是一样的,使用相同。 引脚说明
控制说明
时钟频率 250KHz(4us),如果接收数据不稳定,可以适当的增加频率。在通讯过中,一串数据通讯完成后 CS 才会由低转高,不是 1 个字节通讯完成后就由低转高,在通讯期间,一直处于低电平。 在时钟下降沿时,完成数据(lbit)的发送与接收,发送和接收是同时完成的。
当单片机想读手柄数据或向手柄发送命令时,将会拉低 CS 线电平,并发出一个命令“0x01”;手柄会回复它的 ID “0x41=绿灯模式,0x73=红灯模式”;在手柄发送 ID 的同时,单片机将传送 0x42,请求数据;随后手柄发送出 0x5A,告诉单片机“数据来了”。
一个通讯周期有 9 个字节(8 位),这些数据是依次按位传送。
idle:数据线空闲,该数据线无数据传送。
举例:当有按键按下,对应位为“0”,其他位为“1”,例如当键“SELECT”被按下时,Data[]=11111110。
红灯模式时 :左右摇杆发送模拟值,0x00〜OxFF 之间,且摇杆按下的键值 L3、R3 有效;
绿灯模式时 :左右摇杆模拟值为无效,推到极限时,对应发送 UP、RIGHT、DOWN、LEFT、△、〇、X、□,但是按键 L3、R3 无效。
引脚选择
移植至工程
移植步骤中的导入.c和.h文件与上一节相同,只是将.c和.h文件更改为bsp_ps2.c与bsp_ps2.h。移植完成后面修改相关代码。
详细可见【TTP224触摸传感器】中的移植至工程目录。这里不再过多讲述。移植完成后面修改相关代码。
工程参考入门手册工程模板
我们打开usart.c文件,将里面的代码换成下方的代码:
/******************************************************************************
* 测试硬件:立创开发板·GD32E230C8T6 使用主频72Mhz 晶振8Mhz
* 版 本 号: V1.0
* 修改作者: www.lckfb.com
* 修改日期: 2023年11月02日
* 功能介绍:
*****************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:【立创·GD32E230C8T6开发板】模块移植手册
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
******************************************************************************/
#include "bsp_usart.h"
#include "stdio.h"
uint8_t g_recv_buff[]; // 接收缓冲区
uint16_t g_recv_length = 0; // 接收数据长度
uint8_t g_recv_complete_flag = 0; // 接收数据完成标志位
/************************************************
函数名称 : usart_gpio_config
功 能 : 串口配置GPIO
参 数 : band_rate:波特率
返 回 值 : 无
作 者 : LC
*************************************************/
void usart_gpio_config(uint32_t band_rate)
{
/* 开启时钟 */
rcu_periph_clock_enable(BSP_USART_TX_RCU); // 开启串口时钟
rcu_periph_clock_enable(BSP_USART_RX_RCU); // 开启端口时钟
rcu_periph_clock_enable(BSP_USART_RCU); // 开启端口时钟
/* 配置GPIO复用功能 */
gpio_af_set(BSP_USART_TX_PORT,BSP_USART_AF,BSP_USART_TX_PIN);
gpio_af_set(BSP_USART_RX_PORT,BSP_USART_AF,BSP_USART_RX_PIN);
/* 配置GPIO的模式 */
/* 配置TX为复用模式 上拉模式 */
gpio_mode_set(BSP_USART_TX_PORT,GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_USART_TX_PIN);
/* 配置RX为复用模式 上拉模式 */
gpio_mode_set(BSP_USART_RX_PORT, GPIO_MODE_AF,GPIO_PUPD_PULLUP,BSP_USART_RX_PIN);
/* 配置TX为推挽输出 50MHZ */
gpio_output_options_set(BSP_USART_TX_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,BSP_USART_TX_PIN);
/* 配置RX为推挽输出 50MHZ */
gpio_output_options_set(BSP_USART_RX_PORT,GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_USART_RX_PIN);
/* 配置串口的参数 */
usart_deinit(BSP_USART); // 复位串口
usart_baudrate_set(BSP_USART,band_rate); // 设置波特率
usart_parity_config(BSP_USART,USART_PM_NONE); // 没有校验位
usart_word_length_set(BSP_USART,USART_WL_8BIT); // 8位数据位
usart_stop_bit_set(BSP_USART,USART_STB_1BIT); // 1位停止位
/* 使能串口 */
usart_enable(BSP_USART); // 使能串口
usart_transmit_config(BSP_USART,USART_TRANSMIT_ENABLE); // 使能串口发送
usart_receive_config(BSP_USART,USART_RECEIVE_ENABLE); // 使能串口接收
/* 中断配置 */
nvic_irq_enable(BSP_USART_IRQ, 2); // 配置中断优先级
usart_interrupt_enable(BSP_USART,USART_INT_RBNE); // 读数据缓冲区非空中断和溢出错误中断
usart_interrupt_enable(BSP_USART,USART_INT_IDLE); // 空闲检测中断
}
/************************************************
函数名称 : usart_send_data
功 能 : 串口重发送一个字节
参 数 : ucch:要发送的字节
返 回 值 :
作 者 : LC
*************************************************/
void usart_send_data(uint8_t ucch)
{
usart_data_transmit(BSP_USART,(uint8_t)ucch); // 发送数据
while(RESET == usart_flag_get(BSP_USART,USART_FLAG_TBE)); // 等待发送数据缓冲区标志置位
}
/************************************************
函数名称 : usart_send_String
功 能 : 串口发送字符串
参 数 : ucstr:要发送的字符串
返 回 值 :
作 者 : LC
*************************************************/
void usart_send_string(uint8_t *ucstr)
{
while(ucstr && *ucstr) // 地址为空或者值为空跳出
{
usart_send_data(*ucstr++); // 发送单个字符
}
}
/************************************************
函数名称 : fputc
功 能 : 串口重定向函数
参 数 :
返 回 值 :
作 者 : LC
*************************************************/
int fputc(int ch, FILE *f)
{
usart_send_data(ch);
// 等待发送数据缓冲区标志置位
return ch;
}
/************************************************
函数名称 : BSP_USART_IRQHandler
功 能 : 串口接收中断服务函数
参 数 : 无
返 回 值 : 无
作 者 : LC
*************************************************/
void BSP_USART_IRQHandler(void)
{
if(usart_interrupt_flag_get(BSP_USART,USART_INT_FLAG_RBNE) == SET) // 接收缓冲区不为空
{
g_recv_buff[] = usart_data_receive(BSP_USART); // 把接收到的数据放到缓冲区中
}
if(usart_interrupt_flag_get(BSP_USART,USART_INT_FLAG_IDLE) == SET) // 检测到帧中断
{
usart_data_receive(BSP_USART); // 必须要读,读出来的值不能要
g_recv_buff[] = '\0'; // 数据接收完毕,数组结束标志
g_recv_complete_flag = 1; // 接收完成
usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
我们打开usart.h文件,将里面的代码换成下方的代码:
/******************************************************************************
* 测试硬件:立创开发板·GD32E230C8T6 使用主频72Mhz 晶振8Mhz
* 版 本 号: V1.0
* 修改作者: www.lckfb.com
* 修改日期: 2023年11月02日
* 功能介绍:
*****************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:【立创·GD32E230C8T6开发板】模块移植手册
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
******************************************************************************/
#ifndef _BSP_USART_H
#define _BSP_USART_H
#include "gd32e23x.h"
#include "systick.h"
#define BSP_USART_TX_RCU RCU_GPIOA // 串口TX的端口时钟
#define BSP_USART_RX_RCU RCU_GPIOA // 串口RX的端口时钟
#define BSP_USART_RCU RCU_USART0 // 串口0的时钟
#define BSP_USART_TX_PORT GPIOA // 串口TX的端口
#define BSP_USART_RX_PORT GPIOA // 串口RX的端口
#define BSP_USART_AF GPIO_AF_1 // 串口0的复用功能
#define BSP_USART_TX_PIN GPIO_PIN_9 // 串口TX的引脚
#define BSP_USART_RX_PIN GPIO_PIN_10 // 串口RX的引脚
#define BSP_USART USART0 // 串口0
#define BSP_USART_IRQ USART0_IRQn // 串口0中断
#define BSP_USART_IRQHandler USART0_IRQHandler // 串口0中断服务函数
/* 串口缓冲区的数据长度 */
#define USART_RECEIVE_LENGTH 4096
extern uint8_t g_recv_buff[]; // 接收缓冲区
extern uint16_t g_recv_length; // 接收数据长度
extern uint8_t g_recv_complete_flag; // 接收完成标志位
void usart_gpio_config(uint32_t band_rate); // 配置串口
void usart_send_data(uint8_t ucch); // 发送一个字符
void usart_send_string(uint8_t *ucstr); // 发送一个字符串
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
在文件bsp_ps2.c中,编写如下代码。
/******************************************************************************
* 测试硬件:立创开发板·GD32E230C8T6 使用主频72Mhz 晶振8Mhz
* 版 本 号: V1.0
* 修改作者: www.lckfb.com
* 修改日期: 2023年11月02日
* 功能介绍:
*****************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:【立创·GD32E230C8T6开发板】模块移植手册
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
******************************************************************************/
#include "bsp_ps2.h"
#include "bsp_usart.h"
#include "stdio.h"
uint8_t Comd[]={0x01,0x42}; //开始命令和请求数据命令
uint8_t Data[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //数据存储数组
//按键值
uint16_t MASK[]={
PSB_SELECT, //SELECT键
PSB_L3, //左遥杆被按下
PSB_R3 , //右遥杆被按下
PSB_START, //START键
PSB_PAD_UP, //上键
PSB_PAD_RIGHT, //右键
PSB_PAD_DOWN, //下键
PSB_PAD_LEFT, //左键
PSB_L2, //左边顶部2键
PSB_R2, //右边顶部2键
PSB_L1, //左边顶部1键
PSB_R1 , //右边顶部1键
PSB_GREEN, //绿色的三角形图案键
PSB_RED, //红色的圆形图案键
PSB_BLUE, //蓝色的X形图案键
PSB_PINK //粉色的矩形图案键
};
/**********************************************************
* 函 数 名 称:PS2_GPIO_Init
* 函 数 功 能:初始化PS2手柄接收端引脚
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
**********************************************************/
void PS2_GPIO_Init(void)
{
/* 使能时钟 */
rcu_periph_clock_enable(RCU_CLK);
rcu_periph_clock_enable(RCU_DAT);
rcu_periph_clock_enable(RCU_CMD);
rcu_periph_clock_enable(RCU_CS);
/* 配置CLK */
gpio_mode_set(PORT_CLK,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_CLK);
gpio_output_options_set(PORT_CLK,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_CLK);
CLK_OUT(1);
/* 配置DI */
gpio_mode_set(PORT_DAT,GPIO_MODE_INPUT,GPIO_PUPD_PULLDOWN,GPIO_DAT);
/* 配置DO */
gpio_mode_set(PORT_CMD,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_CMD);
gpio_output_options_set(PORT_CMD,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_CMD);
/* 配置CS */
gpio_mode_set(PORT_CS,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,GPIO_CS);
gpio_output_options_set(PORT_CS,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,GPIO_CS);
CS_OUT(1);
}
/******************************************************************
* 函 数 名 称:PS2_Cmd
* 函 数 说 明:向手柄发送命令
* 函 数 形 参:CMD要发送的命令
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_Cmd(uint8_t CMD)
{
volatile uint16_t ref=0x01;
Data[] = 0;
for(ref=0x01;ref<0x0100;ref<<=1)
{
CMD_OUT( (ref&CMD) );
CLK_OUT(1); //时钟拉高
delay_us(50);
CLK_OUT(0);
delay_us(50);
CLK_OUT(1);
if( DAT_GET() )
{
Data[] = ref|Data[];
}
}
}
/******************************************************************
* 函 数 名 称:PS2_ReadData
* 函 数 说 明:读取手柄数据
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_ReadData(void)
{
volatile uint8_t byte=0;
volatile uint16_t ref=0x01;
uint16_t i = 0;
CS_OUT(0);
PS2_Cmd(Comd[]); //开始命令
PS2_Cmd(Comd[]); //请求数据
for(byte=2;byte<9;byte++) //开始接受数据
{
for(ref=0x01;ref<0x100;ref<<=1)
{
CLK_OUT(1);
delay_us(10);
CLK_OUT(0);
delay_us(10);
CLK_OUT(1);
if( DAT_GET() )
{
Data[] = ref|Data[];
}
}
delay_us(16);
}
CS_OUT(1);
}
/******************************************************************
* 函 数 名 称:PS2_RedLight
* 函 数 说 明:判断是否为红灯模式
* 函 数 形 参:无
* 函 数 返 回:0:红灯模式 其他:其他模式
* 作 者:LC
* 备 注:0X73=红灯亮的模式 0x41红灯灭的模式
******************************************************************/
uint8_t PS2_RedLight(void)
{
CS_OUT(0);
PS2_Cmd(Comd[]); //开始命令
PS2_Cmd(Comd[]); //请求数据
CS_OUT(1);
if( Data[] == 0X73) return 0 ;
else return 1;
}
/******************************************************************
* 函 数 名 称:PS2_ClearData
* 函 数 说 明:清除数据缓冲区
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_ClearData(void)
{
uint8_t a;
for(a=0;a<9;a++)
Data[]=0x00;
}
//对读出来的PS2的数据进行处理
//只处理了按键部分,默认数据是红灯模式,只有一个按键按下时
//按下为0, 未按下为1
/******************************************************************
* 函 数 名 称:PS2_DataKey
* 函 数 说 明:对读出来的PS2的数据进行处理,处理了按键部分
* 函 数 形 参:无
* 函 数 返 回:0=无按键按下 其他=对应键值,返回的值见数组MASK里的按键
* 作 者:LC
* 备 注:当有按键按下,对应位为“0”,其他位为“1”,
* 例如当键“SELECT”被按下时,Data[]=11111110B。
* 低为在前
******************************************************************/
uint8_t PS2_DataKey(void)
{
uint8_t index=0;
uint16_t Handkey=0;
PS2_ClearData();//清除接收缓存
PS2_ReadData();//读取PS2发送过来的数据
//这是16个按键 按下为0, 未按下为1
Handkey=(Data[]<<8)|Data[];
for(index=0;index<16;index++)
{
if( (Handkey & ( 1 << (MASK[]-1) ) ) ==0 )
{
return index+1;//返回键值
}
}
return 0; //没有任何按键按下
}
/******************************************************************
* 函 数 名 称:PS2_AnologData
* 函 数 说 明:得到一个摇杆的模拟量
* 函 数 形 参:button=摇杆的哪个方向的模拟量,取值范围有:
* PSS_LX 左摇杆左右方向的模拟量
* PSS_LY 左摇杆上下方向的模拟量
* PSS_RX 右摇杆左右方向的模拟量
* PSS_RY 右摇杆上下方向的模拟量
* 函 数 返 回:摇杆的模拟量
* 作 者:LC
* 备 注:范围0~255
******************************************************************/
uint8_t PS2_AnologData(uint8_t button)
{
return Data[];
}
/******************************************************************
* 函 数 名 称:PS2_shortPoll
* 函 数 说 明:手柄配置初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_shortPoll(void)
{
CS_OUT(0);
delay_us(16);
PS2_Cmd(0x01);
PS2_Cmd(0x42);
PS2_Cmd(0x00);
PS2_Cmd(0x00);
PS2_Cmd(0x00);
PS2_Cmd(0x00);
CS_OUT(1);
delay_us(16);
}
/******************************************************************
* 函 数 名 称:PS2_EnterConfing
* 函 数 说 明:PS2进入配置模式
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_EnterConfing(void)
{
CS_OUT(0);
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_OUT(1);
delay_us(16);
}
/******************************************************************
* 函 数 名 称:PS2_TurnOnAnalogMode
* 函 数 说 明:发送模式设置
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_TurnOnAnalogMode(void)
{
CS_OUT(0);
PS2_Cmd(0x01);
PS2_Cmd(0x44);
PS2_Cmd(0X00);
PS2_Cmd(0x01); //analog=Ox01;digital=Ox00软件设置发送模式
PS2_Cmd(0xEE);//Ox03锁存设置,即不可通过按键“MODE”设置模式。
//OxEE不锁存软件设置,可通过按键“MODE”设置模式。
PS2_Cmd(0X00);
PS2_Cmd(0X00);
PS2_Cmd(0X00);
PS2_Cmd(0x00);
CS_OUT(1);
delay_us(16);
}
/******************************************************************
* 函 数 名 称:PS2_VibrationMode
* 函 数 说 明:振动设置
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_VibrationMode(void)
{
CS_OUT(0);
delay_us(16);
PS2_Cmd(0x01);
PS2_Cmd(0x4D);
PS2_Cmd(0X00);
PS2_Cmd(0x00);
PS2_Cmd(0X01);
CS_OUT(1);
delay_us(16);
}
/******************************************************************
* 函 数 名 称:PS2_ExitConfing
* 函 数 说 明:完成并保存配置
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_ExitConfing(void)
{
CS_OUT(0);
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_OUT(1);
delay_us(16);
}
/******************************************************************
* 函 数 名 称:PS2_SetInit
* 函 数 说 明:手柄配置初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void PS2_SetInit(void)
{
PS2_GPIO_Init();//引脚初始化
PS2_shortPoll();
PS2_shortPoll();
PS2_shortPoll();
PS2_EnterConfing();//进入配置模式
PS2_TurnOnAnalogMode();//“红绿灯”配置模式,并选择是否保存
PS2_VibrationMode();
PS2_ExitConfing(); //完成并保存配置
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
在文件bsp_ps2.h中,编写如下代码。
/******************************************************************************
* 测试硬件:立创开发板·GD32E230C8T6 使用主频72Mhz 晶振8Mhz
* 版 本 号: V1.0
* 修改作者: www.lckfb.com
* 修改日期: 2023年11月02日
* 功能介绍:
*****************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:【立创·GD32E230C8T6开发板】模块移植手册
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
******************************************************************************/
#ifndef _BSP_PS2_H
#define _BSP_PS2_H
#include "gd32e23x.h"
#include "systick.h"
//端口移植
#define RCU_CLK RCU_GPIOA
#define PORT_CLK GPIOA
#define GPIO_CLK GPIO_PIN_3
#define RCU_DAT RCU_GPIOA
#define PORT_DAT GPIOA
#define GPIO_DAT GPIO_PIN_0
#define RCU_CMD RCU_GPIOA
#define PORT_CMD GPIOA
#define GPIO_CMD GPIO_PIN_1
#define RCU_CS RCU_GPIOA
#define PORT_CS GPIOA
#define GPIO_CS GPIO_PIN_2
#define CMD_OUT(x) gpio_bit_write(PORT_CMD,GPIO_CMD, (x?SET:RESET))
#define CLK_OUT(x) gpio_bit_write(PORT_CLK,GPIO_CLK, (x?SET:RESET))
#define DAT_GET() gpio_input_bit_get(PORT_DAT,GPIO_DAT)
#define CS_OUT(x) gpio_bit_write(PORT_CS,GPIO_CS, (x?SET:RESET))
/***********************************************************************************/
#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 //X键
#define PSB_PINK 16 //矩形键
#define PSB_TRIANGLE 13
#define PSB_CIRCLE 14
#define PSB_CROSS 15
#define PSB_SQUARE 26
#define PSS_RX 5 //右摇杆X轴数据
#define PSS_RY 6
#define PSS_LX 7
#define PSS_LY 8
void PS2_GPIO_Init(void);
uint8_t PS2_RedLight(void);
uint8_t PS2_DataKey(void);
uint8_t PS2_AnologData(uint8_t button);
void PS2_SetInit(void);
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
移植验证
在自己工程中的main主函数中,编写如下。
/******************************************************************************
* 测试硬件:立创开发板·GD32E230C8T6 使用主频72Mhz 晶振8Mhz
* 版 本 号: V1.0
* 修改作者: www.lckfb.com
* 修改日期: 2023年11月02日
* 功能介绍:
*****************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:【立创·GD32E230C8T6开发板】模块移植手册
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
******************************************************************************/
#include "gd32e23x.h"
#include "systick.h"
#include <stdio.h>
#include "bsp_usart.h"
#include "bsp_ps2.h"
int main(void)
{
uint16_t key = 0;
systick_config(); // 滴答定时器初始化
usart_gpio_config(9600U); // 串口0初始化
//PS2手柄初始化
PS2_SetInit();
printf("start\r\n");
delay_1ms(1000);
while(1)
{
key = PS2_DataKey();//读取是否有按键按下
if( key != 0 )
{
//输出每一个按键被按下后的值
printf("%d down \r\n",key);
}
if( PS2_RedLight() == 0 )//如果当前是红灯模式
{
//输出左右两个遥感的XY值
printf(" %5d %5d %5d %5d\r\n",PS2_AnologData(PSS_LX),PS2_AnologData(PSS_LY),
PS2_AnologData(PSS_RX),PS2_AnologData(PSS_RY) );
}
delay_1ms(100);//防止发送太快,接收器反应不过来
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
移植现象:随意按下按键,都有反应