找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6637|回复: 7
收起左侧

PS2手柄控制4个灯闪的STM32程序源码

[复制链接]
ID:321034 发表于 2018-8-30 20:45 | 显示全部楼层 |阅读模式
索尼的 PS2游戏手柄, 通过上下左右4个按键来控制 单片机的4个灯亮灭。  同时 也可以控制 游戏手柄的震动

串口打印

串口打印

0.jpg

源程序如下:
  1. # include "public.h"
  2. # include "printf.h"
  3. # include "systick.h"
  4. # include "ps2.h"
  5. # include "led.h"


  6. int main()
  7. {        
  8.         u8 key;
  9.         LED_Init();
  10.         printf_init();        //printf串口初始化
  11.         PS2_Init();
  12.         led_display();
  13.         //PS2_SetInit();                 //配配置初始化,配置“红绿灯模式”,并选择是否可以修改
  14.                              //开启震动模式
  15.                 printf(" 已开启游戏手柄\r\n");        
  16.         /*
  17.         while(1)
  18.         {
  19.                 key=PS2_DataKey();
  20.                 if(key!=0)                   //有按键按下
  21.             {
  22.                         printf("  \r\n   %d  is  light  \r\n",Data[1]);//ID
  23.                         printf("  \r\n   %d  is  pressed  \r\n",key);
  24.                         if(key == 11)
  25.                         {
  26.                                 PS2_Vibration(0xFF,0x00);  //发出震动后必须有延时  delay_ms(1000);
  27.                                 delay_ms(500);
  28.                         }
  29.                         else if(key == 12)
  30.                         {
  31.                                 PS2_Vibration(0x00,0xFF);  //发出震动后必须有延时  delay_ms(1000);
  32.                                 delay_ms(500);
  33.                         }
  34.                         else
  35.                                  PS2_Vibration(0x00,0x00);
  36.             }
  37.                 printf(" %5d %5d %5d %5d\r\n",PS2_AnologData(PSS_LX),PS2_AnologData(PSS_LY),
  38.                                               PS2_AnologData(PSS_RX),PS2_AnologData(PSS_RY) );
  39.                 delay_ms(60000);
  40.         }         
  41. */        
  42.         while (1)
  43.         {
  44.                 key=PS2_DataKey();
  45.                 if(key!=0)                   //有按键按下
  46.                 {
  47.                                         printf("  \r\n   %d  is  light  \r\n",Data[1]);//ID
  48.                                         printf("  \r\n   %d  is  pressed  \r\n",key);
  49.                                         if(key == 5)
  50.                                         {
  51.                                                 printf(" 按键向上 !\r\n");
  52.                                                 led1();
  53.                                         }
  54.                                         else if(key == 7)
  55.                                         {
  56.                                                 printf(" 按键向下 !\r\n");
  57.                                                 led2();
  58.                                         }
  59.                                         else if(key == 6)
  60.                                         {
  61.                                                 printf(" 按键向右 !\r\n");
  62.                                                 led3();
  63.                                         }
  64.                                         else if(key == 8)
  65.                                         {
  66.                                                 printf(" 按键向左 !\r\n");
  67.                                                 led4();
  68.                                         }
  69.                                         printf(" 输入成功!\r\n");
  70.           }
  71.                 delay_us(60000);
  72.         }
  73.         
  74. }



