12864多级菜单实现方法

前言
       一般来说使用12864进行显示,配合按键作为人机界面交互,如果显示的内容较多的话,往往不能在一个页面显示完全,这里就需要用到多级菜单来进行管理,根据显示内容的不同,将其划分成不同的菜单,通过按键操作来选择不同的界面进行显示。这里介绍一种我自己使用的多级菜单实现原理和框架,并且分析一下其实现的方法,分享出来供大家参考。
一、菜单数据结构体

/************ 定义菜单列表结构体 **************/
typedef struct menu{
	unsigned char menu_sum;        /* 一个菜单中选项的个数 选项编号从0开始 一级最多256个选项 */
	unsigned char menu_cursor_num; /* 当前选中的选项在菜单列表中的编号 */
	unsigned char menu_cursor_lcd; /* 光标在屏幕上显示的位置 1~DP_NUM行 */
	unsigned char menu_dp[DP_NUM]; /* 用于存储目前显示在屏幕上的3行菜单选项在各自列表中的序号 */
	char **menu_str_point;	       /* 菜单选项名称字符串指针,指向各级菜单选项的名称,选项名称为一个指针数组 */
	struct menu *menu_before;      /* 指向上一级菜单列表 如果是主菜单就为NULL */
	struct menu **menu_next;	   /* 指向下一级菜单列表 */
	void (**menu_function)();      /* 函数指针 按下确认按键后 根据选项调用不同的函数执行操作 */
}menu;

多级菜单的实现最重要的就是定义一个菜单结构体,每级菜单都用一个菜单结构体来描述。
1. menu_sum表示每级菜单中的选项数量,由于其数据类型我定义为了unsigned char的类型,所以最大的选项个数类256个,基本够用了,一般没有人会设置超过256个选项吧。
2. menu_cursor_num表示光标位置,这个参数的类型需要和menu_sum的类型一致,为0时表示当前光标在第一个选项上。多级菜单势必要涉及到光标的操作,通过按键来上下移动光标,光标选中的那一行被反白显示,按下确认键之后,根据光标的位置进入到对应的下级菜单中或者执行对应的菜单函数。
3. menu_cursor_lcd用来确定当前光标在屏幕上的位置,12864一般采用3行来显示菜单列表信息,这个参数用来表示当前光标在第几行。
4. menu_dp[DP_NUM]表示当前显示在屏幕上的选项列表,DP_NUM表示屏幕最多可以显示几行列表,一般12864的液晶显示3行选项列表。0,1,2表示当前显示在屏幕上的是列表中标号为0,1,2的选项。
5. **menu_str_point指向一个字符串指针数组,数组里面存放着各个选项的名字字符串,一般定义成如下形式。然后将这个指针指向这个数组即可。

char const *menu_0_str[MENU_0_SUM] = {
	{"放大增益"},
	{"缩小比例"},
	{"DDS频率"},
	{"直流衰减"},
	{"Ui峰峰值"},
	{"继电器控制"}
};

6. *menu_before这个指针指向上级菜单,主菜单没有上级菜单设置为NULL,子菜单想返回上级菜单时即可通过这个指针返回上级菜单。通过这条语句即可now_menu = now_menu->menu_before;
7. **menu_next这是一个指向下级菜单列表的指针,由于一个菜单里面可能包含多个选项子菜单,每个子菜单又有可能对应一个菜单结构体,所以这个参数是一个双重指针,指向一个菜单结构体的列表。想进入光标所指的下级菜单式now_menu = now_menu->menu_next[now_menu->menu_cursor_num];
8. void (**menu_function)();回调函数指针参数,如果菜单选项对应的是一个具体的功能函数时,执行这个选项就会跳转到某个具体的功能函数去执行,一个菜单下面可能有很多的选项,每个选项都对应一个功能函数,这些函数就组成了一个函数列表,同样的用一个双重指针去描述。需要注意的是这里定义的回调函数是void fun(void)类型的函数,所以每个回调函数都必须是这个类型。
定义一个具体的菜单结构体时,可以在其中给其赋予初值,示例如下:

