单片机菜单结构设计
单片机:STM32F030F4 @ 48MHz
开发环境:keil+stm32cubemx
显示屏:LCD12864
一、准备工作:
1、按键功能正常
本例用了3个按键,
上按键=切换菜单里面的项目;
中按键=执行菜单里面的项目;
下按键=退出执行的项目,或返回上一级菜单;
2、液晶屏显示驱动正常
二、构建目录结构
1、例程目录结构如下:
图中只有子菜单1里面写了执行程序。
2、构建目录
/*声明功能函数*/
void Function_11(void);
void Function_12(void);
/*目录组成结构体*/
struct menuItem
{
uint8_t menuNum; /*当前菜单条目数*/
char *prtStr; /*当前项目要显示的内容*/
void (*fun)(void); /*当前项目对应的功能函数*/
struct menuItem *childrenMenu_T; /*当前项目的子菜单*/
struct menuItem *parentMenu_T; /*当前项目的父菜单*/
};
/*声明所需子目录*/
struct menuItem func01Menu[2];
struct menuItem func02Menu[3];
struct menuItem func03Menu[4];
/*定义母目录,并指定与子目录的关联关系*/
struct menuItem mainMenu[3]=
{
{3,(char *)"Func_01",NULL,func01Menu,NULL},
{3,(char *)"Func_02",NULL,func02Menu,NULL},
{3,(char *)"Func_03",NULL,func03Menu,NULL},
};
/*定义子目录,并指定他们的关联关系*/
struct menuItem func01Menu[]=
{
{2,(char *)"Func_11",Function_11,NULL,mainMenu},
{2,(char *)"Func_12",Function_12,NULL,mainMenu},
};
/*定义子目录,并指定他们的关联关系*/
struct menuItem func02Menu[]=
{
{3,(char *)"Func_21",NULL,NULL,mainMenu},
{3,(char *)"Func_22",NULL,NULL,mainMenu},
{3,(char *)"Func_23",NULL,NULL,mainMenu},
};
/*定义子目录,并指定他们的关联关系*/
struct menuItem func03Menu[]=
{
{4,(char *)"Func_31",NULL,NULL,mainMenu},
{4,(char *)"Func_32",NULL,NULL,mainMenu},
{4,(char *)"Func_33",NULL,NULL,mainMenu},
{4,(char *)"Func_34",NULL,NULL,mainMenu},
};
3、创建目录索引信息
struct menuItem *ptrSelectMenu; /*菜单结构体指针*/
uint8_t g_ucSelectItemNum; /*此变量是记录当前要显示本级菜单的第几个项目*/
uint8_t g_ucMenuRefreshEn = 1; /*此变量记录菜单刷新使能*/
4、创建菜单显示和按键回调函数
void MenuDisp(void);
void KeyUP_CallBack(void);
void KeyCenter_CallBack(void);
void KeyDown_CallBack(void);
三、编辑菜单显示和按键回调函数
1、编辑菜单显示函数
/*刷新菜单界面*/
void MenuDisp(void)
{
uint8_t i;
LCD_Clear();
for(i=0;i<ptrSelectMenu->menuNum;i++)
{
LCD_DispStr8x16(1+i*2,1,(ptrSelectMenu+i)->prtStr);
if(i == g_ucSelectItemNum)/*如果是选择条目,显示选择符号*/
{
LCD_DispStr8x16(1+i*2,120,"C");
}
}
}
2、编辑按键回调函数
/*更改菜单选择项目*/
void KeyUP_CallBack(void)
{
if(++g_ucSelectItemNum >= (ptrSelectMenu->menuNum))
{
g_ucSelectItemNum = 0;
}
}
/*执行菜单选择项目*/
void KeyCenter_CallBack(void)
{
if(((ptrSelectMenu+g_ucSelectItemNum)->fun) != NULL)/*执行对应程序*/
{
g_ucMenuRefreshEn = 0;/*禁止菜单刷新*/
(ptrSelectMenu+g_ucSelectItemNum)->fun();/*执行程序*/
}
else if((ptrSelectMenu+g_ucSelectItemNum)->childrenMenu_T != NULL)/*如果此项目有子菜单*/
{
ptrSelectMenu = (ptrSelectMenu+g_ucSelectItemNum)->childrenMenu_T;
g_ucSelectItemNum = 0;
g_ucMenuRefreshEn = 1;/*允许菜单刷新*/
}
}
/*退出当前运行项目,返回上级菜单*/
void KeyDown_CallBack(void)
{
if((ptrSelectMenu+g_ucSelectItemNum)->parentMenu_T != NULL)/*如果此项目有父菜单*/
{
ptrSelectMenu = (ptrSelectMenu+g_ucSelectItemNum)->parentMenu_T;
g_ucSelectItemNum = 0;
g_ucMenuRefreshEn = 1;/*允许菜单刷新*/
}
}
3、编辑功能函数
随意编辑了两个功能函数,用户可以根据自己的情况添加;
void Function_11(void)
{
LCD_Clear();
LCD_DispStr8x16(1,1,"function 11");
}
void Function_12(void)
{
LCD_Clear();
LCD_DispStr8x16(1,1,"function 12");
}
四、使用
1、初始化菜单
ptrSelectMenu = mainMenu;/*初始化选择菜单*/
g_ucSelectItemNum = 0;/**/
2、按键回调和菜单刷新
/*按键操作*/
switch(keyValue_E)
{
case KEY_UP:
KeyUP_CallBack();
break;
case KEY_CENTER:
KeyCenter_CallBack();
break;
case KEY_DOWN:
KeyDown_CallBack();
break;
default:
break;
}
keyValue_E = KEY_NONE;
/******************************/
/*刷新菜单*/
if(g_ulRunTime - menuRefreshGap >500)
{
menuRefreshGap = g_ulRunTime;
if(g_ucMenuRefreshEn == 1)/*如果允许刷新菜单*/
{
MenuDisp();
}
}
结束:
没了。
展示一下:
单片机菜单
整个项目下载见:
https://download.csdn.net/download/qq_39649731/87427494?spm=1001.2014.3001.5503