原创 【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第三十三章 FC游戏手柄控实验

2013-3-21 22:17 2377 19 20 分类: MCU/ 嵌入式 文集: STM32学习

第三十三章  游戏手柄实验

相信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|=1<<4;//先使能外设PORTC时钟     

       GPIOC->CRH&=0XFFF0FF00;

       GPIOC->CRH|=0X00030083;    

       GPIOC->ODR|=3<<8;

       GPIOC->ODR|=1<<12;

}

//读取手柄按键值.

//FC手柄数据输出格式:

//每给一个脉冲,输出一位数据,输出顺序:

//A->B->SELECT->START->UP->DOWN->LEFT->RIGHT.

//总共8位,对于有C按钮的手柄,按下C其实就等于A+B同时按下.

//按下是0,松开是1.

//返回值:

//[0]:右

//[1]:左

//[2]:下

//[3]:上

//[4]:Start

//[5]:Select

//[6]:B

//[7]:A

u8 JOYPAD_Read(void)

{

       u8 temp=0;

       u8 t;

       JOYPAD_LAT=1;                              //锁存当前状态

      JOYPAD_LAT=0;

       for(t=0;t<8;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[8]=

{"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;i<8;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)<>

 

 

 

文章评论1条评论)

登录后参与讨论

用户1777005 2014-8-15 13:24

学习了哈哈哈
相关推荐阅读
正点原子 2013-05-17 23:47
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第六十一章 战舰STM32开发板综合实验(标准例程终结篇)
   第六十一章 战舰STM32开发板综合实验        前面已经给大家讲了55个实例了,本章将设计一个综合实例,作为本指南的最后一个实验 ,该实验向大家展示了STM...
正点原子 2013-05-03 23:02
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第六十章 UCOSII实验3-消息队列、信号量集和软件定时器
   第六十章 UCOSII实验3-消息队列、信号量集和软件定时器   上一章,我们学习了UCOSII的信号量和邮箱的使用,本章,我们将学习消息队列、信号量集和软件定时器...
正点原子 2013-05-03 20:42
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
第五十七章 ENC28J60网络实验   本章,我们将向大家介绍ALIENTEK ENC28J60网络模块及其使用。本章,我们将使用ALIENTEK ENC28J60网络模块...
正点原子 2013-05-01 23:00
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十九章 UCOSII实验2-信号量和邮箱
第五十九章 UCOSII实验2-信号量和邮箱      上一章,我们学习了如何使用UCOSII,学习了UCOSII的任务调度,但是并没有用到任务间的同步与通信,本章我们将学习两个最基本的...
正点原子 2013-04-30 10:55
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十八章 UCOSII实验1-任务调度
  第五十八章 UCOSII实验1-任务调度      前面我们所有的例程都是跑的裸机程序(裸奔),从本章开始,我们将分3个章节向大家介绍UCOSII(实时多任务操作系...
正点原子 2013-04-26 23:16
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
 第五十七章 ENC28J60网络实验  本章,我们将向大家介绍ALIENTEK ENC28J60网络模块及其使用。本章,我们将使用ALIENTEK ENC28J60网络模块和uIP 1...
我要评论
1
19
关闭 站长推荐上一条 /2 下一条