stm32F407-PS手柄代码,20240424

news2024/11/18 1:43:08

一、硬件接线

手柄接收器—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];
}






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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1621303.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# Solidworks二次开发:枚举应用实战(第三讲)

大家好&#xff0c;今天继续介绍枚举相关内容。 下面是今天要介绍的枚举&#xff1a; &#xff08;1&#xff09;第一个为swACisOutputVersion&#xff0c;这个枚举为ACIS的版本&#xff0c;下面是官方的具体解释&#xff1a; 其枚举值为&#xff1a; MemberDescriptionswAc…

git切换源失败解决方案

git切换源失败解决方案 git切换源git切换源失败(无效) git切换源 git可以使用命令行切换源&#xff0c;一般使用的源有两个地址&#xff0c;git原生地址和淘宝镜像地址&#xff0c;部分公司会使用内部地址。 源切换后&#xff0c;npm i就是从源地址拉取相关依赖了。 原生地址…

选择合适的监控观测平台,为业务出海合规建设减负

在全球化商业版图的浩瀚海洋中&#xff0c;企业如同一艘勇敢的船只&#xff0c;突破重重阻碍&#xff0c;勇往直前。在这一征途中&#xff0c;监控观测活动是导航中的指南罗盘&#xff0c;确保企业航向正确、安全稳定&#xff0c;成为企业出海路上维护业务稳定和数据安全的关键…

【论文解析】笔触渲染生成 前沿工作梳理

最近的一些工作梳理 2023年 Stroke-based Neural Painting and Stylization with Dynamically Predicted Painting Region 2022年Im2Oil: Stroke-Based Oil Painting Rendering with Linearly Controllable Fineness Via Adaptive Sampling 文章目录 1 Stroke-based Neural P…

string 类以及模拟实现

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary_walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

【NLP】大语言模型基础之GPT

大语言模型基础之GPT GPT简介1. 无监督预训练2. 有监督下游任务微调 GPT-4体系结构1. GPT-4的模型结构2. GPT-4并行策略3. GPT-4中的专家并行GPT-4的特点 参考连接 以ELMo为代表的动态词向量模型开启了语言模型预训练的大门&#xff0c;此后&#xff0c;出现了以GPT和BERT为代表…

vue中web端播放rtsp视频流(摄像头监控视频)(海康威视录像机)

一、ffmpeg安装​​​​​​ ffmpeg下载 https://ffmpeg.org/download.html找ffmpeg-release-essentials.zip点击下载&#xff0c;下载完解压ffmpeg.exe 程序运行 二、配置ffmpeg环境变量 添加成功后验证是否生效任意地方打开cmd窗口输入 ffmpeg 打印如下表示成功 三、node…

使用IOPaint实现图片擦除路人

IOPaint 是一个免费的开源的 inpainting/outpainting 工具&#xff0c;由最先进的 AI 模型提供支持。 IOPaint 中使用各种模型来修改图像&#xff1a; 擦除&#xff1a;删除任何不需要的物体、缺陷、水印、人物。修复&#xff1a;对图像的特定部分进行修改、添加新对象或替换…

synchronized的底层原理

目录 介绍 实现原理 对象头 Monitor&#xff08;监视器&#xff09; 锁升级 偏向锁 轻量级锁 重量级锁 锁的优缺点 介绍 synchronized 是 Java 中的关键字&#xff0c;它用于锁定代码块或方法&#xff0c;以确保同一时刻只有一个线程可以进入被锁定的部分。这在多线程…

OpenCompass 大模型评测实战——作业

OpenCompass 大模型评测实战——作业 一、基础作业1.1、使用 OpenCompass 评测 internlm2-chat-1_8b 模型在 C-Eval 数据集上的性能1.1.1、安装基本环境1.1.2、解压数据集1.1.3、查看支持的数据集和模型1.1.4、启动评测 二、进阶作业2.1、将自定义数据集提交至OpenCompass官网 …

WPS表格,怎样保留每个人的最近日期的那一行数据?

