【STM32】贪吃蛇 [阶段 3] 增强模块结构(架构优化)

这篇博客是 承接:【项目思维】贪吃蛇(嵌入式进阶方向)中 聚焦于 🧱 阶段 3:增强模块结构(架构优化) 中的 菜单系统(Menu System),这部分的结构优化可以学到的内容包含:工程项目架构设计、模块划分、状态管理、事件响应、接口抽象、可扩展性(预留) 等方面。接下来,我将对这些内容进行详细说明。

🧱 阶段 3:菜单系统的架构优化(模块化 + 状态机)

🎯 目标:
构建一个可维护、可扩展、可复用的菜单系统框架,为后续游戏 / 应用系统提供通用架构。

一、总体架构图
Main
├── MenuManager(菜单框架)
│   ├── 状态管理(enum GameState)
│   ├── 菜单项结构体(MenuItem)
│   └── 菜单事件派发器(事件响应)
├── UI_Display(接口抽象)
│   ├── OLED 显示实现
│   └── TFT 显示实现
├── InputManager(输入管理)
│   ├── 按键扫描
│   └── 输入事件封装
├── Assets(资源)
│   ├── 字体 / 图标
│   └── 菜单配置
📦 二、文件结构 + 模块划分(示例)

此处的模块化划分仅供参考:模块化的具体情况要根据具体项目进行合理化分解。

📁 Core/
│   ├── main.c
│   ├── app.c / app.h            	// 主程序调度
│   └── game_state.c / .h        	// 状态控制
📁 Menu/
│   ├── menu.c / menu.h          	// 菜单控制逻辑
│   └── menu_items.c / .h        	// 菜单项配置
📁 Drivers/
│   ├── oled.c / .h              	// OLED 显示驱动
│   ├── tft.c / .h               	// TFT 驱动
│   └── input.c / .h             	// 输入处理(按键)
📁 Assets/
│   └── font.c / icon.c          	// 字体、图标资源
📦 三、状态管理(GameState)
typedef enum {STATE_MENU,STATE_PLAY,STATE_PAUSE,STATE_GAME_OVER
} GameState;static GameState current_state = STATE_MENU;void switch_state(GameState new_state) {current_state = new_state;// 可在此执行 state entry 动作
}
🔖 四、菜单项结构体定义
typedef struct MenuItem {const char* name;void (*on_select)(void);  // 选中时执行的回调
} MenuItem;MenuItem main_menu[] = {{"Start Game", start_game},{"Settings", open_settings},{"About", show_about},{"Exit", system_exit}
};
🎮 五、菜单控制逻辑(MenuManager)

1. 菜单状态结构:

typedef struct {int current_index;MenuItem* items;int item_count;
} MenuState;MenuState menu = {.current_index = 0,.items = main_menu,.item_count = sizeof(main_menu)/sizeof(MenuItem)
};

2. 菜单事件响应:

void menu_handle_event(InputEvent evt) {switch (evt) {case EVENT_UP:menu.current_index = (menu.current_index - 1 + menu.item_count) % menu.item_count;break;case EVENT_DOWN:menu.current_index = (menu.current_index + 1) % menu.item_count;break;case EVENT_OK:if (menu.items[menu.current_index].on_select)menu.items[menu.current_index].on_select();break;default:break;}
}
🖥️ 六、显示层抽象(支持 OLED / TFT)

1. 显示接口定义(display_interface.h):

typedef struct {void (*clear)(void);void (*draw_text)(int x, int y, const char* text, bool selected);void (*refresh)(void);
} DisplayInterface;extern DisplayInterface* display;  // 指向当前使用的显示驱动

2. OLED 实现:

DisplayInterface oled_display = {.clear = oled_clear,.draw_text = oled_draw_text,.refresh = oled_refresh
};

使用方式:

void render_menu(MenuState* m) {display->clear();for (int i = 0; i < m->item_count; ++i) {display->draw_text(0, i*10, m->items[i].name, i == m->current_index);}display->refresh();
}
🕹️ 七、事件机制(按键输入与事件派发)

1. 输入事件定义:

typedef enum {EVENT_NONE,EVENT_UP,EVENT_DOWN,EVENT_OK
} InputEvent;

2. 按键扫描模块输入处理:

InputEvent read_input_event() {if (key_press(KEY_UP)) return EVENT_UP;if (key_press(KEY_DOWN)) return EVENT_DOWN;if (key_press(KEY_OK)) return EVENT_OK;return EVENT_NONE;
}

此处可以加入 事件队列机制,支持多个模块监听同一事件。


