本帖最后由 xcc521 于 2019-4-3 23:14 编辑

先上图

ScreenCut003.png (8.39 KB, 下载次数: 0)

2019-4-1 00:58 上传

ScreenCut004.png (7.29 KB, 下载次数: 0)

2019-4-1 00:58 上传

使用触摸屏检测作为手柄数据输入

之前还尝试过NRF24L1无线手柄(见这里 http://www.openedv.com/forum.php?mod=viewthread&tid=278263&extra=)以及自己写的APP使用蓝牙连接

0DCGRV[ES(NX}UG~X7({G3T.png (234.31 KB, 下载次数: 0)

2019-4-1 00:58 上传

7EMVA`S}BM({FDU9]@GU5}K.png (174.16 KB, 下载次数: 0)

2019-4-1 00:58 上传

947EE`1VGJ8WWN~H{AWUY.jpg (189.69 KB, 下载次数: 1)

2019-4-1 00:58 上传

Screenshot_2019-04-01-00-27-43-299_xdtech.joystic.png (82.57 KB, 下载次数: 0)

2019-4-1 00:58 上传

Screenshot_2019-04-01-00-27-49-053_xdtech.joystic.png (146.82 KB, 下载次数: 0)

2019-4-1 00:58 上传

Screenshot_2019-04-01-00-28-00-980_com.android.se.png (82.67 KB, 下载次数: 0)

2019-4-1 00:58 上传

Screenshot_2019-04-01-00-28-25-494_xdtech.joystic.png (91.93 KB, 下载次数: 0)

2019-4-1 00:58 上传

Screenshot_2019-04-01-00-28-36-472_xdtech.joystic.png (158.93 KB, 下载次数: 0)

2019-4-1 00:58 上传

蓝牙模块连接串口3,安卓APP发送字符表示按键

//读取游戏手柄数据

void nes_get_gamepadval(void)

{

if(USART3_RX_STA & 0x08000)

{

//printf("usart3 data:%s\r\n",USART3_RX_BUF);

if(USART3_RX_BUF[0] == 'A')

{

PADdata0 |= 0x10;

}

else

{

PADdata0 &= ~0x10;

}

if(USART3_RX_BUF[1] == 'B')

{

PADdata0 |= 0x20;

}

else

{

PADdata0 &= ~0x20;

}

if(USART3_RX_BUF[2] == 'C')

{

PADdata0 |= 0x40;

}

else

{

PADdata0 &= ~0x40;

}

if(USART3_RX_BUF[3] == 'D')

{

PADdata0 |= 0x80;

}

else

{

PADdata0 &= ~0x80;

}

if(USART3_RX_BUF[4] == 'E')

{

PADdata0 |= 0x01;

}

else

{

PADdata0 &= ~0x01;

}

if(USART3_RX_BUF[5] == 'F')

{

PADdata0 |= 0x02;

}

else

{

PADdata0 &= ~0x02;

}

if(USART3_RX_BUF[6] == 'G')

{

PADdata0 |= 0x04;

}

else

{

PADdata0 &= ~0x04;

}

if(USART3_RX_BUF[7] == 'H')

{

PADdata0 |= 0x08;

}

else

{

PADdata0 &= ~0x08;

}

USART3_RX_STA = 0;

}

//PADdata0=JOYPAD_Read();        //读取手柄1的值

//PADdata1=0;                                //没有手柄2,故不采用.

}

注意运行NES的时候倍频需要修改串口3的设置

void usart3_fast_init(u32 pclk2,u32 bound)

{

NVIC_InitTypeDef NVIC_InitStructure;

float temp;

u16 mantissa;

u16 fraction;

temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV

mantissa=temp;                                 //得到整数部分

fraction=(temp-mantissa)*16; //得到小数部分

mantissa<<=4;

mantissa+=fraction;

RCC->APB2ENR|=1<<3;           //使能PORTB口时钟

GPIOB->CRH&=0XFFFF00FF;        //IO状态设置

GPIOB->CRH|=0X00008B00;        //IO状态设置

RCC->APB1ENR|=1<<18;          //使能串口时钟

RCC->APB1RSTR|=1<<18;   //复位串口3

RCC->APB1RSTR&=~(1<<18);//停止复位

//波特率设置

USART3->BRR=mantissa; // 波特率设置

USART3->CR1|=0X200C;  //1位停止,无校验位.

#if EN_USART1_RX                  //如果使能了接收

//使能接收中断

USART3->CR1|=1<<5;            //接收缓冲区非空中断使能2

NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;                //子优先级3

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能

NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器

#endif

TIM7_Int_Init(99,7199);                //10ms中断

USART3_RX_STA=0;                //清零

TIM_Cmd(TIM7,DISABLE);                        //关闭定时器7

}

安卓负责连接蓝牙监听按钮状态

class mImageListenter implements View.OnTouchListener

{

@Override

public boolean onTouch(View view,MotionEvent motionEvent)

{

// TODO Auto-generated method stub

switch (motionEvent.getAction())

{

case MotionEvent.ACTION_DOWN:

case MotionEvent.ACTION_MOVE:

if (view.getId() == R.id.im_joy_a_mode)

{

send_data[4] = 'E';

}

if (view.getId() == R.id.im_joy_b)

{

send_data[1] = 'B';

}

if (view.getId() == R.id.im_joy_b_mode)

{

send_data[5] = 'F';

}

if (view.getId() == R.id.im_joy_f)

{

send_data[0] = 'A';

}

if (view.getId() == R.id.im_joy_l)

{

send_data[2] = 'C';

}

if (view.getId() == R.id.im_joy_r)

{

send_data[3] = 'D';

}

if (view.getId() == R.id.im_joy_sel)

{

send_data[6] = 'G';

}

if (view.getId() == R.id.im_joy_sta)

{

send_data[7] = 'H';

}

break;

case MotionEvent.ACTION_UP:

if (view.getId() == R.id.im_joy_a_mode)

{

send_data[4] = '0';

}

if (view.getId() == R.id.im_joy_b)

{

send_data[1] = '0';

}

if (view.getId() == R.id.im_joy_b_mode)

{

send_data[5] = '0';

}

if (view.getId() == R.id.im_joy_f)

{

send_data[0] = '0';

}

if (view.getId() == R.id.im_joy_l)

{

send_data[2] = '0';

}

if (view.getId() == R.id.im_joy_r)

{

send_data[3] = '0';

}

if (view.getId() == R.id.im_joy_sel)

{

send_data[6] = '0';

}

if (view.getId() == R.id.im_joy_sta)

{

send_data[7] = '0';

}

break;

default:

break;

}

return true;

}

}

如此就可以控制NES游戏了

转回主题,使用触摸屏控制

首先创建界面

_btn_obj * tbtn_game[8];                //总共8个按钮

void load_ctr_ui(void)

{

u16 button_w,button_h,W,H;

uint8_t rval=0;

uint8_t i;

if(lcddev.width == 480)

{

button_w = 60;

button_h = 40;

}

else

{

button_w = 30;

button_h = 18;

}

W = (lcddev.width - button_w * 6) / (6 + 1);//计算缝隙宽度

H = (lcddev.height  - 552 - button_h * 3) / (3 + 1);//计算缝隙高度

tbtn_game[0]=btn_creat(button_w * 1 + W * 2, 552 + button_h * 0 + H * 1,button_w,button_h,0,0x02);        //创建按钮

tbtn_game[1]=btn_creat(button_w * 1 + W * 2, 552 + button_h * 2 + H * 3,button_w,button_h,1,0x02);        //创建按钮

tbtn_game[2]=btn_creat(button_w * 0 + W * 1, 552 + button_h * 1 + H * 2,button_w,button_h,2,0x02);        //创建按钮

tbtn_game[3]=btn_creat(button_w * 2 + W * 3, 552 + button_h * 1 + H * 2,button_w,button_h,3,0x02);        //创建按钮

tbtn_game[4]=btn_creat(button_w * 4 + W * 5, 552 + button_h * 0 + H * 1,button_w,button_h,4,0x02);        //创建按钮

tbtn_game[5]=btn_creat(button_w * 4 + W * 5, 552 + button_h * 2 + H * 3,button_w,button_h,5,0x02);        //创建按钮

tbtn_game[6]=btn_creat(button_w * 3 + W * 4, 552 + button_h * 1 + H * 2,button_w,button_h,6,0x02);        //创建按钮

tbtn_game[7]=btn_creat(button_w * 5 + W * 6, 552 + button_h * 1 + H * 2,button_w,button_h,7,0x02);        //创建按钮

for(i=0;i<8;i++)

{

if(tbtn_game==NULL)

{

rval=1;

break;

}

tbtn_game->bcfucolor=BLACK;//松开时为黑色

tbtn_game->bcfdcolor=WHITE;//按下时为白色

tbtn_game->bkctbl[0]=0X453A;//边框颜色

tbtn_game->bkctbl[1]=0X5DDC;//第一行的颜色

tbtn_game->bkctbl[2]=0X5DDC;//上半部分颜色

tbtn_game->bkctbl[3]=0X453A;//下半部分颜色

if(i==0)tbtn_game->caption="Select";

if(i==1)tbtn_game->caption="Start";

if(i==2)tbtn_game->caption="Left";

if(i==3)tbtn_game->caption="Right";

if(i==4)tbtn_game->caption="Up";

if(i==5)tbtn_game->caption="Down";

if(i==6)tbtn_game->caption="A";

if(i==7)tbtn_game->caption="B";

}

if(rval==0)//无错误

{

for(i=0;i<8;i++)btn_draw(tbtn_game);        //画按钮

}

}

创建就有删除,所以

void delete_ctr_ui(void)

{

uint8_t i;

for(i=0;i<8;i++)

btn_delete(tbtn_game);//删除按钮

}

然后是检测按键逻辑

uint8_t get_ctr_res(void)

{

uint8_t res = 0,i,val = 0;

tp_dev.scan(0);

in_obj.get_key(&tp_dev,IN_TYPE_TOUCH);        //得到按键键值

for(i=0;i<8;i++)

{

res=game_btn_check(tbtn_game,&in_obj);//确认按钮检测

if(res)

{

if((tbtn_game->sta&0X80)==0)//有有效操作

{

switch(i)

{

case 0:

val |= 1 << 2;

break;

case 1:

val |= 1 << 3;

break;

case 2:

val |= 1 << 6;

break;

case 3:

val |= 1 << 7;

break;

case 4:

val |= 1 << 4;

break;

case 5:

val |= 1 << 5;

break;

case 6:

val |= 1 << 0;

break;

case 7:

val |= 1 << 1;

break;

}

}

}

}

return val;

}

game_btn_check本来用的是之前的btn_check,但是不支持实时监测,于是修改成了

static uint8_t game_btn_check(_btn_obj * btnx,void * in_key)

{

_in_obj *key=(_in_obj*)in_key;

uint8_t btnok=0;

if((btnx->sta&0X03)==BTN_INACTIVE)return 0;//无效状态的按键,直接不检测

switch(key->intype)

{

case IN_TYPE_TOUCH:        //触摸屏按下了

if(btnx->topy&&key->ytop+btnx->height)&&btnx->leftx&&key->xleft+btnx->width))//在按键内部

{

btnx->sta&=~(0X03);

btnx->sta|=BTN_PRESS;//按下

//btn_draw(btnx);//画按钮  屏蔽重绘按钮,严重影响帧数

btnok=1;

}else

{

btnx->sta&=~(0X03);

btnx->sta|=BTN_RELEASE;        //松开

//btn_draw(btnx);                        //画按钮

}

break;

default:

break;

}

return btnok;

}

主循环

LCD_Set_Window(0,0,lcddev.width,lcddev.height);//恢复屏幕窗口用于更新屏幕按键状态以及显示文字

nes_get_gamepadval();        //每3帧查询一次USB

nes_set_window();//因为检测屏幕按键时候更新了按钮状态所以需要重新设置窗口

apu_soundoutput();                //输出游戏声音

这样折腾了一晚上就可以按触摸屏一直输出按钮值,不然的话每一次查询按键都要手动点一次放开根本跟不上

但是又发现了个问题,就是按钮值无法组合,也就是只能检测任一个按键,不能多按键同时检测,本来以为就是其中的8个按钮都单独调用一次扫描触屏函数就会好,但是一想每次检测的应该还是第一个按下的坐标,这可能就得需要扫描多点触摸时的坐标了,嗯,暂时就是这样想的,后面再从底层重写扫描函数吧,快一点了,睡觉,哈哈哈

蓝牙手柄APP.zip

(1.84 MB, 下载次数: 10)

2019-4-1 00:58 上传

点击文件名下载附件

IMG_20190401_000056.jpg (2.83 MB, 下载次数: 0)

2019-4-3 23:13 上传

IMG_20190401_000125.jpg (2.93 MB, 下载次数: 0)

2019-4-3 23:14 上传

好奇怪附件会乱

android 开源fc模拟器_战舰开发板触摸屏运行NES模拟器相关推荐

  1. RISC-V 嵌入式 Rust 快速入门,基于 Renode 模拟器和 HiFive1 开发板

    配置开发环境 这里以 Ubuntu 18.04 作为宿主环境,其它 Linux 发行版类似.Windows 环境待更新. 安装标准 Rust 编译器 wget https://cdn.jsdelivr ...

  2. android 测试工具,Android开源项目第四篇:开发及测试工具篇

    本文为那些不错的Android开源项目第四篇--开发工具篇,**主要介绍Android开发工具和测试工具相关的开源项目**. Android开源项目系列汇总已完成,包括: 1.Buck faceboo ...

  3. 【开源分享】自制STC15W408AS开发板

    [开源分享]自制STC15W408AS开发板 实物图: 和Arduino UNO板子尺寸差不多 开源平台:立创EDA 立创eda主页链接:https://oshwhub.com/perseveranc ...

  4. *基于RT-Thread的战舰开发板连接Onenent云平台(学习笔记)**

    基于RT-Thread的战舰开发板连接Onenent云平台(学习笔记) 摘要:本文主要是我在使用正点原子开发板在rt_thread框架下连接onenet云平台的学习笔记.此文主要介绍配置步骤和开发过程 ...

  5. 正点原子mysql_正点原子战舰开发板硬件原理图与PCB

    [实例简介] 正点原子的STM32F103新战舰开发板的硬件原理图与PCB,且PCB含三维元器件封装. [实例截图] [核心代码] 1d489e5a-fad4-4456-aeb8-6225947162 ...

  6. 【PCB开源分享】STC32G12K128/STC8H8K64U开发板

    [PCB开源分享]STC32G12K128/STC8H8K64U开发板 相关开源项目<[开源]STC单片机免冷启动自动下载器> <[PCB开源分享]STC8A8K64D4开发板> ...

  7. 基于STM32战舰开发板的USMART调试组件的使用

    基于STM32战舰开发板的USMART调试组件的使用 USMART调试组件是什么? USMART是正点原子团队为其STM32开发平台开发的一种类似linux的shell的调试工具.具体工作过程是通过串 ...

  8. 在VIM3开发板上运行无修改的iOS内核镜像

    在VIM3开发板上运行无修改的iOS内核镜像 之前在网上有看到过人使用QEMU成功的把IOS内核运行起来且成功挂载根文件系统的相关文章.理论上能在QEMU上跑成功,在真实的ARMv8开发板上运行起来也 ...

  9. 在Developerkit开发板上运行blink例程

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 本文将介绍怎么样在VScode环境下,将AliOS Tings提供的blink例程在Developerkit开发板上运 ...

最新文章

  1. 麻省理工选出的全球十大突破性技术
  2. Christopher Manning​:Uber 出售自动驾驶部门是一个标志性事件​ | AI日报
  3. 教你解决ChartDirector Linux下中文乱码
  4. 【ABAP】销售订单Billing Plan创建
  5. 银行业务软件测试,银行业务软件系统测试研究
  6. HTML5 required是必填
  7. Dubbo Mesh 在闲鱼生产环境中的落地实践
  8. 启动之后自己关闭_电脑怎么关闭自动更新
  9. 使用CMake与VS2012编译OpenCV3.3.0版本
  10. 修改node_modules的包
  11. 【总结】实现点击累加效果的几种方式对比
  12. sql server高可用_SQL Server 2019常规可用性和安装概述
  13. Asp.net.Ajax控件学习
  14. Internet Download Manager互联网下载管理器(简称IDM)无广告弹窗,速度起飞,你值得拥有
  15. 软件编码测试要点总结
  16. JavaScript 如何导出 Excel
  17. ubuntu 键盘输入法为空_Ubuntu12下键盘输入中文设置 - 卡饭网
  18. Invalid row number (65536) outside allowable range (0..65535)
  19. 超级经典的人生格言(搞笑)
  20. 关于netty的@Sharable注解含义,你可bie瞎说了

热门文章

  1. FPGA接MIPI接口sensor
  2. Kubernetes 二进制部署 多节点(基于单节点部署,超详细)3
  3. E11:后台管理系统开发-实现删除文章功能
  4. ansys19.0--联轴器建模
  5. PS显示暂存盘已满情况解决
  6. pcb成型板aoi检测_AOI在PCB检测中的应用
  7. ADC0809仿真-LCD602及数码管显示
  8. 【视频】面试一年大厂经验Java程序员,回答不是很满意与18KOffer失之交臂 生活日常
  9. 关于我想写个脚本,最后却搞了个桌面宠物这件事(三)
  10. 保安日记:前端学习第八篇之HTML5