单片机---HLK-W801移植Nes模拟器(二)

news/2025/2/13 5:53:00/

总目录

《单片机—HLK-W801移植Nes模拟器(一)》
《单片机—HLK-W801移植Nes模拟器(二)》
《单片机—HLK-W801移植Nes模拟器(三)》

前面已经完成了程序的移植,今天试一下按键操作,好歹也能跳一下,吃个蘑菇,也行啊
在这里插入图片描述

按键识别

w801上按键的识别,我这里用的是一个之前用过的全向按键键盘,
在这里插入图片描述通过GPIO的方式采集按键,为了消除抖动,采用了中断定时器循环扫描的方式,连续扫描到8次高电平,认为是按下。
方法参考自博客《#51单片机#中断实现按键消抖》

首先定义一下宏

#define GPIO_UP				WM_IO_PA_01
#define GPIO_DOWN			WM_IO_PA_02
#define GPIO_LFT			WM_IO_PA_08
#define GPIO_RHT			WM_IO_PA_04
#define GPIO_START			WM_IO_PA_05
#define GPIO_A				WM_IO_PA_06
#define GPIO_B				WM_IO_PA_07

然后注册GPIO,

#ifdef GPIO_UPtls_gpio_cfg(GPIO_UP, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
#endif
#ifdef GPIO_DOWNtls_gpio_cfg(GPIO_DOWN, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
#endif
……
#ifdef GPIO_Btls_gpio_cfg(GPIO_B, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
#endif

然后定义一个定时器,每2毫秒就扫描一次按键

void  timer_demo(void)
{u8 timer_id;struct tls_timer_cfg timer_cfg;timer_cfg.unit = TLS_TIMER_UNIT_MS;timer_cfg.timeout = 2;timer_cfg.is_repeat = 1;timer_cfg.callback = (tls_timer_irq_callback)demo_timer_irq;timer_cfg.arg = NULL;timer_id = tls_timer_create(&timer_cfg);tls_timer_start(timer_id);printf("timer start\n");	}

最后实现循环扫描中断函数,这里只写了一个按键作为例子

static void demo_timer_irq(u8 *arg)
{#ifdef GPIO_UP{static unsigned char keybuf_UP = 0XFF;  //扫描缓冲区,保存一段时间内的扫描值。u8 KEY_UP;KEY_UP=tls_gpio_read(GPIO_UP);keybuf_UP = (keybuf_UP<<1)|KEY_UP; //缓冲区左移一位,并将当前扫描值移入最低位。if(keybuf_UP == 0X00){				//连续8次扫描值为0,即16ms内都只检测到按下状态,可认为按键已按下。up_key = 0; }else if(keybuf_UP == 0XFF){				//连续8次扫描值为1,即16ms内都只检测到弹起状态,可认为按键已弹起。up_key = 1;}}#endif
}

最后通过变量up_key ,通知到模拟器。模拟器通过以下函数,循环扫描按键变化

void InfoNES_PadState( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem )

三个参数分别是1P,2P以及开关机按钮,默认的注释


//手柄控制定义,由一个DWORD类型数据表示,手柄1和手柄2定义相同  
//      case Key_Right:
//    pdwPad1 |= (1<<7);  第七位表示 右
//    break;
//  case Key_Left:
//    *pdwPad1 |= (1<<6); 第六位表示左
//    break;
//  case Key_Down:
//    *pdwPad1 |= (1<<5);第五位表示下
//    break;
//  case Key_Up:
//    *pdwPad1 |= (1<<4);第四位表示上
//    break;
//  case Key_S:
//    *pdwPad1 |= (1<<3);第三位表示 Start
//    break;
//  case Key_A:
//    *pdwPad1 |= (1<<2); A键
//    break;
//  case Key_Z: 
//    *pdwPad1 |= (1<<1); Z键
//    break;
//  case Key_X:
//    *pdwPad1 |= (1<<0); X键

