
立创开发板*紫韵青衫【NES游戏机】
简介
本项目是基于立创梁山派设计的一款游戏机拓展板,能玩nes游戏。
简介:本项目是基于立创梁山派设计的一款游戏机拓展板,能玩nes游戏。开源协议
:GPL 3.0
描述
前言
这是一款基于立创梁山派设计的游戏机拓展板,官方的叫天魁星,交通灯拓展板叫天罡星,那我做的就叫它天机星吧!哈哈哈!
项目需求
1、具有UI界面,能够通过选择来玩多种游戏。
2、屏幕小巧、亮度可调节。
3、通过喇叭或者插入有线耳机输出声音、振动马达给予使用者一定的反馈。
4、使用摇杆和按键结合的方式获得良好游戏体验。
5、独立电源、Type-C可充电式设计、电量检测以及支持长按开机与长按关机等功能。
器件选择
1、屏幕:
使用1.69寸IPS屏幕
2、耳机孔、喇叭与功放IC:
喇叭需在淘宝购买。
8002A
3、3D摇杆
个人认为这种3D摇杆比官方的手感体验更好些。然后我在淘宝购买了一个摇杆按键帽安装上去。
4、按键
综合考量,这种开关虽然手感上没有官方拓展板的体验那么好,但是这种轻触开关可以安上键帽,显得更好看。
5、EEPROM
M24C02
6、震动马达
7、充电IC
LP4056HSPF
8、升压IC
ME2159AM6G
将锂电池3.7V的电压升压到5V给板子供电。
原理图设计说明
1、MOS开关电路:
长按开机功能:按下START轻触开关时,PMOS管的栅极接低电位导致其源极和漏极导通,相当于开关打开,这时单片机已经上电,为了实现长按开机的效果,当按下时间小于2S时,单片机控制屏幕不亮,且PE6端口输出低电平,只要轻触开关放开,源极和漏极就会截止。单片机断电。当按键按下大于2S时,PE6端口输出高电平,使得S8050三极管发射级与集电极导通,无论按键是否按下,单片机都不会断电。这样就实现了长按开机的功能。
长按关机功能:PE5管脚使用外部中断、上拉输入的形式,当按键按下时,PE5电平被拉低,单片机通过检测按下时间,当按下时间大于设定的阈值,PE6输出低电平,熄灭屏幕,给用户造成关机的感觉,但单片机其实还没断电,当手从按键移开时,PMOS栅极电位拉高,源极和漏极截止,从何实现真正断电。
2、充电电路:
充电IC使用LP4056HSPF,ISET引脚接的2K电阻,通过查找数据手册知这样充电电流为0.5A.STAT1与STAT2引脚在充电时与充电完成输出的电平不同,将两个引脚接到梁山派的相应引脚上可以检测游戏机是否正在充电以及是否充电完成。充电接口使用的是TYPE-C。由于VBAT网络位于PMOS管的源极端,所以无论游戏机电源是否打开,都可以进行充电。
3、升压电路:
升压IC采用ME2159AM6G,将3.7V的电压升到5V给板子供电,当充电时5V_CG网络的电压使MMBT3904三极管集电极与发射极导通,EN引脚置低,升压IC停止升压,这样就可以避免电池与外接电源同时给板子通电的情况发生。采用两个510K电阻的串联分压进行电压检测,如上图,由于VCC网络位于PMOS管的漏极端,所以当关闭游戏机时,ADC电压检测不会存在形成回路而导致放电的现象。
4、按键电路:
为了更方便布线,所以将部分按键引脚做了“非连接”处理。
其余电路设计与官方拓展板基本相同,不做一一赘述。
PCB设计说明
考虑到使用了另一种3D摇杆,这种摇杆的高度比较高,如果仍把屏幕贴在主板子中间,效果可能不是特别好,因此这里把屏幕焊接在另一个小板子上,在通过焊盘将两个板子焊接在一起。
软件说明
1、控制开关机的PE5 PE6引脚的配置代码如下:
void output_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOE);
gpio_mode_set(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,GPIO_PIN_6);
gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6);
}
void On(void)
{
gpio_bit_set(GPIOE,GPIO_PIN_6);//PE6置高,无论按键是否按下,板子都会有供电
}
void Off(void)
{
gpio_bit_reset(GPIOE,GPIO_PIN_6);//PE6置低,手从按键上放开时,板子真正意义上断电
}
void input_EXTI_Init(void)//检测START按键是否按下
{
/* 开启时钟 */
rcu_periph_clock_enable(RCU_GPIOE);
rcu_periph_clock_enable(RCU_SYSCFG);
/* 配置GPIO的模式 */
gpio_mode_set(GPIOE,GPIO_MODE_INPUT,GPIO_PUPD_PULLUP,GPIO_PIN_5);//上拉输入
nvic_irq_enable(EXTI5_9_IRQn,2U,0U);
syscfg_exti_line_config(EXTI_SOURCE_GPIOE,EXTI_SOURCE_PIN5);
exti_init(EXTI_5,EXTI_INTERRUPT,EXTI_TRIG_FALLING);
exti_interrupt_enable(EXTI_5);
exti_interrupt_flag_clear(EXTI_5);
}
2、延迟开机部分:当按下START按键时,先执行Off()函数,延迟2S再执行On()函数,同时亮屏,提示用户松开按键。下面是代码放置的位置:
systick_config();
nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
output_Init();
Off();//按键按下时间小于两秒就移开,板子会断电
delay_1ms(2000);//延迟2S
usart0_init();
adc_config();
adc_bat_init();
key_init();
led_init();
ui_main_set_init();
On();//由于下面的开机logo显示函数里面也有延时部分,实现加载效果,所以On()函数放在这一行执行
ui_main_lcd_init();//开机logo显示
//....省略之间的代码.....//
ui_main_init_show();
input_EXTI_Init();//PE5引脚输入初始化
while(1)
{
//....省略代码.....//
}
当要关闭游戏机时,按下START按键,PE5引脚产生下降沿,程序执行立刻进入外部中断回调函数,具体作用以及代码上文已经涉及,不再赘述,回调函数代码如下:
void EXTI5_9_IRQHandler(void)//中断回调函数
{
if(exti_interrupt_flag_get(EXTI_5) == SET)
{
delay_1ms(20);
if(gpio_input_bit_get(GPIOE,GPIO_PIN_5) == RESET)
{
uint8_t i;
for(i=0;i<10;i++)//2s长按关机,每200ms检测一次
{
delay_1ms(200);
if(gpio_input_bit_get(GPIOE,GPIO_PIN_5) == RESET && i==9)
{
Off();//PE6置低,手从按键上放开时,板子真正意义上断电
LCD_Fill(0,0,240,280,0x0000);//屏幕熄灭,造成关机的现象
while(1);//死循环
}
else if(gpio_input_bit_get(GPIOE,GPIO_PIN_5) == SET)
{
break;//若不符合条件则退出循环
}
}
}
exti_interrupt_flag_clear(EXTI_5);//清除中断标志位
}
}
2、开机LOGO显示与加载效果
LCD_ShowPicture1函数可显示图片,最后一个参数是图片转数组之后的数组名称。
官方的示例程里的开机LOGO是立创开发板的字样,我把他换成了自己设计的图片。
//开机logo显示
void ui_main_lcd_init(void)
{
LCD_Init();
LCD_timer_config();
LCD_ShowPicture1(0,0,LCD_W,LCD_H,START_BMP); //开机logo
LCD_ShowString(((240-strlen("Loading")*12)/2),0,"Loading!",LCEDA,WHITE,24,0);
delay_1ms(1200);
LCD_ShowString(((240-strlen("*Loading!*")*12)/2),0,"*Loading!*",LCEDA,WHITE,24,0);
delay_1ms(900);
LCD_ShowString(((240-strlen("**Loading!**")*12)/2),0,"**Loading!**",LCEDA,WHITE,24,0);
delay_1ms(600);
LCD_ShowString(((240-strlen("***Loading!***")*12)/2),0,"***Loading!***",LCEDA,WHITE,24,0);
delay_1ms(300);
timer_channel_output_pulse_value_config(TIMER2,TIMER_CH_1,50+ui_set.luminance*10);
}
图片转数组可使用一个叫Image2Lcd的软件进行转换:
转换完成后将数组复制粘贴到image.h相应的位置上。
这张图是我设计的开机LOGO
这张图是“关于本机”的内容。所以大家也可以根据自己的喜好导入想显示的图片。
3、显示中文不乱码的方法
由于一开始梁山派板载的SPI Flash里没有中文字库数据,所以运行NES系统时显示中文会乱码,那么这时候就要导入中文字库,第一步:使用一张SD卡(推荐使用32GB的,因为有群友表示选择的SD卡内存过大或过小可能会导致无法识别的现象)。在根目录下新建一个名为font文件夹,将字库文件放在里面;第二步:将其插入到已经下载好NES系统程序的梁山派SD卡槽中,插电启动时它自己就会将字库数据刷到flash里面。之后不管是否插入内存卡,都可以正常显示中文了!
4、优化在未玩游戏时喇叭或者耳机的沙沙声
由于nes游戏的音频输出有一个0x80的直流偏置。如果这个输出到喇叭或耳机的信号有突变,就会导致喇叭有一个非常令人难受的异响,所以可能官方的nes系统的程序为了兼容,在未玩游戏时也对音频输出了0x80的偏置,但这样会造成一个很大的问题,就是会有沙沙声,使体验感不佳,因此,经过我对代码的研究,未进入游戏时,音频信号直接输出零,进入游戏时加入0->0x80,退出游戏时加入0x80->0的信号缓变,这样就可以很好程度的解决沙沙声的问题。
Timer3的初始化音频就输出零,然后Timer3的中断回调函数改的比较多,这部分自己改的屎山代码太长就不贴出来了,其余是一些细节部分,需要可以下载我上传的程序,复制相关内容到自己的代码里。
实物展示
1、3D外壳实物展示
使用了嘉立创三维猴的3D打印,效果很好,表面非常光滑,满满的大赞!
2、面板展示
使用嘉立创EDA的绘制面板功能画了一个面板,发给立创商城进行打印,色彩效果也是非常棒,尺寸也非常对应,无偏差。面板文件在工程里面。
3、游戏机内部展示
4、游戏机整体展示
创新点
1、未采用官方提供的电源模块方案,而是自己设计了MOS管开关电路,搭配充电与升压电路,完成供电的硬件部分,在软件层面加入相关代码,实现了长按开机与长按关机功能,效果很不错。
2、设计了3D外壳与面板,使得PCB有了一个好看的外衣,玩游戏的体验感得到提升。
3、对NES系统的音频部分的代码进行优化,解决了在未玩游戏时的沙沙声问题。
未来的计划
由于最近很忙,未能将游戏的功能变得更加丰富多彩,但我希望在未来能够增加、丰富程序内容,加入有意思的部分,比如听音乐、电子时钟等功能。
致谢
首先十分感谢嘉立创,为我们这些电子爱好者提供了大力的支持,“不以卖板赚钱,以培养中国工程师为己任”,的确,不管是PCB免费打样,还是立创开发板,又或是立创开源硬件平台,都让电子制作低成本化、普及化......为培养中国硬件工程师做出了很大的贡献!
感谢吴工、小许,以及立创商城妮姐,虽然我经常去烦他们,他们还是很热心的为我解答问题,更重要的是他们给我发了券,降低了制作游戏机的成本,哈哈哈!
OK,就这样,前前后后写了好久,终于完成啦!
设计图

BOM


评论