/*************** 数据查看 MENU_0下级菜单结构体定义 *************/

char const *menu_0_str[MENU_0_SUM] = {
	{"放大增益"},
	{"缩小比例"},
	{"DDS频率"},
	{"直流衰减"},
	{"Ui峰峰值"},
	{"继电器控制"}
};

menu menu_0 = {
	MENU_0_SUM, 				/* 选项个数 */
	0,							/* 初始化默认指向 第0个选项 */
	1,							/* 屏幕上显示默认在第1行	*/
	{0,1,2},					/* 初始化默认显示前3个选项 */
	(char **)menu_0_str,   		/* 指向菜单选项信息的指针数组 */
	&menu_main,					/* 指向上级目录 */
	NULL,						/* 指向下级目录 */
	NULL,						/* 函数指针 确认选项后操作的函数 */
};

二、菜单初始化
       程序中通过一个菜单初始化函数来对所有的菜单结构体进行初始化,主要是为结构体中的双重指针申请内存,然后将双重指针指向对应的结构体和函数。

void Menu_Init(void)
{
	/********************** 主菜单结构体中各成员变量初始化 **********************************/
	menu_main.menu_next = Menu_Malloc( sizeof(int)* MENU_MAIN_SUM); /* 为下级菜单指针申请内存 */
	/* 将主菜单结构体中的指向下级菜单的指针 一一指向各个菜单结构体 */
	menu_main.menu_next[0] = &menu_0;  /* 选项0 的下级菜单 没有就为NULL */
	/* 将主菜单结构体中的指向下级菜单的执行函数 一一指向各个函数 */
	menu_main.menu_function = Menu_Malloc( FUNC_SIZE* MENU_MAIN_SUM); /* 为选项的函数指针申请内存 */
	menu_main.menu_function[0] = NULL; 		/* 选项0的执行函数指针 指向相对应的函数 没有就为NULL */
	
	/*********************** menu_0菜单结构体中各成员变量初始化 *****************************/
	
	/* menu_0菜单没有下级菜单不需要申请内存 */
	
	menu_0.menu_next = NULL; /* 没有下级菜单了 将下级菜单指针初始化为NULL */
	
	menu_0.menu_function = Menu_Malloc(FUNC_SIZE* MENU_0_SUM); /* 为menu_0选项的函数指针 申请内存 */
	
	menu_0.menu_function[0] = &Func_0_0;/* 选项0的执行函数指针 指向相对应的函数 没有就为NULL */
	menu_0.menu_function[1] = &Func_0_1;/* 选项1的执行函数指针 指向相对应的函数 没有就为NULL */
	menu_0.menu_function[2] = &Func_0_2;/* 选项2的执行函数指针 指向相对应的函数 没有就为NULL */
	menu_0.menu_function[3] = &Func_0_3;/* 选项3的执行函数指针 指向相对应的函数 没有就为NULL */
	menu_0.menu_function[4] = &Func_0_4;/* 选项4的执行函数指针 指向相对应的函数 没有就为NULL */
	menu_0.menu_function[5] = &Func_0_5;/* 选项5的执行函数指针 指向相对应的函数 没有就为NULL */
}

       程序中有两个菜单,一个就是主菜单,主菜单下只有一个设置选项子菜单,设置菜单下有6个选项,这6个选项没有子菜单,都是具体的执行函数。首先初始化主菜单结构体,为指针申请内存,根据子菜单的数量申请内存,根据顺序指向子菜单结构体,之后为回调函数指针申请内存,由于是子菜单没有具体的执行函数,指针指向NULL。之后是设置子菜单结构体的初始化,过程是相同的,由于没有子菜单了,子菜单指针设置为NULL,设置回调函数指针指向每个选项的执行函数。

