单片机液晶多级菜单的程序写法

单片机液晶多级菜单的程序写法

    • 传统单片机液晶菜单写法
    • 函数指针法写液晶多级菜单

传统单片机液晶菜单写法

一般用单片机写液晶菜单都是通过大量标志位配合if else语句,或是switch case语句来完成当前液晶显示位置记录以及跳转的情况,这种写法往往会出现标志位多,代码冗余度高,程序中套用大量的条件判断语句,使得程序难以维护和升级。本文介绍了一种通过函数指针的方法来实现多级菜单的写法,程序通俗易懂,且易于维护。

函数指针法写液晶多级菜单

extern void (*KeyFuncPtr)(void); 
typedef struct
{
	  unsigned int KeyIndex;	//当前所在的位置,类似于索引号,目的是为了告诉用户当前位置下需要执行的函数  
	  unsigned int KeyUp;  //当前按下了向上按键,按下后需要跳转到下一幅菜单的KeyIndex的值
	  unsigned int KeyDown;  //当前按下了向下按键,按下后需要跳转到下一幅菜单的KeyIndex的值
	  unsigned int KeyLeft;  //当前按下了向左按键,按下后需要跳转到下一幅菜单的KeyIndex的值
	  unsigned int KeyRight;  //当前按下了向右按键,按下后需要跳转到下一幅菜单的KeyIndex的值
	  unsigned int KeyEnter; //当前按下了确定按键,按下后需要跳转到下一幅菜单的KeyIndex的值
	  unsigned int KeyEsc; 	//当前按下了取消按键,按下后需要跳转到下一幅菜单的KeyIndex的值
	  void (*CurrentOperate)(void);  //当前位置下需要执行的函数
}MeunTabStruct;

首先定义了结构体用来记录菜单的位置,以及按键该按键后要跳转的函数位置,KeyIndex变量主要做唯一索引用,用来给每一幅液晶画面一个唯一标识,上下左右确定取消按键目的是为了记录在当前KeyIndex下,按下这些按键会跳转到的下一个KeyIndex的索引值是多少,CurrentOperate函数指针是记录当前KeyIndex索引下需要执行的函数。

大致代码如下:
Menu.h

#ifndef _MENU_H_ 
#define _MENU_H_ 
extern void (*KeyFuncPtr)(void); 
typedef struct
{
      unsigned int KeyState;	        //当前状态索引号
	  unsigned int KeyEnter;            //按下"确认"键时转向的状态索引号
	  unsigned int KeyEsc;              //按下"取消"键时转向的状态索引号 
      unsigned int KeyUp;               //按下"向上"键时转向的状态索引号
	  unsigned int KeyDown;             //按下"向下"键时转向的状态索引号
	  unsigned int KeyLeft;             //按下向左键时转向的状态索引号
	  unsigned int KeyRight;            //按下向右键时转向的状态索引号
	  void (*CurrentOperate)(void);   //当前状态应该执行的功能操作 
}MeunTabStruct;
void DispFirstSectionMenu(void);
void DispSecondSection1Menu(void);
void DispSecondSection2Menu(void);
#endif

Menu.c

#include "Menu.h"
onst MeunTabStruct   KeyTab[]=
{
//	  	|-----------> Index
//		|   Enter 
//	  	|	  |    Esc
//      |	  |     |    up
//      |     |		|    |   down
//      |     |  	|    |    |   left
//      |     |  	|    |    |    |   right
//      |     |  	|    |    |    |	|		      |--->功能函数
//      |     |  	|    |    |    |    |             |
/**************************一级主菜单***************************************/ 
       {0,    5, 	0, 4,   1,   0,   0,      (*DispFirstSectionMenu)}, //一级菜单功能1
       {1,    6,	0,   0,   2,   1,   1,    (*DispFirstSectionMenu)}, //一级菜单功能2
       {2,    7,    0,   1,   3,   2,   2,    (*DispFirstSectionMenu)}, //一级菜单功能3
       {3,    8,    0,   2,   4,   3,   3,    (*DispFirstSectionMenu)}, //一级菜单功能4
	   {4,    9,    0,   3,   0,   4,   4,    (*DispFirstSectionMenu)}, //一级菜单功能5                 
/*************************功能1二级菜单*************************/ 
       {5,    5,    0,   5,   5,   5,   5,    (*DispSecondSection1Menu)},//功能1二级菜单
/*************************功能2二级菜单*******************************/
       {6,    6,    1,   6,   6,   6,   6,    (*DispSecondSection2Menu)}, //功能2二级菜单

void DispFirstSectionMenu(void)
{
//液晶屏幕显示处理
}
void DispSecondSection1Menu(void)
{//液晶屏幕显示处理
}
void DispSecondSection2Menu(void)
{//液晶屏幕显示处理
}
void MenuProc(unsigned int KeyValue)
{
	case _KEY_NO:
	 		break;	
	 case _ESC_KEY:
	  	   LastKeyFuncIndex = KeyFuncIndex; //存取上一次函数的索引
		   KeyFuncIndex = KeyTab[KeyFuncIndex].KeyEsc;
	   	   KeyFuncPtr = KeyTab[KeyFuncIndex].CurrentOperate;//按下取消键后,	                                              
	       (*KeyFuncPtr)();  
	 break;            
	 case _ENT_KEY:
	  	   LastKeyFuncIndex = KeyFuncIndex; //存取上一次函数的索引
		   KeyFuncIndex = KeyTab[KeyFuncIndex].KeyEnter;
	   	   KeyFuncPtr = KeyTab[KeyFuncIndex].CurrentOperate;//按下确认键后,	                                              
		  (*KeyFuncPtr)();
	 break;            
	 case _UP_KEY:
	  	   BK = 1;
		   BKLightCount = 0;
	  	   LastKeyFuncIndex = KeyFuncIndex; //存取上一次函数的索引
	 	   KeyFuncIndex = KeyTab[KeyFuncIndex].KeyUp;
	 	 	   KeyFuncPtr = KeyTab[KeyFuncIndex].CurrentOperate;//按下向上键后,	                                              
	             	   (*KeyFuncPtr)();
	 break;             
	 case _LEFT_KEY:
	 	   LastKeyFuncIndex = KeyFuncIndex; //存取上一次函数的索引
		   KeyFuncIndex = KeyTab[KeyFuncIndex].KeyLeft;
	   	   KeyFuncPtr = KeyTab[KeyFuncIndex].CurrentOperate;//按下确认键后,	                                              
	       (*KeyFuncPtr)();
	 break;
	 case _DOWN_KEY:
	 	   LastKeyFuncIndex = KeyFuncIndex; //存取上一次函数的索引
	 	   KeyFuncIndex = KeyTab[KeyFuncIndex].KeyDown;
	       KeyFuncPtr = KeyTab[KeyFuncIndex].CurrentOperate;//按下向下键后,	                                              
	       (*KeyFuncPtr)(); 
	 break;
	 case _RIGHT_KEY:
	       LastKeyFuncIndex = KeyFuncIndex; //存取上一次函数的索引
		   KeyFuncIndex =  KeyTab[KeyFuncIndex].KeyRight;
	   	   KeyFuncPtr = KeyTab[KeyFuncIndex].CurrentOperate;//按下确认键后,	                                              
	       (*KeyFuncPtr)();
	 break;      
}

main.c

int main()
{
	while(1)
	{
		MenuProc(GetKeyValue());//这里的GetKeyValue是获取按键值的意思,可以参考我的个人博客中关于按键函数的编写
	}
}

你可能感兴趣的:(单片机,嵌入式硬件,开发语言)