一、PS2 手柄介绍:
PS2 由手柄与接收器两部分组成,手柄主要负责发送按键信息。都接通电源并打开手柄开关时,手柄与接收器自动配对连接(这是由于手柄与接收器之间依靠2.4G进行通信),在未配对成功的状态下,接收器绿灯闪烁,手柄上的灯也会闪烁,配对成功后,接收器上绿灯常亮,手柄上灯也常亮,这时可以按“MODE”键,选择手柄发送模式,红灯模式:遥杆输出模拟值;绿灯模式:遥杆对应上面四个按键,只有四个极限方向对应。
接收器和主机(单片机)相连,实现主机与手柄之间的通讯。
亚博智能给的又是用STM32F103C8T6,标准库的代码。这还是我从平衡小车那里弄来的源码,原本给的用来测试的源码还是用寄存器写的。然后以下是移植到STM32F407ZGT6基于HAL库的记录。
引脚定义
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|
DI/DAT | DO/CMD | NC | GND | VDD | CS/SEL | CLK | NC | ACK |
NC我合理猜测是空端口
二、编程实验
cube
GPIO
将三个GPIO口设置为推挽输出模式,一个设置为下拉输入模式。三个GPIO_Output的引脚分别对应MISO、CS和SCK,GPIO_Input的引脚对应的是MOSI。
USART
串口初始化
keil
主函数中初始化PS2
在while(1)中读取手柄按键
void PS2_Init(void)
{
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
/*Configure GPIO pins : PD0 PD1 PD2 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : PD3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2, GPIO_PIN_SET);
}
将IO口的初始化写在这里是为了方便之后的移植
unsigned char PS2_DataKey()
{
uint8_t index = 0, i = 0;
PS2_ClearData();
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_1,GPIO_PIN_RESET);
for(i=0;i<9;i++) //更新扫描按键
{
Data[i] = PS2_ReadData(scan[i]);
}
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_1,GPIO_PIN_SET);
Handkey=(Data[4]<<8)|Data[3]; //这是16个按键 按下为0, 未按下为1
for(index=0;index<16;index++)
{
if((Handkey&(1<<(MASK[index]-1)))==0)
return index+1;
}
return 0; //没有任何按键按下
}
对串口数据收发相关的把信号线,时钟线进行拉高拉低的操作我没有进行封装,主要是懒。
uint8_t PS2_ReadData(uint8_t command)
{
uint8_t i,j=1;
uint8_t res=0;
for(i=0; i<=7; i++)
{
if(command&0x01)
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_0,GPIO_PIN_SET);
else
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_0,GPIO_PIN_RESET);
command = command >> 1;
delay_us(10);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
delay_us(10);
if(HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_3) )
res = res + j;
j = j << 1;
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
delay_us(10);
}
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_0,GPIO_PIN_SET) ;
delay_us(50);
return res;
}
记得这里的读数据延时是微秒级别的
三、实验结果
反正就是成功了