🛠️ 八、主函数(main.c
int main(void) {hardware_init();display = &oled_display;  // 或 tft_displaywhile (1) {InputEvent evt = read_input_event();switch (current_state) {case STATE_MENU:menu_handle_event(evt);render_menu(&menu);break;case STATE_PLAY:game_run();break;// 更多状态...}delay_ms(50);}
}
菜单系统设计原则

模块解耦:菜单逻辑、UI 显示、输入处理独立开发。
状态明确:使用 GAME_STATE 管理程序流程。
接口抽象:显示接口统一支持不同设备。
事件驱动:菜单响应按键事件,支持外部事件扩展。
可扩展性:菜单项可动态增加 / 嵌套子菜单。

这个菜单后续还可以扩展更多的功能:
功能						实现方式
菜单嵌套					每个菜单项跳转到子菜单(子 MenuItem 数组)
动画效果					菜单切换时加入滑动、淡入淡出
声音反馈					按键 / 选中时播放 beep 声
存档支持					菜单设置保存到 Flash
多语言支持				使用字符串资源表切换语言

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95652.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95652.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

江协科技STM32学习笔记补充之004

STM32 ISP 一键下载电路&#xff08;按功能、逻辑与时序拆解&#xff09;

数据库小册(1)

1. 关系型数据库主要考点关系型数据库&#xff1a;架构索引锁语法理论规范2. 如何设计一个关系型数据库设计即模块划分。数据库最主要的功能是存储我们的数据&#xff0c;所以需要一个存储的文件系统。我们要把涉及到的物流数据提供逻辑的形式给组织和表示出来&#xff0c;这是…

记录收入最高的一次私活 选号网,需要大量卖号的人可能需要,比如游戏脚本批量跑的号

选号网管理后台(上传游戏信息、账号信息、 查看记录) http://124.223.214.5:180/admin1 选号网客户端(PC/H5页面 给客户筛选商品用) http://124.223.214.5:181/ 该在线地址仅供低频率测试&#xff0c;正式使用需要另外部署。 功能不满足可以联系开发者定制 一、项目的由来 …

热烈庆祝“中国抗战胜利80周年”,织信低代码助力国之重器砥砺前行!

“从保家卫国到科技强军&#xff0c;织信低代码平台为军工企业数字化转型注入新动能。”80年后的今天&#xff0c;国人记忆从未褪色。2025年9月3日&#xff0c;正值中国抗战胜利80周年阅兵之际&#xff0c;我国国防军工力量在经历长期的艰苦奋斗后&#xff0c;现今终于迎来了曙…

PostgreSQL与SQL Server:B树索引差异及去重的优势

PostgreSQL与SQL Server&#xff1a;B树索引差异及去重的优势 在优化查询性能方面&#xff0c;索引是数据库工程师可使用的最强大工具之一。PostgreSQL和Microsoft SQL Server&#xff08;或Azure SQL&#xff09;都将B树索引用作其默认索引结构&#xff0c;但每个系统实现、维…

【微实验】使用MATLAB制作一张赛博古琴?

当一个理工音乐人没钱去买古琴&#xff0c;我直接用代码画一个古琴&#xff01;目录 零、总脚本&#xff1a; 一、核心功能&#xff1a;交互模块拆解 二、核心价值 一、初始化脚本&#xff1a;参数配置与启动界面 ①废话不说&#xff0c;直接上代码 ②代码模块拆解与详细解…

毕业项目推荐:67-基于yolov8/yolov5/yolo11的大棚黄瓜检测识别系统(Python+卷积神经网络)

文章目录 项目介绍大全&#xff08;可点击查看&#xff0c;不定时更新中&#xff09;概要一、整体资源介绍技术要点功能展示&#xff1a;功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出&#xff08;xls格式…

无人机小尺寸RFSOC ZU47DR板卡

整板尺寸&#xff1a;120*120mmFPGA: XCZU47DR-2FFVE1156I;DDR&#xff1a;PS侧8GB 2400Mhz*64bit / PL侧 4GB 2400Mhz*32bit&#xff1b;2路(QSP0QSPI1)/单片512Mb、共计1Gb&#xff1b;千兆以太网&#xff1a;1路&#xff08;PS侧&#xff09;&#xff1b;主要接口资源如下&a…

LangGraph(一):入门从0到1(零基础)

文章目录LangGraph入门从0到10️⃣ 安装 & 确认环境1️⃣ 把 LangGraph 想象成「自动化的做菜流水线」2️⃣ 最小可运行例子&#xff1a;一句话复读机3️⃣ 加一个小节点&#xff1a;把用户输入变大写4️⃣ 条件边&#xff1a;如果用户说 quit 就结束&#xff0c;否则复读5…

学习数据结构(16)快速排序

快速排序的基本思想&#xff1a;快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&#xff0c;其基本思想为&#xff1a;任取待排序元素序列中的某元素作为基准值&#xff0c;按照该基准值将待排序集合分割成两子序列&#xff0c;左子序列中所有元素均小于基准值&am…

uni-app iOS 上架常见问题与解决方案,实战经验全解析

uni-app 让开发者能够“一套代码&#xff0c;多端运行”&#xff0c;极大降低了开发成本。 但当应用进入 iOS 上架阶段 时&#xff0c;不少团队发现流程并没有想象中那么顺利&#xff1a;证书问题、打包失败、上传出错、审核被拒……这些都可能让项目卡壳。 本文结合实际案例&a…

洗衣机的智能升级集成方案WT2606B屏幕驱动+AI语音控制

2025&#xff0c;洗衣机市场正从功能满足转向体验升级&#xff0c;企业正面临哪些转型难点?一文为您解读洗衣机行业智能化升级之路。传统洗衣机就像是一个"沉默的工人"&#xff0c;只能通过简单的LED指示灯告诉你它在工作&#xff0c;却无法让你真正了解它在干嘛。用…

机器学习进阶,梯度提升机(GBM)与XGBoost

梯度提升机&#xff08;Gradient Boosting Machine, GBM&#xff09;&#xff0c;特别是其现代高效实现——XGBoost。这是继随机森林后自然进阶的方向&#xff0c;也是当前结构化数据竞赛和工业界应用中最强大、最受欢迎的算法之一。为什么推荐XGBoost&#xff1f; 与随机森林互…

【ARMv7】开篇:掌握ARMv7架构Soc开发技能

本专栏&#xff0c;开始与大家共同总结使用ARMv7系列CPU的Soc开发技能。大概汇总了一下&#xff0c;后面再逐步完善下面的思维导图。简单说说&#xff1a;与通用的ARMv7-A/R相比&#xff0c;以STM32F为代表的ARMv7-M架构有以下关键区别和重点&#xff1a;无MMU&#xff0c;有MP…

【学术会议论文投稿】JavaScript在数据可视化领域的探索与实践

【ACM出版 | EI快检索 | 高录用】2024年智能医疗与可穿戴智能设备国际学术会议&#xff08;SHWID 2024&#xff09;_艾思科蓝_学术一站式服务平台 更多学术会议请看 学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言 JavaScript可视化库概览 D3.js基础入门 1. 引入…

CSS基础学习步骤

好的&#xff0c;这是一份为零基础初学者量身定制的 **CSS 学习基础详细步骤**。我们将从最根本的概念开始&#xff0c;通过一步一步的实践&#xff0c;带你稳稳地入门。 第一步&#xff1a;建立核心认知 - CSS 是做什么的&#xff1f; 1. 理解角色&#xff1a; HTML&…

MTK Linux DRM分析(三十七)- MTK phy-mtk-hdmi.c 和 phy-mtk-hdmi-mt8173.c

一、简介 HDMI PHY驱动 HDMI 的物理层接口主要就是 HDMI Type-A 接口(19 pin),除此之外还有 Type-B、Type-C(Mini HDMI)、Type-D(Micro HDMI)、Type-E(车载专用)。 1. HDMI Type-A(常见 19-pin 标准接口) HDMI Type-A Connector Pinout ========================…

【人工智能学习之MMdeploy部署踩坑总结】

【人工智能学习之MMdeploy部署踩坑总结】报错1&#xff1a;TRTNet: device must be a GPU!报错2&#xff1a;Failed to create Net backend: tensorrt报错3&#xff1a;Failed to load library libonnxruntime_providers_shared.so1. 确认库文件是否存在2. 重新安装 ONNX Runti…

力扣516 代码随想录Day16 第一题

找二叉树左下角的值class Solution { public:int maxd0;int result;void traversal(TreeNode* root,int depth){if(root->leftNULL&&root->rightNULL){if(depth>maxd){maxddepth;resultroot->val;}}if(root->left){depth;traversal(root->left,depth…

网格图--Day07--网格图DFS--LCP 63. 弹珠游戏,305. 岛屿数量 II,2061. 扫地机器人清扫过的空间个数,489. 扫地机器人,2852. 所有单元格的远离程度之和

网格图–Day07–网格图DFS–LCP 63. 弹珠游戏&#xff0c;305. 岛屿数量 II&#xff0c;2061. 扫地机器人清扫过的空间个数&#xff0c;489. 扫地机器人&#xff0c;2852. 所有单元格的远离程度之和 今天要训练的题目类型是&#xff1a;【网格图DFS】&#xff0c;题单来自灵茶山…