这里还是以上键作为例子

#define PAD_JOY_UP		0x10
    *pdwPad1 = 0;
#ifdef GPIO_UPif(up_key){*pdwPad1 |= PAD_JOY_UP;printf("up\n");}
#endif

超级玛丽这款游戏的话,添加上 左右 开始和A键,就可以玩了,没有加速而已。添加好之后,展示效果

请添加图片描述
请添加图片描述
虽然是很卡顿,颜色也不正,但是好歹是走出了第一步。
在这里插入图片描述

颜色问题

估计是在写入SPI的时候,点的颜色与字节序有关系,猜测的没错,颠倒顺序之后,颜色就纯正多了

void ILI9341_DrawLineOne(u16 y,u16* data)
{int i=0;u16* dat=data;ILI9341_Address_Set(0,y,240,y);//设置光标位置 GPIO_DATA();//写数据for(i=0;i<240;i++){uint8_t data[2];data[0] = (*dat)>>8;data[1] = (*dat);tls_spi_write((uint8_t *)data,2);dat++;}}

在这里插入图片描述

不过随之而来的速率更慢了……因为每画一个点,都需要计算颠倒一次数据,再写入SPI。
不过我马上又灵机一动,
假如它想显示AB;
我错了一次,把AB显示成了BA;
那么让nes计算点的时候,也错一次,它要AB的,我就给它BA的,错上加错……
那么我画BA的时候,就会画成AB,那么


画AB目的达到!!!

这叫负负得正!!!

结果还真显示正常了。
修改方法就是,SPI改回原来的直接写一行

void ILI9341_DrawLineOne(u16 y,u16* data)
{int i=0;ILI9341_Address_Set(0,y,240,y);//设置光标位置 GPIO_DATA();//写数据tls_spi_write((uint8_t *)data,480);}

再把调色板的高低位对调

/*-------------------------------------------------------------------*/
/*  Palette data                                                     */
/*-------------------------------------------------------------------*/
WORD NesPalette[64]={
#if 00x738E,0x20D1,0x0015,0x4013,0x880E,0xA802,0xA000,0x7840,0x4140,0x0200,0x0280,0x01C2,0x19CB,0x0000,0x0000,0x0000,0xBDD7,0x039D,0x21DD,0x801E,0xB817,0xE00B,0xD940,0xCA41,0x8B80,0x0480,0x0540,0x0487,0x0411,0x0000,0x0000,0x0000,0xFFDF,0x3DDF,0x5C9F,0x445F,0xF3DF,0xFB96,0xFB8C,0xFCC7,0xF5C7,0x8682,0x4EC9,0x5FD3,0x075B,0x0000,0x0000,0x0000,0xFFDF,0xAF1F,0xC69F,0xD65F,0xFE1F,0xFE1B,0xFDD6,0xFED5,0xFF14,0xE7D4,0xAF97,0xB7D9,0x9FDE,0x0000,0x0000,0x0000,
#else0x8E73,0xD120,0x1500,0x1340,0x0E88,0x02A8,0x00A0,0x4078,0x4041,0x0002,0x8002,0xC201,0xCB19,0x0000,0x0000,0x0000,0xD7BD,0x9D03,0xDD21,0x1E80,0x17B8,0x0BE0,0x40D9,0x41CA,0x808B,0x8004,0x4005,0x8704,0x1104,0x0000,0x0000,0x0000,0xDFFF,0xDF3D,0x9F5C,0x5F44,0xDFF3,0x96FB,0x8CFB,0xC7FC,0xC7F5,0x8286,0xC94E,0xD35F,0x5B07,0x0000,0x0000,0x0000,0xDFFF,0x1FAF,0x9FC6,0x5FD6,0x1FFE,0x1BFE,0xD6FD,0xD5FE,0x14FF,0xD4E7,0x97AF,0xD9B7,0xDE9F,0x0000,0x0000,0x0000,
#endif
};

我还真是个天才
在这里插入图片描述

刷新速率

这个还是在研究中
在这里插入图片描述

结束语

年前工作最后一天,其实对放假也没有什么渴望,听说教主和按住了北鼻离婚了,可能是有人劝说他们中一个,这样的人,不离婚留着过年吗?希望别再因为家产打官司上热搜,看够了这些人了。
在这里插入图片描述


http://www.ppmy.cn/news/330927.html

相关文章

单片机---HLK-W801移植Nes模拟器(三)

总目录 《单片机—HLK-W801移植Nes模拟器&#xff08;一&#xff09;》 《单片机—HLK-W801移植Nes模拟器&#xff08;二&#xff09;》 《单片机—HLK-W801移植Nes模拟器&#xff08;三&#xff09;》 本章重点—优化显示 前两章完成之后&#xff0c;测试了一下刷新速率&am…

移植NES模拟器到STM32G431 详细移植教程 CubeMX HAL库

框架 开发环境移植步骤1.新建工程2.移植NES文件 效果展示程序下载 开发环境 MUC:STM32G431RBT6 板子&#xff1a;蓝桥杯 CT117E_M4 LCD:TFTLCD 2.4寸 注&#xff1a;若使用蓝桥杯 CT117E_M4板子&#xff0c;可以直接烧录该程序使用。 移植步骤 1.新建工程 配置LED、按键IO和…

java按键机nes模拟器_NES 模拟器开发教程 12 - 输入设备

NES 支持许多设备&#xff0c;最常见的还是官方手柄&#xff0c;它有 8 个按键&#xff1a; A B SELECT START UP DOWN LEFT RIGHT 读取的时候比较奇怪&#xff0c;按道理来讲 8 个按键刚好可以用 1 个 byte 表示&#xff0c;读一次就可以了&#xff0c;但是 NES 读取的时候却是…

基于i.mx6q平台的NES模拟器移植

基于i.mx6q平台的NES模拟器移植 小时候一直希望自己能够制作一台游戏机&#xff0c;那时玩的游戏大多都是NES游戏和GBA游戏&#xff0c;那今天就在i.mx6q平台下移植一下NES模拟器吧&#xff0c;后续有时间再移植一下GBA模拟器。下面开始移植NES模拟器。 硬件环境&#xff1a;…

单片机---HLK-W801移植Nes模拟器(一)

总目录 《单片机—HLK-W801移植Nes模拟器&#xff08;一&#xff09;》 《单片机—HLK-W801移植Nes模拟器&#xff08;二&#xff09;》 《单片机—HLK-W801移植Nes模拟器&#xff08;三&#xff09;》 背景介绍 年关将至&#xff0c;不过学习的脚步不能停&#xff0c;最近在…

挖个大坑:挑战用纯micropython写一个nes模拟器(一)

驱动类的micropython程序基本都已经会了&#xff0c;现在给自己挖个大坑&#xff1a;挑战用纯micropython写个nes模拟器。 为啥干这个事儿&#xff0c;其实从小就对模拟器特别又兴趣&#xff0c;很好奇是怎么做到的&#xff0c;在30岁终于动手干了&#xff0c;难度很大&#xf…

嵌入式linux加入nes模拟器,成功运行于 ARM 上的 NES模拟器(InfoNES)

回复: 108 成功运行于 ARM 上的 NES模拟器(InfoNES) (330851310) 出0入0汤圆 楼主| 发表于 2010-11-12 23:19:43 | 只看该作者 程序运行图:

NES模拟器源码阅读

前言 编程语言是一门工具。它用于实现逻辑。看到C实现的任天堂红白机模拟器这篇推荐之后&#xff0c;遂去阅读SimpleNES的源码。 代码中关于日志设置和按键映射的相关代码阅读完毕。关于nes模拟的代码并没有阅读。使用软件来模拟硬件&#xff0c;需要先熟悉游戏机的硬件。这里…