# 为单片机OLED写的一个菜单模块 **Repository Path**: acutebubbles/MenuOLED ## Basic Information - **Project Name**: 为单片机OLED写的一个菜单模块 - **Description**: 纯抽象层,不存在硬件适配问题 - **Primary Language**: C - **License**: Unlicense - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2025-03-16 - **Last Updated**: 2025-09-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 为单片机OLED写的一个菜单模块(基于malloc) ## 使用与函数说明 ### 1. 文件说明: `Menu.c`:所需要的函数实现 `MenuSetting.c`:可供用户修改的设置与自定义函数文件 `Menu.h`:所需要的函数及结构体声明 ### 2. 变量说明: #### (1)先说明`MenuSetting.c`中的变量及函数 ``` MenuNode Core_Menu; //根节点 MenuNode a;//a节点 MenuNode b;//b节点 MenuNode c;//c节点 MenuNode d;//d节点 MenuNode e;//e节点 MenuNode f;//f节点 MenuNode g;//g节点 MenuNode h;//h节点 void Menu_Init() { a = *CREATE_FUNCTION_NODE("a", block_test_func, &Core_Menu); //a节点作为函数功能节点,父节点为Core_Menu b = *CREATE_FUNCTION_NODE("b", block_test_func, &Core_Menu); //b节点作为函数功能节点,父节点为Core_Menu c = *CREATE_FUNCTION_NODE("c", block_test_func, &Core_Menu); //c节点作为函数功能节点,父节点为Core_Menu d = *CREATE_FUNCTION_NODE("d", block_test_func, &Core_Menu); //d节点作为函数功能节点,父节点为Core_Menu e = *CREATE_CONTAINER_NODE("e", &Core_Menu, &f, &g, &h); //e节点作为文件夹功能节点,父节点为Core_Menu f = *CREATE_FUNCTION_NODE("f", block_test_func, &e); //f节点作为函数功能节点,父节点为e g = *CREATE_FUNCTION_NODE("g", block_test_func, &e); //g节点作为函数功能节点,父节点为e h = *CREATE_FUNCTION_NODE("h", block_test_func, &e); //h节点作为函数功能节点,父节点为e Core_Menu = *CREATE_CONTAINER_NODE("Core", NULL, &a, &b, &c, &d, &e); //Core_Menu绑定为globalMenuControler的根节点 initMenuControler(&globalMenuControler, &Core_Menu); } ``` ``` 形成的结构就是: Core_Menu ├── a ├── b ├── c ├── d └── e ├── f ├── g └── h ``` 而且abcd和fgh都存储着一个函数,可以通过`Menu.c`的函数调用之 #### (2)再说说如何具体使用这个库 **事实上**,只有以下几个函数是要使用的: ``` void decrementSelection(MenuControler *controller); void incrementSelection(MenuControler *controller); void exitMenu(MenuControler *controller); void useSelected(MenuControler *controller); ``` 分别对应向上选择,向下选择,退到上一级,使用选中单元(可以理解为双击文件) ``` void menuOLED_MenuControl_Print(MenuControler * Controler); ``` 则是打印当前页面 具体怎么打印,还要在`MenuSetting.c`中定义好选中与非选中的打印样式,文字默认16*16大小 ``` /** * @brief 未选中字符串打印的样式 * @param x OLED横坐标 * @param y OLED横坐标 * @param str 打印字符串 */ void MenuOLED_PrintString_N(uint8_t x, uint8_t y, char *str){ OLED_PrintString(x, y, str, &font16x16, OLED_COLOR_NORMAL); } /** * @brief 选中字符串打印的样式 * @param x OLED横坐标 * @param y OLED横坐标 * @param str 打印字符串 */ void MenuOLED_PrintString_R(uint8_t x, uint8_t y, char *str){ OLED_PrintString(x, y, str, &font16x16, OLED_COLOR_REVERSED); } ``` 完成后,你就可以用你的程序打印自己的菜单了 比如我的main中(hal库) ``` /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_I2C1_Init(); /* USER CODE BEGIN 2 */ HAL_Delay(100); OLED_Init(); HAL_Delay(100); Menu_Init(); OLED_NewFrame(); menuOLED_MenuControl_Print(&globalMenuControler); OLED_ShowFrame(); HAL_Delay(2000); OLED_NewFrame(); incrementSelection(&globalMenuControler); menuOLED_MenuControl_Print(&globalMenuControler); OLED_ShowFrame(); HAL_Delay(2000); OLED_NewFrame(); ``` OLED初始化后,执行`Menu_Init();` **注意**,根据你自己的oled代码,一定要注意`OLED_NewFrame();`与`OLED_ShowFrame(); `