三、菜单的操作和显示
       菜单的操作和显示主要通过两个函数来实现,一个就是Menu_Handler()菜单操作函数主要负责处理各种按键消息,根据不同的按键消息来进行不同的操作,还有一个就是Menu_Display()负责显示菜单列表。所有的菜单操作都是通过一个菜单结构体指针进行的,Current_Menu指针指向当前正在操作的结构体,为NULL时表示没有进行菜单操作。

menu *Current_Menu = NULL; /* 初始化时默认为NULL,不显示菜单 */
void Menu_Display(void)
{
	if(Current_Menu != NULL) /* 有菜单时 */
	{
		/**************** 根据光标的位置显示向上和向下箭头 *******************/ 
		if(Current_Menu->menu_sum > 1)//菜单的选项大于一个才显示箭头
		{
			if(Current_Menu->menu_cursor_num == 0) /* 当前的光标位置在第一个选项了,就没有那个向上箭头显示,只有一个向下箭头显示 */
			{
				Menu_ShowBmp(Menu_Arrow_X+8,0,Menu_Arrow_X+16,2,Menu_ShowNor,Menu_BMP_DOWN); /* 显示向下的箭头 */
				Menu_Rect(Menu_Arrow_X,0,Menu_Arrow_X+8,2,0); /* 清除上箭头显示的位置 */
			}
			else if(Current_Menu->menu_cursor_num == (Current_Menu->menu_sum-1)) /* 光标在菜单的最后一个选项的时候,只显示向上的箭头 */
			{
				Menu_ShowBmp(Menu_Arrow_X,0,Menu_Arrow_X+8,2,Menu_ShowNor,Menu_BMP_UP); /* 显示向下的箭头 */
				Menu_Rect(Menu_Arrow_X+8,0,Menu_Arrow_X+16,2,0); /* 清除下箭头显示的位置 */
			}
			else /* 其他光标在菜单中间选项时,同时显示两个箭头 */
			{
				Menu_ShowBmp(Menu_Arrow_X+8,0,Menu_Arrow_X+16,2,Menu_ShowNor,Menu_BMP_DOWN); /* 显示向下的箭头 */
				Menu_ShowBmp(Menu_Arrow_X,0,Menu_Arrow_X+8,2,Menu_ShowNor,Menu_BMP_UP); /* 显示向下的箭头 */
			}
		}
		if((Current_Menu->menu_cursor_lcd == 1)||(Current_Menu->menu_cursor_lcd == 2)||(Current_Menu->menu_cursor_lcd == 3))  /* 有效的光标位置 同时有选项 */
		{
			Menu_Display_PrintfShowClear(Menu_X,Menu_Line2,Menu_Size16,((Current_Menu->menu_cursor_lcd == 1)?Menu_ShowClear2:Menu_ShowClear0/* 光标选中的一行反白加填充 */),\
			"%d.%s", Current_Menu->menu_dp[0]+1,Current_Menu->menu_str_point[Current_Menu->menu_dp[0]]); /* 显示菜单的第一个显示选项 */
			if(Current_Menu->menu_sum > 1) /* 如果菜单的选项大于1 显示第二个选项 */
			{
				Menu_Display_PrintfShowClear(Menu_X,Menu_Line3,Menu_Size16,((Current_Menu->menu_cursor_lcd == 2)?Menu_ShowClear2:Menu_ShowClear0/* 光标选中的一行反白加填充 */),\
				"%d.%s",Current_Menu->menu_dp[1]+1,Current_Menu->menu_str_point[Current_Menu->menu_dp[1]]); /* 显示菜单的第二个显示选项 */
			}
			if(Current_Menu->menu_sum > 2) /* 如果菜单的选项大于2 显示第三个选项 */
			{
				Menu_Display_PrintfShowClear(Menu_X,Menu_Line4,Menu_Size16,((Current_Menu->menu_cursor_lcd == 3)?Menu_ShowClear2:Menu_ShowClear0/* 光标选中的一行反白加填充 */),\
				"%d.%s",Current_Menu->menu_dp[2]+1,Current_Menu->menu_str_point[Current_Menu->menu_dp[2]]); /* 显示菜单的第三个显示选项 */
			}
		}
	}
}

