一,内容概括:不使用长篇大论
1:多级菜单介绍
2:实现思路
3:代码编写
4:总结
二,正文
1.多级菜单介绍:
想必大家看到这里,也知道多级菜单大概是什么;对于还不太清楚的朋友说明以下,多级菜单就是将一块屏幕原本只能显示一种内容,扩展到可以显示很多内容。依据自己的设定显示内容。
2.实现思路:
本文实现思路是自己设计出来的,只设计了三级菜单,你们可以自行拓展
(1)实现多级菜单:将菜单进行分类:分为一级菜单,二级菜单,三级菜单(子菜单)
(2)功能选择:设定在二级菜单当中进行选择,选择之后进入三级菜单(子菜单)
(3)返回功能:返回上一级菜单
注:本文是基于独立按键进行 KEY1:向下,KEY2:确定,KEY3:返回
3.代码编写:
注:要实现多级菜单,就必须有一个清晰的流程图,能够梳理代码逻辑,并最终实现功能
1.先看oled_menu.h文件
#ifndef _oled_menu_H
#define _oled_menu_H
#include "system.h"
//KEY1:向下
//KEY2:确定
//KEY3:返回
/*
* 代码逻辑循序:菜单>功能>返回
*逻辑梳理:
* 1:菜单选择:Enter进入 -----------子菜单----------------
* Enter=1,菜单1;Enter=2,菜单2; Enter=3,子菜单1;.....;Enter=6,子菜单4
* 2:功能选择:Next,进入菜单2以后,进行功能选择
* Next=1,功能1; Next=2,功能2;Next=3,功能3;Next=4,功能4;
* 3:返回菜单:Back 只需要返回菜单1,2:即将Enter置为1,2
*/
//菜单对应Enter值
#define MENU1 1
#define MENU2 2
#define MENU3_A 3
#define MENU3_B 4
#define MENU3_C 5
#define MENU3_D 6
//功能对应Next值
#define FUNTION_A 1
#define FUNTION_B 2
#define FUNTION_C 3
#define FUNTION_D 4
void Oled_Menu_Manage(void ); //初始版本
void Oled_Menu_Manage_Optimize(void); //优化版本
#endif
代码逻辑梳理:定义菜单值,功能选择值
1.菜单选择:每一级菜单都有自己对于的菜单值,定义了一个Enter变量,依据该Enter变量值选取对应的菜单。KEY2为确认键,每按一次Enter加1,直到6;定义功能对应值,在菜单2中进行功能选取。
//菜单对应Enter值
#define MENU1 1
#define MENU2 2
#define MENU3_A 3
#define MENU3_B 4
#define MENU3_C 5
#define MENU3_D 6
注:
(1)MENU1:菜单1,我自己是写入了一些提示信息,当然你也可以显示一些欢迎信息等等。想了一下还是放一些图片效果会比较好:注意显示数字的目的是为了验证每一级菜单都是可以进行动态显示。
(2)MENU2:菜单2,在按下KEY2确认进入到菜单2后,菜单2显示功能。
(3)MENU3:菜单3(子菜单),此时介绍的是菜单选取,并没有进行功能选择,但是为了与上文衔接我先放出选取功能1的子菜单。具体显示功能只是放入一些数值进行演示,具体功能你们自行添加。
2.功能选择:每按一次KRY1,功能加1,加到4,,返回。按下KEY1确认进行功能选择。其实和菜单是一样的。这里也还是放入一些图片。
//功能对应Next值
#define FUNTION_A 1
#define FUNTION_B 2
#define FUNTION_C 3
#define FUNTION_D 4
3.返回功能:返回上一级,此处就不详细说了,应该都知道。
注:此处对该代码功能进行一下阐述,基本和以前的按键手机设计差不多。
(1)首先并不是上电就显示菜单1,因为在正常使用的时候,可能有时候不使用该模块,要使用需要按下KEY2确认,进入菜单1;
按下KEY2此时再进入到菜单2,进入菜单2,从上图所知,并不是一开始就有箭头指向功能选取,按下KEY1功能选取后,再进入到子菜单中。
(2)返回键:假设现在处于子菜单,按下KEY3,返回到菜单2,此时功能选取停留在上次选取位置,若再返回到菜单1,在功能选取清空。
2.再看oled_menu.c文件
(1)代码逻辑梳理:此处直接说明设计流程
1:菜单选择:定义变量:Enter 根据KEY2按下后,对每一层菜单显示内容均进行函数封装,根据菜单入口参数进行选取菜单,直接上代码,应该很好理解;在菜单2当中会看到多一个参数,因为菜单2还多一个功能选取。
//第1层:欢迎界面等
//界面
void menu1(u8 menu)
{
static u16 i=0;
i++;
delay_ms(2);
if(menu==1)
{
OLED_ShowString(0,0,"Menu1:2024.8.1",16);
OLED_ShowString(0,20,"KEY2 to menu2",16);
OLED_ShowNum(0,40,i,5,16);
}
}
void menu2(u8 menu,u8 fun) //参数:菜单,功能选择
{
if(menu==2)
{
fun_a2(fun); //功能1:fun=FUNTION_A 1
fun_b2(fun); //....
fun_c2(fun);
fun_d2(fun);
}
}
// 第3层:子菜单:
void menu3_a(u8 menu )
{
static u16 i=0;
i++;
if(menu==MENU3_A)
{
//显示数值
OLED_ShowString(0,0,"MENU3_A",16);
OLED_ShowNum(0,30,i,5,16);
}
}
void menu3_b(u8 menu )
{
static u16 i=0;
i++;
if(menu==MENU3_B)
{
OLED_ShowString(0,0,"MENU3_B",16);
OLED_ShowNum(0,30,i,5,16);
}
}
void menu3_c(u8 menu )
{
static u16 i=0;
i++;
if(menu==MENU3_C)
{
OLED_ShowString(0,0,"MENU3_C",16);
OLED_ShowNum(0,30,i,5,16);
}
}
void menu3_d(u8 menu )
{
static u16 value=0;
value++;
if(menu==MENU3_D)
{
OLED_ShowString(0,0,"MENU3_D",16);
OLED_ShowNum(0,30,value,5,16);
delay_ms(2);
}
}
2:功能选取:和菜单选取思路一致,直接上代码。
void fun_a2(u8 fun)
{
if(fun==1) OLED_ShowChar(0,0,'>',12,1);
OLED_ShowString(14,0,"ESP01s",16);
}
void menu2(u8 menu,u8 fun) //参数:菜单,功能选择
{
if(menu==2)
{
fun_a2(fun); //功能1:fun=FUNTION_A 1
fun_b2(fun); //....
fun_c2(fun);
fun_d2(fun);
}
}
3:返回功能:KEY3返回,每按下一次菜单值减一,返回就是返回上一级菜单,子菜单->菜单2->菜单1,但是子菜单都是返回到菜单2;设计思路和上面两种一致,菜单有菜单对应变量进行管理,功能选择有功能变量进行管理,返回功能对菜单对应变量进行管理。
(2)显示部分:菜单对应变量值进行索取,直接上代码。
/*----------------------------显示菜单界面---------------------------------------*/
switch (Enter) //进入菜单1,2,3(子菜单)
{
case MENU1: //菜单1
if(Clear==1)OLED_Clear(); //******菜单2,转换菜单1就清屏
menu1(Enter);
OLED_Refresh_Gram();//刷新显存
break;
case MENU2: //菜单2:功能显示,功能选择
if(Clear==1)OLED_Clear(); //******菜单1,转换菜单2就清屏
menu2(Enter,Next); //菜单2:显示功能,和被选择功能
OLED_Refresh_Gram();//刷新显存
break;
case MENU3_A: //功能1子菜单
if(Clear==1)OLED_Clear(); //******菜单1,转换菜单2就清屏
menu3_a(Enter ) ;
OLED_Refresh_Gram();//刷新显存
break;
case MENU3_B: //功能2子菜单
if(Clear==1)OLED_Clear(); //******菜单1,转换菜单2就清屏
menu3_b(Enter ) ;
OLED_Refresh_Gram();//刷新显存
break;
case MENU3_C: //功能3子菜单
if(Clear==1)OLED_Clear(); //******菜单1,转换菜单2就清屏
menu3_c(Enter ) ;
OLED_Refresh_Gram();//刷新显存
break;
case MENU3_D: //功能4子菜单
if(Clear==1)OLED_Clear(); //******菜单1,转换菜单2就清屏
menu3_d(Enter ) ;
OLED_Refresh_Gram();//刷新显存
break;
default:
break;
}
注:设计思路将不同部分进行分别管理,没有用到死循环,梳理一下逻辑还是很简单的,这个设计思路,多级菜单对于思路感觉比代码编写更重要。
三.总结部分:
这段两天,本来是打算使用一下多级菜单,但是看了一些资料,都不是很详细,而且不太好复刻,所以自己设计了一个,希望能对你们有帮助;原码共设计了两个,一个初级版本,另一个优化之后的,代码会更加清晰明了,这个也是up第一次发文章,可能写的不好,希望同各位一起进步。
有需要原码的可以加:3344539646
有疑惑也可留言。
标签:功能,菜单,可移植,STM32,MENU3,OLED,fun,define From: https://blog.csdn.net/qaz2003411/article/details/140847105