ps2 手柄由手柄與接收器兩部分組成,手柄主要負責發送按鍵信
息;接收器與單片機(也可叫作主機,可直接用在PS2 游戲機上)
相連,用于接收手柄發來的信息,并傳遞給單片機,單片機也可通過
接收器,向手柄發送命令,配置手柄的發送模式。
時鐘頻率250KHz(4us),如果接收數據不穩定,可以適當的增加頻率。在通訊過程中,一串數據通訊完成后CS 才會由低轉高,不是1 個字節通訊完成后就由低轉高,在通訊期間,一直處于低電平。在時鐘下降沿時,完成數據(1bit)的發送與接收,發送和接收是同時完成的。當單片機想讀手柄數據或向手柄發送命令時,將會拉低CS 線電平,并發出一個命令“0x01”;手柄會回復它的ID“0x41=綠燈模式,0x73=紅燈模式”;在手柄發送ID 的同時,單片機將傳送0x42,請求數據;隨后手柄發送出0x5A,告訴單片機“數據來了”。
idle:數據線空閑,該數據線無數據傳送。
一個通訊周期有9 個字節(8 位),這些數據是依次按位傳送。
當有按鍵按下,對應位為“0”,其他位為“1”,例如當鍵“SELECT”被按下時,Data[3]=11111110B。
需自己根據實際情況修改IO口
#.c文件
#include "pstwo.h"
/********************************************************* **********************************************************/
#define DELAY_TIME delay_us(5);
float PS2_LX,PS2_LY,PS2_RX,PS2_RY,PS2_KEY; //PS2相關變量
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
};
/************************************************************************** 函數功能:PS2手柄初始化 入口參數:無 返回 值:無 **************************************************************************/
void PS2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOB, ENABLE); //使能端口時鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //上拉輸入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M
GPIO_Init(GPIOD, &GPIO_InitStructure); //根據設定參數初始化GPIOD
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // inpuT
GPIO_Init(GPIOE, &GPIO_InitStructure); //根據設定參數初始化GPIOE
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13; //端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M
GPIO_Init(GPIOB, &GPIO_InitStructure); //根據設定參數初始化GPIOE
}
/************************************************************************** 函數功能:向手柄發送命令 入口參數:CMD指令 返回 值:無 **************************************************************************/
void PS2_Cmd(u8 CMD)
{
volatile u16 ref=0x01;
Data[1] = 0;
for(ref=0x01;ref<0x0100;ref<<=1)
{
if(ref&CMD)
{
DO_H; //輸出一位控制位
}
else DO_L;
CLK_H; //時鐘拉高
DELAY_TIME;
CLK_L;
DELAY_TIME;
CLK_H;
if(DI)
Data[1] = ref|Data[1];
}
delay_us(16);
}
/************************************************************************** 函數功能:判斷是否為紅燈模式,0x41=模擬綠燈,0x73=模擬紅燈 入口參數:CMD指令 返回 值: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 u8 byte=0;
volatile u16 ref=0x01;
CS_L;
PS2_Cmd(Comd[0]); //開始命令
PS2_Cmd(Comd[1]); //請求數據
for(byte=2;byte<9;byte++) //開始接受數據
{
for(ref=0x01;ref<0x100;ref<<=1)
{
CLK_H;
DELAY_TIME;
CLK_L;
DELAY_TIME;
CLK_H;
if(DI)
Data[byte] = ref|Data[byte];
}
delay_us(16);
}
CS_H;
}
/************************************************************************** 函數功能:對讀出來的PS2的數據進行處理,只處理按鍵部分 入口參數:CMD指令 返回 值:無 //只有一個按鍵按下時按下為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++)
{
if((Handkey&(1<<(MASK[index]-1)))==0)
return index+1;
}
return 0; //沒有任何按鍵按下
}
/************************************************************************** 函數功能:向手柄發送命令 入口參數:得到一個搖桿的模擬量 范圍0~256 返回 值:無 **************************************************************************/
u8 PS2_AnologData(u8 button)
{
return Data[button];
}
//清除數據緩沖區
void PS2_ClearData()
{
u8 a;
for(a=0;a<9;a++)
Data[a]=0x00;
}
/****************************************************** 函數功能: 手柄震動函數, Calls: void PS2_Cmd(u8 CMD); 入口參數: motor1:右側小震動電機 0x00關,其他開 motor2:左側大震動電機 0x40~0xFF 電機開,值越大 震動越大 返回 值:無 ******************************************************/
void PS2_Vibration(u8 motor1, u8 motor2)
{
CS_L;
delay_us(16);
PS2_Cmd(0x01); //開始命令
PS2_Cmd(0x42); //請求數據
PS2_Cmd(0X00);
PS2_Cmd(motor1);
PS2_Cmd(motor2);
PS2_Cmd(0X00);
PS2_Cmd(0X00);
PS2_Cmd(0X00);
PS2_Cmd(0X00);
CS_H;
delay_us(16);
}
/************************************************************************** 函數功能:short poll 入口參數:無 返回 值:無 **************************************************************************/
void PS2_ShortPoll(void)
{
CS_L;
delay_us(16);
PS2_Cmd(0x01);
PS2_Cmd(0x42);
PS2_Cmd(0X00);
PS2_Cmd(0x00);
PS2_Cmd(0x00);
CS_H;
delay_us(16);
}
/************************************************************************** 函數功能:進入配置 入口參數:無 返回 值:無 **************************************************************************/
void PS2_EnterConfing(void)
{
CS_L;
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_H;
delay_us(16);
}
/************************************************************************** 函數功能:發送模式設置 入口參數:無 返回 值:無 **************************************************************************/
void PS2_TurnOnAnalogMode(void)
{
CS_L;
PS2_Cmd(0x01);
PS2_Cmd(0x44);
PS2_Cmd(0X00);
PS2_Cmd(0x01); //analog=0x01;digital=0x00 軟件設置發送模式
PS2_Cmd(0x03); //Ox03鎖存設置,即不可通過按鍵“MODE”設置模式。
//0xEE不鎖存軟件設置,可通過按鍵“MODE”設置模式。
PS2_Cmd(0X00);
PS2_Cmd(0X00);
PS2_Cmd(0X00);
PS2_Cmd(0X00);
CS_H;
delay_us(16);
}
/************************************************************************** 函數功能:振動設置 入口參數:無 返回 值:無 **************************************************************************/
void PS2_VibrationMode(void)
{
CS_L;
delay_us(16);
PS2_Cmd(0x01);
PS2_Cmd(0x4D);
PS2_Cmd(0X00);
PS2_Cmd(0x00);
PS2_Cmd(0X01);
CS_H;
delay_us(16);
}
/************************************************************************** 函數功能:完成并保存配置 入口參數:無 返回 值:無 **************************************************************************/
void PS2_ExitConfing(void)
{
CS_L;
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_H;
delay_us(16);
}
/************************************************************************** 函數功能:手柄配置初始化 入口參數:無 返回 值:無 **************************************************************************/
void PS2_SetInit(void)
{
PS2_ShortPoll();
PS2_ShortPoll();
PS2_ShortPoll();
PS2_EnterConfing(); //進入配置模式
PS2_TurnOnAnalogMode(); //“紅綠燈”配置模式,并選擇是否保存
//PS2_VibrationMode(); //開啟震動模式
PS2_ExitConfing(); //完成并保存配置
}
/************************************************************************** 函數功能:讀取PS2手柄的控制量 入口參數:無 返回 值:無 **************************************************************************/
void PS2_Read(void)
{
static int Start, count=0;
PS2_KEY=PS2_DataKey(); //讀取按鍵鍵值
PS2_LX=PS2_AnologData(PSS_LX); //讀取左邊遙感X軸方向的模擬量
PS2_LY=PS2_AnologData(PSS_LY); //讀取左邊遙感Y軸方向的模擬量
PS2_RX=PS2_AnologData(PSS_RX); //讀取右邊遙感X軸方向的模擬量
PS2_RY=PS2_AnologData(PSS_RY); //讀取右邊遙感Y軸方向的模擬量
}
#.h文件
#ifndef __PSTWO_H
#define __PSTWO_H
#include "delay.h"
#include "sys.h"
#include "init.h"
/********************************************************* **********************************************************/
#define DI PEin(15) // 輸入引腳
#define DO_H PDout(3)=1 //命令位高
#define DO_L PDout(3)=0 //命令位低
#define CS_H PBout(13)=1 //CS拉高
#define CS_L PBout(13)=0 //CS拉低
#define CLK_H PBout(12)=1 //時鐘拉高
#define CLK_L PBout(12)=0 //時鐘拉低
//手柄接口初始化 輸入 DI->PA0
// 輸出 DO->PA1 CS->PA2 CLK->PA3
//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 16
//#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;
extern float PS2_LX,PS2_LY,PS2_RX,PS2_RY,PS2_KEY; //PS2相關變量
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); //清除數據緩沖區
void PS2_Vibration(u8 motor1, u8 motor2);//振動設置motor1 0xFF開,其他關,motor2 0x40~0xFF
void PS2_EnterConfing(void); //進入配置
void PS2_TurnOnAnalogMode(void); //發送模擬量
void PS2_VibrationMode(void); //振動設置
void PS2_ExitConfing(void); //完成配置
void PS2_SetInit(void); //配置初始化
void PS2_Read(void); //讀取PS2手柄的控制量
#endif
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
華縣隸屬安陽市。1.河南省直管縣華縣位于河南省北部,與濮陽、安陽、鶴壁、新鄉接壤。南距鄭州130公里,北距安陽70公里,東北距濮陽53公里,西南距新鄉70公里。2.滑縣位于河南省北部平原,隸屬安陽市。目前是省直管縣,與濮陽、演金、??h、長垣、封丘、內黃接壤。北距安陽70km,東北距濮陽53km,西南距新鄉70km,西北距鶴壁新城25km。河南的滑縣屬于哪個市?河南省直管縣滑縣?;h是河南省直屬縣,...
縱觀LOL歷屆S系列賽,哪一屆奪冠的含金量最高?哪一屆又最低?S1來自歐洲的FNC。當時隊伍不多。S2來自臺灣的TPA,在勝利面前擊敗熱火,急于奪冠。來自韓國的S3 SKT,faker的首次亮相是巔峰。魔王用他可怕的行動殺戮并將刀子壓在繩子上完成了統治之路?;始襆PL獲得第二名。來自韓國SSW的S4,前四名擊潰兄弟隊SSB,奪冠勢不可擋。LPL王室再次失利,獲得第二名。三星解散后,三星世子進入LP...
excle表格如何查找重復姓名?在excel表格中,通過在條件格式中突出顯示單元規則,可以找出重復的名稱。這里以excel 2013版本為例。具體方法如下:1.首先,在電腦上打開要找出重名的Excel表格。2.然后選擇頁面頂部的條件格式。3.接下來,單擊突出顯示單元格規則。4.進入高亮顯示的單元格規則頁面后,選擇復制項目。5.然后在彈出的頁面中選擇【確定】,在excwps怎么搜索人名?在wps表中...