/*****************************************
*函数名称:Menu_Handler
*输入参数:Menu_News:一般为按键消息 上、下、确认、取消 光标在菜单中只能上下移动
*返回值  :无
*功能描述:根据传递进来的消息改变菜单结构体值
*更新时间:2019-02-02
*****************************************/
void Menu_Handler(u8 Menu_News)
{
	if((Menu_News == Menu_News_up)||(Menu_News == Menu_News_down)||(Menu_News == Menu_News_conf)||(Menu_News == Menu_News_cancel)) /* 判断消息的有效性,是否为有效的按键按下了 */
	{
		switch(Menu_News)
		{
			case(Menu_News_up): /* 向上按键按下 */
				if(Current_Menu != NULL) /* 屏幕上已经显示了菜单 */
				{
					if(Current_Menu->menu_cursor_num != 0) /* 光标还没有移动到当前菜单的第一个选项 */
					{
						Current_Menu->menu_cursor_num--; /* 光标上移一个选项 */
						if(Current_Menu->menu_cursor_lcd > 1) /* 屏上的光标显示不在第一行 */
						{
							Current_Menu->menu_cursor_lcd--; /* 光标上移一个选项 */
						}
						else /* 光标在屏幕上的第一行选项同时也不是菜单的第一个选项 需要改变屏幕上显示的三个选项 */
						{
							Current_Menu->menu_dp[0]--; /* 屏幕上显示的三个选项,整体上移一个选项 */
							Current_Menu->menu_dp[1]--; /* 屏幕上显示的三个选项,整体上移一个选项 */
							Current_Menu->menu_dp[2]--; /* 屏幕上显示的三个选项,整体上移一个选项 */
						}
					}
				}
				break;
			case(Menu_News_down): /* 向下按键按下 */
				if(Current_Menu != NULL) /* 屏幕上已经显示了菜单 */
				{
					if(Current_Menu->menu_cursor_num != (Current_Menu->menu_sum-1)) /* 光标是否已经移动到了最后一个选项 */
					{
						Current_Menu->menu_cursor_num++; /* 光标下移一个选项 */
						if(Current_Menu->menu_cursor_lcd < DP_NUM) /* 屏上的光标显示不在最后一行 */
						{
							Current_Menu->menu_cursor_lcd++; /* 光标下移一个选项 */
						}
						else /* 光标在屏幕上的第三行选项同时也不是菜单的最后一个选项 需要改变屏幕上显示的三个选项 */
						{
							Current_Menu->menu_dp[0]++; /* 屏幕上显示的三个选项,整体下移一个选项 */
							Current_Menu->menu_dp[1]++; /* 屏幕上显示的三个选项,整体下移一个选项 */
							Current_Menu->menu_dp[2]++; /* 屏幕上显示的三个选项,整体下移一个选项 */
						}
					}
				}
				break;
			case(Menu_News_conf): /* 确认按键被按下 */
				if(Current_Menu == NULL) /* 屏幕上还没有显示菜单选项 */
				{
					Display_Clear();//清屏
					Current_Menu = &menu_main; /* 菜单指针指向主菜单 */
					Menu_Display_PrintfShowClear(0,0,Menu_Size16,0,"主菜单"); /* 显示菜单标题 */
				}
				else /* 屏幕上已经有显示的菜单了 */
				{
					Menu_Display_Clear(); /* 清屏 */
					if(Current_Menu->menu_next != NULL) /* 如果当前的光标选择的选项有下级菜单 */
					{
						Menu_Display_PrintfShowClear(0,0,Menu_Size16,0,Current_Menu->menu_str_point[Current_Menu->menu_cursor_num]); /* 显示菜单标题 */
						Current_Menu = Current_Menu->menu_next[Current_Menu->menu_cursor_num]; /* 菜单指针指向下级菜单 */
					}
					else if(Current_Menu->menu_function[Current_Menu->menu_cursor_num] != NULL) /* 如果没有下级菜单了,但是有回调函数,则执行回调函数 */
					{
//						Menu_Display_Clear(); /* 清屏 */
						Menu_Display_PrintfShowClear(0,0,Menu_Size16,0,Current_Menu->menu_str_point[Current_Menu->menu_cursor_num]); /* 显示菜单标题 */
						Current_Menu->menu_function[Current_Menu->menu_cursor_num]();  /* 回调函数执行 */
						Menu_Display_PrintfShowClear(0,0,Menu_Size16,0,Current_Menu->menu_before->menu_str_point[Current_Menu->menu_before->menu_cursor_num]); /* 显示菜单标题 */
					}
					else /* 既没有下级菜单,也没有回调函数,说明没有菜单初始化完成 */
					{
						Menu_Assert(0); /* 错误断言 */
					}
				}
				break;
			case(Menu_News_cancel): /* 取消返回 */
				if(Current_Menu != NULL) /* 如果屏幕上现在是有菜单的才执行取消 */
				{
					Current_Menu->menu_cursor_num = 0; /* 光标位置清零 */
					Current_Menu->menu_cursor_lcd = 1; /* 光标在屏幕上回到第一行 */
					Current_Menu->menu_dp[0] = 0;			 /* 显示的选项初始化 */
					Current_Menu->menu_dp[1] = 1;			 /* 显示的选项初始化 */
					Current_Menu->menu_dp[2] = 2;			 /* 显示的选项初始化 */
					Current_Menu = Current_Menu->menu_before; /* 回到上级菜单 */
					Menu_Display_Clear(); /* 清屏 */
					if(Current_Menu != NULL)
					{
						if(Current_Menu->menu_before == NULL) /* 主菜单 */
						{
							Menu_Display_PrintfShowClear(0,0,Menu_Size16,0,"主菜单"); /* 显示菜单标题 */
						}
						else
						{
							Menu_Display_PrintfShowClear(0,0,Menu_Size16,0,Current_Menu->menu_before->menu_str_point[Current_Menu->menu_before->menu_cursor_num]); /* 显示菜单标题 */
						}
					}
					else /* 回到主界面了 */
					{
						
					}
				}
				break;
		}
	}
}

       Menu_Display()函数主要是菜单显示,显示菜单选项、光标、箭头指示等。Menu_Handler()函数主要是根据按键操作来改变光标和菜单状态的。这两个函数注释的比较详细的,有兴趣的可以研究一下,可以参考借鉴,这里不再多做分析。