复制代码
  1. #include "ps2.h"
  2. #include "systick.h"


  3. u16 Handkey;        // 按键值读取,零时存储。
  4. u8 Comd[2]={0x01,0x42};        //开始命令。请求数据
  5. u8 Data[9]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //数据存储数组
  6. u16 MASK[]={
  7.     PSB_SELECT,
  8.     PSB_L3,
  9.     PSB_R3 ,
  10.     PSB_START,
  11.     PSB_PAD_UP,
  12.     PSB_PAD_RIGHT,
  13.     PSB_PAD_DOWN,
  14.     PSB_PAD_LEFT,
  15.     PSB_L2,
  16.     PSB_R2,
  17.     PSB_L1,
  18.     PSB_R1 ,
  19.     PSB_GREEN,
  20.     PSB_RED,
  21.     PSB_BLUE,
  22.     PSB_PINK
  23.         };        //按键值与按键明

  24. //手柄接口初始化    输入  DI->PB12
  25. //                  输出  DO->PB13    CS->PB14  CLK->PB15
  26. void PS2_Init(void)
  27. {                
  28.   GPIO_InitTypeDef  GPIO_InitStructure;

  29.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能GPIOF时钟

  30.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
  31.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//普通输出模式
  32.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  33.   GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
  34.          
  35.        
  36.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
  37.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//普通输出模式
  38.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz
  39.   GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
  40. }

  41. //向手柄发送命令
  42. void PS2_Cmd(u8 CMD)
  43. {
  44.         volatile u16 ref=0x01;
  45.         Data[1] = 0;
  46.         for(ref=0x01;ref<0x0100;ref<<=1)
  47.         {
  48.                 if(ref&CMD)
  49.                 {
  50.                         DO_H;                   //输出一位控制位
  51.                 }
  52.                 else DO_L;

  53.                 CLK_H;                        //时钟拉高
  54.                 delay_us(10);
  55.                 CLK_L;
  56.                 delay_us(10);
  57.                 CLK_H;
  58.                 if(DI)
  59.                         Data[1] = ref|Data[1];
  60.         }
  61.         delay_us(16);
  62. }
  63. //判断是否为红灯模式,0x41=模拟绿灯,0x73=模拟红灯
  64. //返回值;0,红灯模式
  65. //                  其他,其他模式
  66. u8 PS2_RedLight(void)
  67. {
  68.         CS_L;
  69.         PS2_Cmd(Comd[0]);  //开始命令
  70.         PS2_Cmd(Comd[1]);  //请求数据
  71.         CS_H;
  72.         if( Data[1] == 0X73)   return 0 ;
  73.         else return 1;

  74. }
  75. //读取手柄数据
  76. void PS2_ReadData(void)
  77. {
  78.         volatile u8 byte=0;
  79.         volatile u16 ref=0x01;
  80.         CS_L;
  81.         PS2_Cmd(Comd[0]);  //开始命令
  82.         PS2_Cmd(Comd[1]);  //请求数据
  83.         for(byte=2;byte<9;byte++)          //开始接受数据
  84.         {
  85.                 for(ref=0x01;ref<0x100;ref<<=1)
  86.                 {
  87.                         CLK_H;
  88.                         delay_us(10);
  89.                         CLK_L;
  90.                         delay_us(10);
  91.                         CLK_H;
  92.                       if(DI)
  93.                       Data[byte] = ref|Data[byte];
  94.                 }
  95.         delay_us(16);
  96.         }
  97.         CS_H;
  98. }

  99. //对读出来的PS2的数据进行处理,只处理按键部分  
  100. //只有一个按键按下时按下为0, 未按下为1
  101. u8 PS2_DataKey()
  102. {
  103.         u8 index;

  104.         PS2_ClearData();
  105.         PS2_ReadData();

  106.         Handkey=(Data[4]<<8)|Data[3];     //这是16个按键  按下为0, 未按下为1
  107.         for(index=0;index<16;index++)
  108.         {            
  109.                 if((Handkey&(1<<(MASK[index]-1)))==0)
  110.                 return index+1;
  111.         }
  112.         return 0;          //没有任何按键按下
  113. }

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

  119. //清除数据缓冲区
  120. void PS2_ClearData()
  121. {
  122.         u8 a;
  123.         for(a=0;a<9;a++)
  124.                 Data[a]=0x00;
  125. }
  126. /******************************************************
  127. Function:    void PS2_Vibration(u8 motor1, u8 motor2)
  128. Description: 手柄震动函数,
  129. Calls:                 void PS2_Cmd(u8 CMD);
  130. Input: motor1:右侧小震动电机 0x00关,其他开
  131.            motor2:左侧大震动电机 0x40~0xFF 电机开,值越大 震动越大
  132. ******************************************************/
  133. void PS2_Vibration(u8 motor1, u8 motor2)
  134. {
  135.         CS_L;
  136.         delay_us(16);
  137.     PS2_Cmd(0x01);  //开始命令
  138.         PS2_Cmd(0x42);  //请求数据
  139.         PS2_Cmd(0X00);
  140.         PS2_Cmd(motor1);
  141.         PS2_Cmd(motor2);
  142.         PS2_Cmd(0X00);
  143.         PS2_Cmd(0X00);
  144.         PS2_Cmd(0X00);
  145.         PS2_Cmd(0X00);
  146.         CS_H;
  147.         delay_us(16);  
  148. }
  149. //short poll
  150. void PS2_ShortPoll(void)
  151. {
  152.         CS_L;
  153.         delay_us(16);
  154.         PS2_Cmd(0x01);  
  155.         PS2_Cmd(0x42);  
  156.         PS2_Cmd(0X00);
  157.         PS2_Cmd(0x00);
  158.         PS2_Cmd(0x00);
  159.         CS_H;
  160.         delay_us(16);       
  161. }
  162. //进入配置
  163. void PS2_EnterConfing(void)
  164. {
  165.     CS_L;
  166.         delay_us(16);
  167.         PS2_Cmd(0x01);  
  168.         PS2_Cmd(0x43);  
  169.         PS2_Cmd(0X00);
  170.         PS2_Cmd(0x01);
  171.         PS2_Cmd(0x00);
  172.         PS2_Cmd(0X00);
  173.         PS2_Cmd(0X00);
  174.         PS2_Cmd(0X00);
  175.         PS2_Cmd(0X00);
  176.         CS_H;
  177.         delay_us(16);
  178. }
  179. //发送模式设置
  180. void PS2_TurnOnAnalogMode(void)
  181. {
  182.         CS_L;
  183.         PS2_Cmd(0x01);  
  184.         PS2_Cmd(0x44);  
  185.         PS2_Cmd(0X00);
  186.         PS2_Cmd(0x01); //analog=0x01;digital=0x00  软件设置发送模式
  187.         PS2_Cmd(0xEE); //Ox03锁存设置,即不可通过按键“MODE”设置模式。
  188.                                    //0xEE不锁存软件设置,可通过按键“MODE”设置模式。
  189.         PS2_Cmd(0X00);
  190.         PS2_Cmd(0X00);
  191.         PS2_Cmd(0X00);
  192.         PS2_Cmd(0X00);
  193.         CS_H;
  194.         delay_us(16);
  195. }
  196. //振动设置
  197. void PS2_VibrationMode(void)
  198. {
  199.         CS_L;
  200.         delay_us(16);
  201.         PS2_Cmd(0x01);  
  202.         PS2_Cmd(0x4D);  
  203.         PS2_Cmd(0X00);
  204.         PS2_Cmd(0x00);
  205.         PS2_Cmd(0X01);
  206.         CS_H;
  207.         delay_us(16);       
  208. }
  209. ……………………

  210. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

