stm32F407-PS手柄代码,20240424

一、硬件接线

手柄接收器—stm32板子
GND—GND
VCC—5V
DAT–F3
CMD–F5
CS–F6
CLK–F4

二、PStwo.h

#ifndef __PSTWO_H
#define __PSTWO_H

//F3 F5 F6 F4 F10
//
#include "delay.h"
#include "sys.h"

#define DI   PFin(3)         //PB12  输入

#define DO_H PFout(5)=1      //命令位高
#define DO_L PFout(5)=0      //命令位低

#define CS_H PFout(6)=1       //CS拉高
#define CS_L PFout(6)=0       //CS拉低

#define CLK_H PFout(4)=1      //时钟拉高
#define CLK_L PFout(4)=0      //时钟拉低

//#define LED0 PFout(7)  // DS0 
//#define LED1 PFout(8)// DS1 

//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      26//方框

//#define WHAMMY_BAR    8
//These are stick values
#define PSS_RX 5                //右摇杆X轴数据
#define PSS_RY 6
#define PSS_LX 7
#define PSS_LY 8

extern 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);	  //清除数据缓冲区

#endif


三、PStwo.c

#include "pstwo.h"
//#include "usart.h"

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
	};	//按键值与按键明

//手柄接口初始化    输入  DI->PF3 
//                  输出  DO->PB13    CS->PB0  CLK->PB1
void PS2_Init(void)
{
	 GPIO_InitTypeDef      GPIO_InitStructure;
	
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	 
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	 GPIO_Init(GPIOF, &GPIO_InitStructure);
	
  	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6| GPIO_Pin_4;//
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//
	 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
	 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//
	 GPIO_Init(GPIOF, &GPIO_InitStructure);//GPIO
	
	GPIO_SetBits(GPIOF,GPIO_Pin_5);  
  GPIO_SetBits(GPIOF,GPIO_Pin_6); 
  GPIO_SetBits(GPIOF,GPIO_Pin_4); 
}

//向手柄发送命令
void PS2_Cmd(u8 CMD)
{
	//volatile是易变型变量,是防止编译器优化代码时假设这个变量的值,保证每次小心地重新读取值。
	volatile u16 ref=0x01;
	u8 i=0,j=0;
	Data[1] = 0;
	//ref的变化是一个八位二进制数中唯一一个1的位置变化,从最低位到最高位移动,从0000 0001到1000 0000。
	for(ref=0x01;ref<0x0100;ref<<=1)//
	{
	//当ref中1的位置对应CMD中得位置上也为1时,结果为1;当ref中1的位置对应CMD中得位置上为0时,结果为0。CMD的其他位则不影响此结果。
		if(ref&CMD)
		{
			DO_H;  //	delay_us(12);
                 //输出以为控制位
		}
		else DO_L;
		//这个结果为1时,DO_H即输出1,这个结果为0时,DO_L即输出0。因此for循环八次,DO的结果就是将CMD的每一位传送了过去。
		
		CLK_H;                        //时钟拉高
		delay_us(100);
		CLK_L;
		delay_us(100);
		CLK_H;    //手动拉出一个下降沿使DO和DI得以同时传送
		/*
		接下来又对接收到的DI进行判断:当DI为1时,运用按位或操作,根据Data[1]初始值为0000 0000,
		以及按位或的定义,不难理解ref | Data[1]得到新的Data[1]的过程是:ref里的唯一的1以值不变
		位置不变的形式给到结果的二进制数中,比如某一次循环Data[1] = 0000 0010,ref = 0000 1000,
		且DI=1,则ref | Data[1]=0000 1010。而这个给1的操作,只有这一bit的DI=1时才会进行;若DI=0,
		则ref只进行1的移位,不给予,但其实也就相当于这一位ref是给予了0给Data[1]。所以其实判断DI并
		执行从句的这一步在整个for循环后的结果即是将8 bit的DI按位保存到Data[1]。		
		*/
		if(DI)  Data[1] = ref|Data[1];//运用或运算按位存入Data[1]的8位
		
		CLK_H;                        //时钟拉高
		delay_us(100);
	}
	
	
	
}
//判断是否为红灯模式
//返回值;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是易变型变量,是防止编译器优化代码时假设这个变量的值,保证每次小心地重新读取值。
	volatile u8 byte=0;
	volatile u16 ref=0x01;

	CS_L;		
	//delay_us(12);


	PS2_Cmd(Comd[0]);  //开始命令
	PS2_Cmd(Comd[1]);  //请求数据

	for(byte=2;byte<9;byte++)          //开始接受数据
	{
		for(ref=0x01;ref<0x0100;ref<<=1)
		{
			CLK_H; delay_us(5);
			CLK_L;
			delay_us(50);
			
		    if(DI)Data[byte] = ref|Data[byte];
			CLK_H; //delay_us(5);
		}
		
        delay_us(50);
	}
	CS_H;			

}
//清除数据缓冲区
void PS2_ClearData()
{
	u8 a;
	for(a=0;a<9;a++)
		Data[a]=0x00;
}

//对读出来的PS2的数据进行处理      只处理了按键部分         默认数据是红灯模式  只有一个按键按下时
//按下为0, 未按下为1
u8 PS2_DataKey()
{
	u8 index;

	PS2_ClearData();
	
	PS2_ReadData();

	Handkey=(Data[4]<<8)|Data[3]; //这是16个按键  按下为0, 未按下为1
	for(index=0;index<16;index++)//循环16次,看哪一个按键被按下
	{	    
		if((Handkey&(1<<(MASK[index]-1)))==0)
		return index+1;
	}
	return 0;          //没有任何按键按下
}

//得到一个摇杆的模拟量	 范围0~256
u8 PS2_AnologData(u8 button)
{
	return Data[button];
}






在这里插入图片描述
四、实物图
在这里插入图片描述
在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值