ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于ESP32-P4自制复古掌机:硬件选型、PCB设计与RetroGo移植实战

基于ESP32-P4自制复古掌机:硬件选型、PCB设计与RetroGo移植实战 1. 为什么我选择用ESP32-P4折腾一台复古掌机去年年底看到乐鑫发布ESP32-P4这颗芯片的时候我第一反应不是拿它做HMI或者做边缘网关而是想把它塞进一台掌机里。原因很简单这颗芯片有MIPI-DSI接口、有RGB LCD控制器、有双核RISC-V 400MHz主频、还带硬件JPEG解码这些特性堆在一起跑一个复古游戏模拟器前端简直是量身定做。之前用ESP32-S3做过一版屏幕刷新率和音频延迟始终差口气P4出来之后我就知道该换平台了。这篇文章要聊的是我从零开始做一台基于ESP32-P4的复古掌机的完整过程。包括硬件选型思路、PCB设计里踩过的坑、RetroGo系统的移植和适配、ST7789V屏幕驱动的调参、以及最终用ESP-Flasher烧录固件的实操细节。适合有嵌入式基础、会画PCB、想自己动手做一台掌机的朋友参考。如果你只是想知道ESP32-P4能不能跑模拟器答案是可以而且跑得比你想的好。整台机器的定位是能流畅跑NES、GB、GBC、SMS、部分SNES和Genesis游戏屏幕用3.5寸320x240的ST7789V电池用单节18650带充电管理外壳3D打印。成本控制在200块以内PCB打样用嘉立创元器件全部立创商城可采购。2. 硬件方案设计与核心器件选型2.1 ESP32-P4为什么适合做掌机主控先说说为什么选P4而不是其他方案。市面上做复古掌机的方案大概几类全志F1C200s、树莓派Zero、ESP32-S3、还有各种STM32专用视频芯片的组合。F1C200s跑Linux确实方便但启动慢、功耗高、PCB复杂度上一个台阶。树莓派Zero更不用说体积和功耗都不适合手持设备。ESP32-S3我实际用过240MHz双核跑NES没问题但SNES就吃力了而且SPI屏幕刷新率上不去撕裂感明显。ESP32-P4的核心优势在于MIPI-DSI和RGB接口可以直接驱动RGB接口的TFT屏不占用SPI带宽刷新率轻松上60fps双核RISC-V 400MHz比S3的Xtensa 240MHz强了不止一个档次模拟器帧率稳定硬件JPEG解码虽然游戏模拟用不到但RetroGo的封面显示用得上512KB SRAM 可选PSRAM跑模拟器需要大量RAM做帧缓冲和ROM加载P4支持外挂PSRAMUSB 2.0 OTG可以直接做USB设备方便传ROM和调试实际选型时我对比了P4和S3的模拟器性能。以NES为例S3跑Nofrendo大概能到50-60fps但不稳定P4跑同样的核心基本锁60fps而且CPU占用率只有40%左右。SNES用Snes9x2005核心S3大概20-30fpsP4能到45-55fps配合跳帧可以玩。这个差距主要来自主频和内存带宽。2.2 屏幕选型ST7789V vs RGB屏屏幕这块我纠结了很久。ST7789V是SPI接口的3.5寸320x240 IPS屏优点是驱动简单、引脚少、资料多、便宜大概25块。缺点是SPI带宽有限即使超频到80MHz全屏刷新也就30fps左右而且SPI传输占用CPU时间。RGB接口的屏比如ILI9488或者ST7701S刷新率能上60fps但需要大量IO口RGB565需要16根数据线控制线PCB布线复杂度高而且P4的RGB接口引脚是固定的布局受限。最终我选了ST7789V原因有三个一是RetroGo对SPI屏有优化用了DMA传输和双缓冲实际游戏体验可以接受二是PCB走线简单四层板就能搞定三是成本低坏了换屏不心疼。如果你追求更好的显示效果可以上RGB屏但PCB要重新设计本文的方案不直接适用。ST7789V的驱动要点后面会详细讲这里先提一句这块屏的初始化序列有很多版本不同厂家的面板参数不一样直接用公版初始化可能会偏色或者显示区域不对。2.3 电源管理SW6206方案解析电源部分我用的是SW6206这颗芯片它是一颗集成度很高的移动电源管理IC支持升压、充电管理、电量显示、按键控制。选它的理由很简单单节18650供电需要升压到5V给屏幕背光和USB外设同时要给ESP32-P4供3.3V还要有充电管理。如果用分立方案至少需要升压IC充电ICLDO三颗芯片SW6206一颗全搞定。SW6206的关键参数输入5V支持最大2A充电电流升压输出5V/2.4A内置电量计支持4颗LED指示支持边充边放QFN封装占板面积小实际使用中需要注意的是SW6206的升压效率大概在85%左右18650 3000mAh的电池实际可用容量大概2500mAh。掌机整机功耗在1.5W左右屏幕背光占大头续航大概4-5小时够用了。注意SW6206的PCB布局很关键电感要靠近芯片反馈走线要远离电感否则输出纹波会很大影响屏幕显示。2.4 其他关键器件按键用的是普通的轻触开关方向键用五向摇杆或者四个独立按键都行我用的独立按键手感更接近原版GB。音频用PAM8302功放8欧1W喇叭P4的I2S输出直接接功放。存储用TF卡SPI模式存ROM和存档。USB接口用Type-C只做供电和烧录不做OTG。3. PCB设计实战从原理图到打样3.1 原理图设计要点原理图这块我用的嘉立创EDA主要是方便直接对接打样和元器件采购。整个原理图分几个模块电源管理、主控、屏幕接口、按键、音频、存储。电源部分的原理图要注意几点SW6206的使能引脚要接按键实现短按开机、长按关机。电池电压检测要接到P4的ADC引脚用于低电量提示。充电指示灯和电量指示灯要引出到面板。主控部分ESP32-P4的引脚分配要提前规划好。我用的是ESP32-P4-Function-EV-Board的引脚定义作为参考但实际画板时重新分配了。关键引脚包括SPI屏幕SCLK、MOSI、CS、DC、RST、BLKI2S音频BCLK、LRCLK、DATATF卡SPI模式共用屏幕的SPI总线用不同的CS按键6个GPIO用内部上拉USBD、D-提示P4的GPIO有复用限制有些引脚在启动时有特殊功能画原理图前一定要查数据手册的引脚定义表避免用了启动时必须为高或者为低的引脚。3.2 PCB布局思路PCB布局我采用的是“主板屏幕转接板”的方案。主板尺寸大概80x50mm屏幕转接板单独做用FPC排线连接。这样做的原因是屏幕的FPC连接器不好焊单独做转接板可以降低焊接难度而且屏幕坏了换起来方便。主板的布局原则电源模块放在板子一侧远离模拟音频部分ESP32-P4放在中间天线区域净空TF卡座放在板边方便插拔按键放在板子边缘对应外壳的开孔位置音频功放靠近喇叭接口输入走线要短PCB叠层用四层板顶层信号、第二层地、第三层电源、底层信号。四层板的好处是地平面完整SPI和I2S的信号完整性好而且嘉立创四层板打样现在很便宜没必要省这个钱。3.3 布线规则与避坑经验布线这块我踩了不少坑说几个关键的SPI屏幕走线SCLK和MOSI要等长尽量短远离电源电感。ST7789V虽然对时序要求不严但走线太长会导致EMI问题屏幕出现噪点。我第一版走线大概10cm屏幕就有轻微闪烁第二版缩短到5cm以内就正常了。电源走线SW6206的升压输出电流大走线宽度至少1mm最好铺铜。电感到芯片的走线要短而粗反馈线要从输出电容后面取不要从电感后面取。晶振和天线P4的外置晶振要靠近芯片走线包地。天线区域所有层都要净空不要走线不要铺铜。按键走线按键信号线要加RC滤波否则抖动会导致误触发。我用的10k上拉100nF电容到地效果很好。TF卡走线SPI模式虽然速度不快但CLK线还是要远离模拟信号。TF卡座的金属外壳要接地否则插拔时会有静电问题。布线项目规则原因SPI时钟线长度5cm包地减少EMI防止屏幕噪点电源升压走线宽度≥1mm铺铜大电流减少压降晶振走线长度1cm包地防止时钟抖动天线区域所有层净空保证射频性能按键信号RC滤波防止抖动误触发音频输出远离电源防止底噪3.4 打样与焊接PCB打样用的嘉立创四层板沉金工艺5片大概50块。焊接用热风枪烙铁QFN封装的芯片用热风枪吹注意风量不要太大否则会把旁边的阻容吹飞。ESP32-P4是QFN封装底部有散热焊盘焊接时要先在焊盘上涂锡膏然后用热风枪从底部加热。注意SW6206和ESP32-P4都是QFN封装焊接时一定要用锡膏不要用锡丝。锡膏的量和回流温度要控制好否则容易虚焊。焊接完成后先不要焊屏幕和电池用USB供电测试电源部分。测各路电压是否正常3.3V和5V都要测。然后用ESP-Flasher烧录一个简单的测试固件确认主控能正常工作。4. RetroGo系统移植与ST7789V驱动适配4.1 RetroGo是什么为什么选它RetroGo是一个开源的复古游戏模拟器前端基于ESP-IDF开发支持ESP32系列芯片。它的架构是底层用ESP-IDF的驱动中间层是模拟器核心Nofrendo、Gnuboy、Snes9x等上层是菜单系统和UI。选它的原因是它对ESP32系列支持最好社区活跃而且代码结构清晰方便移植。RetroGo的源码结构大概是这样main/主程序菜单逻辑components/模拟器核心和驱动drivers/屏幕、音频、按键驱动roms/ROM文件实际存在TF卡里移植到P4的主要工作是修改屏幕驱动适配ST7789V、修改音频驱动适配I2S、修改按键驱动适配GPIO、调整编译配置适配P4的硬件参数。4.2 ST7789V驱动初始化序列调参ST7789V的初始化序列是移植过程中最耗时间的部分。公版的初始化序列能点亮屏幕但显示效果不一定好。我用的这块3.5寸IPS屏厂家给的初始化序列和公版有几处不同// ST7789V初始化序列关键部分 static const st7789_cmd_t init_cmds[] { {0x36, {0x00}, 1}, // MADCTL: 扫描方向 {0x3A, {0x55}, 1}, // COLMOD: 16位色 {0xB2, {0x0C, 0x0C, 0x00, 0x33, 0x33}, 5}, // PORCH设置 {0xB7, {0x35}, 1}, // 门控设置 {0xBB, {0x19}, 1}, // VCOM设置 {0xC0, {0x2C}, 1}, // 电源控制 {0xC2, {0x01}, 1}, // 电源控制2 {0xC3, {0x12}, 1}, // 电源控制3 {0xC4, {0x20}, 1}, // 电源控制4 {0xC6, {0x0F}, 1}, // 帧率控制 {0xD0, {0xA4, 0xA1}, 2}, // 电源控制5 {0xE0, {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23}, 14}, // 正伽马 {0xE1, {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23}, 14}, // 负伽马 {0x21, {0x00}, 0}, // 反转开启 {0x11, {0x00}, 0}, // 睡眠退出 {0x29, {0x00}, 0}, // 显示开启 };几个关键点MADCTL0x36这个寄存器控制扫描方向和RGB顺序。我的屏幕是横屏使用所以设置为0x00如果是竖屏用0x60。RGB顺序不对会导致红蓝互换需要根据实际屏幕调整。COLMOD0x3A设置为0x55表示16位色RGB565这是最常用的配置。如果屏幕支持18位色可以设0x66但P4的SPI传输16位更高效。伽马校正0xE0/0xE1这两组参数直接影响色彩表现。厂家给的参数和公版不同我实测下来厂家的参数色彩更准尤其是暗部细节更好。帧率控制0xC6设置为0x0F表示60Hz刷新率。如果屏幕有闪烁可以尝试调整这个值。提示ST7789V的初始化序列没有统一标准不同厂家的面板参数不同。最好的方法是找厂家要初始化代码或者用逻辑分析仪抓原厂驱动的SPI波形。4.3 SPI DMA传输与双缓冲ST7789V是SPI接口如果直接用阻塞方式发送像素数据CPU会被占满模拟器帧率会掉得厉害。RetroGo用了SPI DMA传输配合双缓冲实际体验好很多。具体实现是申请两块帧缓冲一块用于模拟器渲染一块用于SPI DMA发送。模拟器渲染完一帧后切换缓冲区启动DMA传输然后继续渲染下一帧。这样CPU和DMA并行工作屏幕刷新率能稳定在30fps左右。SPI时钟我超频到了80MHzST7789V的规格书标称最大62.5MHz但实测80MHz也能稳定工作。超频后全屏刷新时间从20ms降到15ms左右提升明显。// SPI DMA配置 spi_bus_config_t buscfg { .mosi_io_num PIN_MOSI, .miso_io_num -1, .sclk_io_num PIN_SCLK, .quadwp_io_num -1, .quadhd_io_num -1, .max_transfer_sz 320 * 240 * 2, // 全屏缓冲 }; spi_device_interface_config_t devcfg { .clock_speed_hz 80 * 1000 * 1000, // 80MHz .mode 0, .spics_io_num PIN_CS, .queue_size 2, };4.4 音频I2S驱动适配音频部分用的是P4的I2S接口输出到PAM8302功放。RetroGo的音频驱动需要修改采样率和缓冲区大小。我用的配置是采样率22050Hz模拟器原生采样率位深16位缓冲区512样本这个配置下音频延迟大概50ms玩动作游戏能感觉到轻微延迟但可以接受。如果追求更低延迟可以降低缓冲区到256样本但会有爆音风险。注意I2S的时钟配置要和模拟器的采样率匹配否则音频会变调。RetroGo的音频驱动里有个重采样模块可以把模拟器的输出重采样到I2S的采样率。5. 整机调试与常见问题排查5.1 屏幕显示问题排查屏幕问题是最常见的我遇到过的有白屏初始化序列没发对或者RST引脚时序不对。检查RST引脚是否在初始化前拉低再拉高延时是否足够。花屏SPI时钟太快或者走线太长。降低SPI时钟到40MHz试试如果正常就是信号完整性问题。偏色MADCTL寄存器的RGB顺序不对或者伽马参数不对。尝试修改0x36寄存器的值。显示区域偏移PORCH参数不对需要调整0xB2寄存器的值。不同屏幕的PORCH参数不同需要查规格书。闪烁帧率设置不对或者电源纹波太大。先调0xC6寄存器如果不行就检查电源。问题现象可能原因解决方法白屏初始化失败检查RST时序和初始化序列花屏SPI信号完整性降低时钟缩短走线偏色RGB顺序错误修改MADCTL寄存器区域偏移PORCH参数错误调整0xB2寄存器闪烁帧率或电源问题调0xC6检查电源纹波5.2 模拟器性能优化模拟器性能不够的话可以从几个方面优化跳帧RetroGo支持跳帧设置跳过1帧可以提升大概30%的帧率。但跳帧会导致画面不流畅建议只在性能不足时开启。音频重采样如果音频处理占用CPU太多可以降低采样率到11025Hz音质会差一些但性能提升明显。ROM加载方式ROM从TF卡加载到PSRAM再运行比直接从TF卡读取快很多。RetroGo默认是加载到PSRAM的确保PSRAM配置正确。编译优化ESP-IDF的编译优化等级设为-O2可以提升10%左右的性能。5.3 电源管理调试SW6206的调试主要是测各路电压和纹波。我用示波器测了升压输出的纹波大概50mV左右在可接受范围内。如果纹波太大可以加大输出电容或者调整电感值。电池电量检测用的是P4的ADC需要校准。我用的方法是测几个已知电压点拟合出电压和ADC读数的曲线然后在代码里做线性插值。提示SW6206的电量指示灯是电流模式的LED的亮度随电池电压变化。如果LED亮度不对可以调整限流电阻。5.4 烧录与固件更新烧录用的是ESP-Flasher这是一个图形化的烧录工具支持ESP32全系列。烧录时需要注意选择正确的芯片型号ESP32-P4选择正确的Flash大小我用的16MB烧录地址要正确bootloader、partition table、app烧录前要按住BOOT键再上电进入下载模式ESP-Flasher的优点是简单易用不需要装ESP-IDF环境。缺点是功能有限不能做OTA更新。如果需要OTA还是要用ESP-IDF的idf.py命令。# 用esptool烧录 esptool.py --chip esp32p4 --port /dev/ttyUSB0 --baud 921600 \ write_flash 0x0 bootloader.bin \ 0x8000 partition-table.bin \ 0x10000 app.bin6. 外壳设计与整机组装6.1 3D打印外壳设计外壳用Fusion 360设计分前后壳用螺丝固定。设计时要注意屏幕开孔要精确留0.5mm余量按键开孔要对准PCB上的按键位置电池仓要留够空间18650电池直径18mm长度65mmUSB接口开孔要对准Type-C座喇叭开孔要留出声孔我打了三版才满意第一版屏幕开孔太小第二版按键位置偏了第三版才完美。建议先用纸板做个模型验证尺寸再打印。6.2 整机组装步骤组装顺序很重要我总结的步骤是焊接PCB上的所有元器件包括屏幕FPC座、TF卡座、按键、USB座测试电源部分确认各路电压正常烧录测试固件确认主控和屏幕工作正常焊接电池线注意正负极不要接反安装屏幕到前壳用双面胶固定安装PCB到前壳用螺丝固定安装喇叭和电池到后壳连接前后壳的排线屏幕、电池、喇叭合壳拧螺丝开机测试注意电池线焊接时一定要确认正负极接反会烧芯片。建议先用万用表测电池座的电压确认极性后再焊。6.3 手感优化与细节调整按键手感很重要我试了几种方案轻触开关手感硬行程短适合方向键锅仔片手感软行程长适合AB键导电胶手感最好但需要定制最终我用了轻触开关硅胶垫的组合手感接近原版GB。硅胶垫是3D打印的用TPU材料硬度选95A。屏幕亮度调节用PWM控制背光RetroGo的菜单里有亮度调节选项。背光电路用一个MOS管驱动PWM频率设为5kHz避免人耳听到啸叫。7. 我踩过的坑和实操心得7.1 PCB设计中的血泪教训第一版PCB我犯了个低级错误SPI屏幕的CS引脚和TF卡的CS引脚接反了。结果就是屏幕能显示但TF卡读不出来查了半天才发现是引脚定义搞错了。画原理图时一定要仔细核对引脚定义最好做个表格对照。第二版的问题是电源纹波太大屏幕有横纹。原因是SW6206的电感离芯片太远反馈线走线太长。重新布局后电感靠近芯片反馈线从输出电容后面取纹波从200mV降到50mV。第三版的问题是按键抖动偶尔会误触发。加了RC滤波后解决。RC滤波的参数是10k上拉100nF电容截止频率大概160Hz能有效滤除抖动。7.2 软件调试中的坑RetroGo移植到P4时最大的坑是PSRAM的配置。P4支持外挂PSRAM但需要在menuconfig里正确配置。我一开始没配置PSRAM模拟器一加载ROM就崩溃。配置PSRAM后ROM加载正常但速度慢后来发现是PSRAM的时钟配置不对改成200MHz后正常。另一个坑是I2S的时钟配置。P4的I2S时钟源和S3不同需要重新计算分频系数。我一开始直接用了S3的配置结果音频变调。后来查了P4的技术参考手册重新计算了分频系数才正常。7.3 一些实用的调试技巧用逻辑分析仪抓SPI波形屏幕不亮或者花屏时用逻辑分析仪抓SPI波形看初始化序列是否发对了。我用的Saleae Logic 8配合ST7789V的协议解码器很方便。用示波器测电源纹波电源问题用示波器测最直观。测纹波时要用AC耦合带宽限制到20MHz否则会测到高频噪声。用串口打印调试信息RetroGo支持串口日志输出调试时打开日志可以看到模拟器的帧率、音频缓冲状态等信息。用ESP-Flasher的日志功能ESP-Flasher烧录时会输出日志如果烧录失败看日志能快速定位问题。7.4 成本清单与采购建议整机成本大概如下项目价格备注ESP32-P4模组35元立创商城ST7789V屏幕25元淘宝SW62065元立创商城PCB打样50元/5片嘉立创18650电池15元淘宝外壳3D打印30元淘宝代打其他元器件30元阻容、按键、喇叭等合计190元不含工具采购建议ESP32-P4模组和SW6206从立创商城买保证正品。屏幕从淘宝买注意选IPS全视角的。电池选正规厂家的不要买杂牌。8. 后续可以扩展的方向这台掌机目前能流畅跑NES、GB、GBC、SMSSNES和Genesis需要跳帧。后续我想做的改进有换RGB屏RGB屏刷新率能上60fps画面更流畅。但需要重新设计PCB工作量不小。加震动马达用P4的LEDC输出PWM驱动震动马达增加游戏反馈。加蓝牙手柄支持P4支持蓝牙可以加蓝牙手柄支持实现双人游戏。优化模拟器核心目前用的模拟器核心还有优化空间比如用汇编优化关键循环提升帧率。做OTA更新目前只能用ESP-Flasher烧录做OTA后可以直接在掌机上更新固件。加视频输出P4有MIPI-DSI接口可以加一个DSI转HDMI芯片输出到电视。这个项目从开始到完成大概花了两个月大部分时间在PCB设计和调试上。如果你也想做一台建议先从简单的方案开始比如用现成的开发板屏幕模块跑通RetroGo后再画PCB。这样风险小而且能快速看到效果。最后分享一个小技巧调试屏幕时可以先写一个简单的测试程序全屏显示红绿蓝三色确认屏幕能正常显示后再跑RetroGo。这样可以把屏幕问题和软件问题分开排查效率高很多。
返回列表