四、回调函数编写
       回调函数是底层菜单最终需要执行的函数,根据这个函数来实现功能和显示不同的界面,由于结构体中的函数指针定义关系,回调函数的形式都是void fun(void)类型的,可以根据自己的需要进行更改。我这里来分享一下我的回调函数的编写框架。一个具体的回调函数如下所示:

const uint16_t CountDown_Ui[] = {100,10,1}; /* 根据光标位置加减数值 */
/*****************************************
*函数名称:Func_0_0 (放大增益)
*功能描述:主菜单 0_0选项的回调执行函数
*输入参数:无
*返回值  :无
*更新时间:2018-12-30
*****************************************/
void Func_0_0(void)
{
	uint8_t key,cursor_sta = 0,res;
	uint16_t Ui_gain_old = Ui_gain;
	AV_MEASURE_UO_IN();//继电器控制到 测试Ui
	delay_ms(50);//等待继电器动作完成
	ADC_sample_sta = 0; //测量Ui
	while(1)
	{
		Menu_Display_PrintfShowClear(0,Menu_Line2,Menu_Size16,Menu_ShowNor,"增益:%02d.%d",Ui_gain/10,Ui_gain%10);
		Menu_Display_PrintfShowClear(0,Menu_Line3,Menu_Size16,Menu_ShowNor,"Ui_Vpp:%02d.%01dmV",ADC_sample_data.Ui/10,ADC_sample_data.Ui%10);
		switch(cursor_sta)
		{
			case(0):
				Menu_Display_PrintfShow(40,Menu_Line2,Menu_Size16,Menu_ShowWhite,"%d",Ui_gain/100); /* 显示光标 */
				break;
			case(1):
				Menu_Display_PrintfShow(40+8,Menu_Line2,Menu_Size16,Menu_ShowWhite,"%d",(Ui_gain%100)/10); /* 显示光标 */
				break;
			case(2):
				Menu_Display_PrintfShow(40+24,Menu_Line2,Menu_Size16,Menu_ShowWhite,"%d",Ui_gain%10); /* 显示光标 */
				break;
		}
		res = xQueueReceive(Key_QueueHandle,&key,200); /* 200ms */
		if(res == pdTRUE) //检测到按键
		{
			if((key == Menu_News_conf)||(key == Menu_News_cancel)) /* 按下了取消键或者确认键 跳出循环 */
				break;
			switch(key)
			{
				case(Menu_News_up): /* 上键 这里做加键 */
					if((Ui_gain + CountDown_Ui[cursor_sta]) <= 500) /* 小于等于最大的设定值 */
					{
						Ui_gain = Ui_gain + CountDown_Ui[cursor_sta];
					}
					break;
				case(Menu_News_down): /* 下键 这里做减键 */
					if(((Ui_gain - CountDown_Ui[cursor_sta]) >= 200)&&(Ui_gain > CountDown_Ui[cursor_sta])) /* 大于最小设定值 */
					{
						Ui_gain = Ui_gain - CountDown_Ui[cursor_sta];
					}
					break;
				case(Menu_News_left): /* 左键 */
					if(cursor_sta == 0)
						cursor_sta = 2;
					else
						cursor_sta--;
					break;
				case(Menu_News_right): /* 右键 */
					if(cursor_sta == 2)
						cursor_sta = 0;
					else
						cursor_sta++;
					break;
			}
		}
	}
	if(Conf_Revise() == 0xaa ) /* 确认 */
	{
		Menu_Display_PrintfShowCent(Menu_Line2,Menu_Size16,Menu_ShowClear0,"修改中...");
		Write_Gain();//写入存储
		delay_ms(500);
	}
	else /* 取消 */
	{
		Ui_gain = Ui_gain_old; //增益调回原值
	}
	ADC_sample_sta = 0xff;
	memset(ADC_sample_data.ADC_Ui_buf,0,sizeof(ADC_sample_data.ADC_Ui_buf));
	ADC_sample_data.ADC_Ui_count = 0;
}

       这个函数是一个参数设置函数,用来设置参数并保存,一个while(1)的死循环,在加上一个if break的语句,判断按下取消或确认键就退出死循环,退出循环后选择是否确认要保存参数,Conf_Revise返回0xaa表示确认保存,否则不保存修改的参数。

