tag 标签: 手柄

相关博文
  • 热度 20
    2013-3-21 22:17
    2413 次阅读|
    1 个评论
    第三十三章  游戏手柄实验 相信80后小时候都有玩过FC游戏机(又称:红白机/小霸王游戏机),那是一代经典,给我们的童年带了了无限乐趣。本章,我们将向大家介绍如何通过STM32来驱动FC游戏机手柄,将FC游戏机的手柄作为战舰STM32开发板的输入设备(综合实验可以直接通过这个手柄来玩FC游戏)。 在本章中,我们将使用STM32驱动FC手柄,将手柄的按键键值等信息通过TFTLCD模块显示出来。本章分为如下几个部分: 33.1 游戏手柄简介 33.2 硬件设计 33.3 软件设计 33.4 下载验证 33.1游戏手柄简介 FC游戏机曾今是一统天下(现在也还是很多人玩),红极一时,那时任天堂单是FC机的主机的发售收入就超过全美国的电视台的收入的总和。本章,我们将使用STM32来驱动FC手柄,实现手柄控制信号的读取,我们先来了解一下FC手柄。        FC手柄,大致可分为两种:一种手柄插口是11针的,一种是9针的。但11针的现在市面上很少了(因为11针手柄是早期FC组装兼容机最主要的周边),现在几乎都是9针FC组装手柄的天下,所以我们本章使用的是9针FC手柄,该手柄还有一个特点,就是可以直接和DR9的串口头对插!这样同开发板的连接就简单了。FC手柄的外观如图33.1.1所示:     图33.1.1 FC手柄外观图        这种手柄一般有10个按键(实际是8个键值):上、下、左、右、Start、Select、A、B、A连发、B连发。这里的A和A连发是一个键值,而B和B连发也是一个键值,只是连发按键当你一直按下的时候,会不停的发送(方便快速按键,比如发炮弹之类的功能)。 FC手柄的控制电路,由1个8位并入串出的移位寄存器(CD4021),外加一个时基集成电路(NE555,用于连发)构成。不过现在的手柄,为了节约成本,直接就在PCB上做绑定了,所以你拆开手柄,一般是看不到里面有四四方方的IC,而只有一个黑色的小点,所有电路都集成到这个里面了,但是他们的控制和读取方法还是一样的。 9针手柄的读取时序和接线图如图33.1.2所示:     图33.1.2 FC手柄读取时序和接线图        从上图可看出,读取手柄按键值的信息十分简单:先Latch(锁存键值),然后就得到了第一个按键值(A),之后在Clock的作用下,依次读取其他按键的键值,总共8个按键键值。        有了以上了解,我们就可以通过STM32的IO来驱动FC手柄了。 33.2 硬件设计 本实验采用STM32的3个普通IO连接FC手柄的Clock、Data和Latch信号,本章实验功能简介:在主函数不停的查询手柄输入,一旦检测到输入信号,则在LCD模块上面显示键值和对应的按键符号。同样我们也是用LED0来指示程序正在运行。 所要用到的硬件资源如下: 1)  指示灯DS0 2) TFTLCD模块 3)  FC手柄 前两个,在之前的实例已经介绍过了,FC手柄属于外部器件。战舰STM32开发板板载了一个FC手柄接口(就是一个DR9接头,在开发板上标号为JOY_PAD),该接口与MCU的连接原理图如33.2.1所示:      图33.2.1 FC手柄接头与STM32的连接电路图 图中,JOY_PAD就是用来连接FC手柄的,该接头采用标准的DR9座,战舰STM32开发板上有2个DR9座,一个用来接FC手柄(有JOY_PAD字样,LCD左上),另外一个用来接RS232串口(有COM字样,LCD右上), 这两个头千万不要接错!否则可能烧坏手柄或者烧坏 STM32 。 从上图我们知道,手柄的CLK(Clock)、LAT(Latch)和DAT(Data)分别连接在STM32的PC12、PC8和PC9上面,这里与SDIO部分信号线共用了,所以当使用SDIO的时候,就不能使用FC手柄了。因为信号线都是直连的,所以我们在开发板上不需要做配置,只需要将FC手柄插入JOY_PAD插口即可。 开发板配套的手柄,见图33.1.1。 33.3 软件设计 打开上一章的工程,首先在HARDWARE文件夹下新建一个REMOTE的文件夹。然后新建一个joypad.c和joypad.h的文件保存在JOYPAD文件夹下,并将这个文件夹加入头文件包含路径。 打开joypad.c文件,输入如下代码: #include "joypad.h" //初始化手柄接口. void JOYPAD_Init(void) {       RCC-APB2ENR|=14;//先使能外设PORTC时钟             GPIOC-CRH=0XFFF0FF00;        GPIOC-CRH|=0X00030083;            GPIOC-ODR|=38;        GPIOC-ODR|=112; } //读取手柄按键值. //FC手柄数据输出格式: //每给一个脉冲,输出一位数据,输出顺序: //A-B-SELECT-START-UP-DOWN-LEFT-RIGHT. //总共8位,对于有C按钮的手柄,按下C其实就等于A+B同时按下. //按下是0,松开是1. //返回值: // :右 // :左 // :下 // :上 // :Start // :Select // :B // :A u8 JOYPAD_Read(void) {        u8 temp=0;        u8 t;        JOYPAD_LAT=1;                              //锁存当前状态       JOYPAD_LAT=0;        for(t=0;t8;t++)        {               temp=1;                   if(JOYPAD_DAT)temp|=0x01;     //LOAD之后,就得到第一个数据               JOYPAD_CLK=1;                     //每给一次脉冲,收到一个数据              JOYPAD_CLK=0;         }        return temp; } 该部分代码仅2个函数,都比较简单,JOYPAD_Init函数用于初始化IO,即把PC8、PC9和PC12设置为正确的状态,以便同FC手柄通信。另外一个函数JOYPAD_Read就是按照图33.1.2所示的时序读取FC手柄,该函数的返回值就是手柄的状态。 保存joypad.c,然后把该文件加入HARDWARE组下。接下来打开joypad.h在该文件里面加入如下代码: #ifndef __JOYPAD_H #define __JOYPAD_H   #include "sys.h" //手柄连接引脚 #define JOYPAD_CLK PCout(12)      //时钟            PC9 #define JOYPAD_LAT PCout(8)        //锁存        PC8 #define JOYPAD_DAT PCin(9)         //数据        PC12    void JOYPAD_Init(void);                   //初始化 u8 JOYPAD_Read(void);                    //读取键值                                    #endif 这部分代码就不介绍了,我们保存joypad.h,然后在test.c里面修改主函数如下: const u8*JOYPAD_SYMBOL_TBL = {"Right","Left","Down","Up","Start","Select","A","B"};//手柄按键符号定义 int main(void) {                   u8 key;        u8 t=0,i=0;                  Stm32_Clock_Init(9);    //系统时钟设置        uart_init(72,9600);      //串口初始化为9600        delay_init(72);                  //延时初始化        LED_Init();                //初始化与LED连接的硬件接口        LCD_Init();                  //初始化LCD        usmart_dev.init(72);      //初始化USMART               JOYPAD_Init();            //手柄初始化       POINT_COLOR=RED;//设置字体为红色        LCD_ShowString(60,50,200,16,16,"WarShip STM32");           LCD_ShowString(60,70,200,16,16,"JOYPAD TEST");             LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");        LCD_ShowString(60,110,200,16,16,"2012/9/12");      LCD_ShowString(60,130,200,16,16,"KEYVAL:");              LCD_ShowString(60,150,200,16,16,"SYMBOL:");                POINT_COLOR=BLUE;//设置字体为红色        while(1)        {               key=JOYPAD_Read();               if(key!=0XFF)               {                      LCD_ShowNum(116,130,key,3,16);//显示键值                      for(i=0;i8;i++)                      {                             if((key(1                             {                                    LCD_Fill(60+56,150,60+56+48,150+16,WHITE);//清除之前的显示                                    LCD_ShowString(60+56,150,200,16,16,(u8*) JOYPAD_SYMBOL_TBL ); //显示符号                             }                                 }                              }              delay_ms(10);               t++;               if(t==20)               {                      t=0;                      LED0=!LED0;               }        } } 此部分代码也比较简单,初始化JOYPAD之后,就一直扫描FC手柄(通过JOYPAD_Read函数实现),然后只要接收到手柄的有效信号,就在LCD模块上面显示出来。 至此,我们的软件设计部分就结束了。 33.4下载验证 在代码编译成功之后,我们通过下载代码到ALIENTEK战舰STM32开发板上,可以看到LCD显示如图33.4.1所示的内容:     图33.4.1程序运行效果图 此时我们按下FC手柄的按键,则可以看到LCD上显示了对应按键的键值以及对应的符号。如图33.4.2所示:     图33.4.2解码游戏手柄数据成功   ))==0)      
相关资源