方法很多&#xff0c;这里演示使用排序删除重复项 来完成。具体操作如下&#xff1a; 1. 选中数据区域中任意一个单元格&#xff0c;注意要么全选数据区域&#xff0c;要么只选一个单元格 2. 点击数据选项卡&#xff0c;排序&#xff0c;自定义排序&#xff0c; 在弹出对话框…

Java | Leetcode Java题解之第42题接雨水

题目&#xff1a; 题解&#xff1a; class Solution {public int trap(int[] height) {int n height.length;if (n 0) {return 0;}int[] leftMax new int[n];leftMax[0] height[0];for (int i 1; i < n; i) {leftMax[i] Math.max(leftMax[i - 1], height[i]);}int[] …

单例设计模式c++

什么是单例模式&#xff1f; 单例模式指在整个系统生命周期里&#xff0c;保证一个类只能产生一个实例&#xff0c;确保该类的唯一性。 单例模式分类 单例模式可以分为懒汉式和饿汉式&#xff0c;两者之间的区别在于创建实例的时间不同&#xff1a; 懒汉式&#xff1a;指系…

德国激荡50年的荆棘之路

财通证券表示&#xff0c;过去50年见证了德国如何走出财政泥沼、以保守的货币政策稳步前行&#xff0c;见证了“专精特新”带来的全球竞争力&#xff0c;也见证了产业转型缓慢导致的增长动能缺失。 过去50年&#xff0c;德国经济经历了一段跌宕起伏的发展史&#xff0c;这辆曾…

2024五一萌趣嘉年华主题展活动策划案

2024五一国宝大作战 萌趣嘉年华熊猫滚滚来野主题展活动策划案-53P 活动策划信息&#xff1a; 方案页码&#xff1a;53页 文件格式&#xff1a;PPT 方案简介&#xff1a; 活动思路&#xff1a; 五一马上就要到了~再加上全民关注的对象--大熊猫&#xff01;&#xff01; 这…

SpringCloud系列(14)--Eureka服务发现(Discovery)

前言&#xff1a;在上一章节中我们说明了一些关于服务信息的配置&#xff0c;在本章节则介绍一些关于Discovery的知识点及其使用 1、Discovery是什么&#xff0c;有什么用 Discovery&#xff08;服务发现&#xff09;是eureka的功能和特性&#xff0c;有时候微服务可能需要对外…

【MATLAB源码-第31期】基于matlab的光通信中不同调制方式的误码率对比。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 光通信&#xff1a; 光通信是一种利用光波传输信息的技术。它使用光信号作为信息的载体&#xff0c;通过调制光波的特性来传输数据&#xff0c;通常利用光纤作为传输介质。光通信具有高带宽、低延迟和大容量等优点&#…

PE结构(二)PE头字段说明

PE头字段 DOS头 PE标记 标准PE头 可选PE头 我们今天分析一下PE头字段中所有重要成员的含义 DOS头 DOS头中我们需要去分析的是如下两个成员&#xff1a; 1.WORD e_magic&#xff1a;MZ标记&#xff0c;用于判断是否为可执行文件&#xff0c;即如果显示4D 5A&#xff0c;…

Centos7 安装zabbix agent2并测试与zabbix server的连通性

目录 1、实验环境 2、yum在线安装 2.1 查看agent2 rpm包&#xff0c;找到合适的rpm包 2.2 rpm安装 2.3 配置zabbix_agent2.conf 2.4启动agent2服务并将其加入到开机启动项中 3、配置防火墙放行10050端口&#xff0c;允许10050/tcp端口的入站流量。 4、在zabbix-server机…

云南旅游攻略

丽江景点 Day1 ——丽江古城 丽江古城是一个充满文化和历史的地方&#xff0c;拥有丰富的景点和活动。 推荐游玩&#xff1a; 参观标志性建筑&#xff1a;大水车是丽江古城的标志性建筑&#xff0c;可以在这里拍照留念。 探索中心广场&#xff1a;四方街是古城的中心&#xf…