总结
       上面分析了一下关于多级菜单实现的方法,介绍的方法最好基于RTOS来实现,创建一个任务来运行多级菜单的操作和显示,并且由于回调函数是一个死循环的形式,如果没有RTOS的任务调度和阻塞功能,就无法在回调函数执行的过程中处理别的数据,实现起来较为困难。

源码下载

  • 19
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: LCD12864多级菜单实现是通过显示屏上的不同菜单实现用户与设备交互和操作的过程。具体实现方式如下: 1. 初始化LCD12864屏幕:首先需要初始化LCD12864屏幕,确保其能正常显示。 2. 设计菜单结构:根据实际需求,设计多级菜单的结构,包括主菜单和子菜单。主菜单是一级菜单,子菜单可以有多级,组成多级菜单。 3. 显示主菜单:将主菜单的选项显示在LCD12864屏幕上,使用屏幕上的光标选择相应的选项。 4. 用户选择选项:通过按键或触摸屏等输入设备,用户可以选择不同的菜单选项。 5. 显示子菜单:根据用户选择的菜单选项,在LCD12864屏幕上显示对应的子菜单选项。 6. 用户选择子菜单选项:用户可以通过光标或触摸屏幕等输入设备选择子菜单中的具体选项。 7. 执行操作:根据用户选择的子菜单选项,执行相应的操作,例如显示特定信息、设置参数、执行功能等。 8. 返回上级菜单:用户可以通过按返回键返回上一级菜单,或者通过选择特定的返回选项返回。 9. 循环操作:循环执行上述步骤,使用户可以在不同菜单之间切换和操作。 通过以上步骤,LCD12864多级菜单实现可以提供用户友好的界面,使用户能够方便地进行操作和配置设备。在实际应用中,还可以根据需要进行其他功能的拓展,例如增加菜单项、添加快捷操作等。 ### 回答2: LCD12864多级菜单实现主要分为以下几个步骤: 1. 初始化LCD屏幕:将LCD屏幕模式设置为128x64点阵模式,并清空屏幕内容。 2. 定义菜单数据结构:根据实际需求定义菜单的结构体,包括菜单名称、菜单项数目、菜单项内容等信息。可以使用数组、链表等数据结构存储菜单数据。 3. 显示主菜单:根据菜单数据结构,显示主菜单菜单项。可以使用LCD屏幕的绘图函数将菜单项逐个显示出来,同时通过光标或其他标记方式来确定当前选中的菜单项。 4. 处理菜单项选择:通过按键、遥控器等输入方式来选择菜单项。根据不同的输入方式,可以监听对应的按键或遥控器指令,并根据当前选中的菜单项进行相应的操作。 5. 处理上下级菜单切换:当选择某个菜单项时,根据当前菜单项的类型(菜单项还是功能项)进行不同的处理。如果是菜单项,需要切换到下一级菜单,更新菜单数据结构,并重新显示菜单项。如果是功能项,执行对应的功能代码。 6. 返回上一级菜单:在下一级菜单中,可以通过返回按钮或其他指令返回上一级菜单。返回操作需要更新菜单数据结构,重新显示上一级菜单菜单项。 7. 退出菜单系统:当用户退出菜单系统时,清空LCD屏幕内容,并进行必要的资源释放。 通过以上步骤,我们可以实现LCD12864多级菜单的功能,实现用户友好的菜单操作界面,方便用户进行选择和操作。同时,根据具体需求,可以进行个性化的定制和扩展。 ### 回答3: LCD12864多级菜单实现的基本思路是利用LCD12864显示屏和控制器的特性,通过设置不同的菜单层级和相关操作进行菜单的切换和功能的实现。 首先,需要确定菜单的层级结构,可以分为一级菜单、二级菜单等。每一级菜单都有相应的菜单选项和功能操作。 接下来,需要定义菜单切换的条件和方式。通常可以使用按钮、旋钮等控制器来进行菜单项的选择和切换。根据控制器的信号,可以判断当前所处的菜单层级和菜单项,并显示在LCD12864上。 在菜单实现过程中,需要编写相应的代码逻辑。可以通过判断当前所处的菜单层级和菜单项来执行相应的功能操作。例如,当选择某个菜单项后,可以进入下一级菜单或执行相应的功能操作,如打开某个功能模块、进行一些设置操作等。不同菜单层级和菜单项之间的切换和操作都需要根据具体需求进行编写。 最后,需要在LCD12864上显示当前的菜单和选项内容。可以使用适当的图形和文字来实现清晰易懂的显示效果。在显示的同时,还可以根据需要进行一些动态效果的增加,如闪烁、滚动等,以增强用户的交互体验。 综上所述,LCD12864多级菜单实现涉及到层级结构的定义、菜单切换的控制、代码逻辑的编写和LCD12864的显示设置等方面。只要根据具体需求和硬件特性进行相应的配置和编码工作,就可以实现一个功能完善的LCD12864多级菜单系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落叶凋凌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值