全部资料51hei下载地址:
PS2 震动+上下左右按键.rar (910.7 KB, 下载次数: 68)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:321034 发表于 2018-8-30 20:46 | 显示全部楼层
发错了  不好意思
回复

使用道具 举报

ID:321034 发表于 2018-8-30 20:47 | 显示全部楼层
源程序 是这个,上面那个发错了
#include "delay.h"
#include "sys.h"
#include "pwm.h"
# include "ps2.h"
# include "stdio.h"


int main(void)
{       
         u8 angle;
         PS2_Init();
         delay_init();                     //延时函数初始化          

                  //TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
           //选择定时器模式:TIM脉冲宽度调制模式2
        TIM1_PWM_Init(199,7199);//不分频。PWM频率===(7200*200)/72000000=0.02=20ms
         
  while(1)
        {
                PS2_ClearData();   //清除缓存
                PS2_ReadData();           //读数据
                angle = (PS2_AnologData(PSS_RX)/5)*3+15;  //只产生15°~165°的运动范围
                SERVO1(angle);
                delay_ms(50);
    }
}

回复

使用道具 举报

ID:405033 发表于 2019-2-25 20:19 | 显示全部楼层
楼楼能否解答一下,这个手柄该怎么与单片机接线,我的手柄上有5个接口,vcc,gnd,VRX,VRY,SW,这些该怎么接线,用的是mini版的stm32
回复

使用道具 举报

ID:485634 发表于 2019-3-6 15:33 | 显示全部楼层
学习一下
回复

使用道具 举报

ID:302850 发表于 2019-5-24 15:19 来自手机 | 显示全部楼层
标记一下,这个可能会用到
回复

使用道具 举报

ID:544885 发表于 2019-5-24 16:13 | 显示全部楼层
共享代码的人是值得尊敬的人
回复

使用道具 举报

ID:554410 发表于 2019-6-10 16:49 | 显示全部楼层
楼主,最近还在看stm32和ps2么
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表