大家讨论下基于LCD的菜单函数的编写,有我最近正在写的一个

2020-02-01 16:27发布

大家讨论下基于LCD的菜单函数的编写.

我的情况是12864不带字库LCD,4*4键盘.
以前也做过类似的,不过还是用51汇编做的,现在回头看看很不规范
因为项目时间比较紧,而且用的STM32以前也没用过,本来想用图标来做菜单,想了下还是用文字的方式
一个界面四行四个菜单,反显当前选中菜单,支持滚动菜单,程序肯定还有冗余的地方,不过时间关系没有太多思考

在网上搜了下,找到一些参考,但都不能直接拿来用,于是改了下,下面是我定义的结构体
typedef struct
{
        const UCHAR NowMenu;   //菜单索引
        const UCHAR UpMenu;    //向上菜单
        const UCHAR DownMenu;  //向下菜单
        const UCHAR BackMenu;  //返回菜单
        const UCHAR EnterMenu;  //进入菜单
        const UCHAR UpMenuGroup[4];   //向上菜单显示
        const UCHAR DownMenuGroup[4]; //向下菜单显示
        const UCHAR **String;   //指向当前菜单字库
        const UCHAR EnterProgram;  //是否按下确认键后执行程序
        void (*Subs)();         //按下确认键后执行的程序
}Menu;


typedef struct
{
        UCHAR NowMenu;         //当前菜单
        UCHAR UpMenu;          //向上
        UCHAR DownMenu;        //向下
        UCHAR BackMenu;        //返回
        UCHAR EnterMenu;       //确认
        UCHAR MenuGroup[4];    //当前显示菜单
}MenuRam;


主程序如下:
  while(1)
  {         
    if(Flag20ms==1)
    {
      Flag20ms=0;
      DivKey();        //读键
    }
    if(1==FlagKeyDo)  //是否按下了一次键
    {
            FlagKeyDo = 0;
            switch(TempKeyValue)   //判断键值
            {
                    case UPKEY:{NowMenuStruct.NowMenu=NowMenuStruct.UpMenu;
                    }break;
                    case DOWNKEY:{NowMenuStruct.NowMenu=NowMenuStruct.DownMenu;
                    }break;
                    case BACKKEY:{NowMenuStruct.NowMenu=NowMenuStruct.BackMenu;
                    }break;
                    case ENTERKEY:{
                            if(MenuStruct[NowMenuStruct.NowMenu].EnterProgram==0)
                                    NowMenuStruct.NowMenu=NowMenuStruct.EnterMenu;
                            else
                                    (MenuStruct[NowMenuStruct.NowMenu].Subs)();
                    }break;
                    default:break;
            }
            MenuStructInit();     //更新菜单
            InitDisplay();
    }
  }
}

void MenuStructInit(void)
{
        UCHAR i;
        NowMenuStruct.UpMenu = MenuStruct[NowMenuStruct.NowMenu].UpMenu;      
        NowMenuStruct.DownMenu = MenuStruct[NowMenuStruct.NowMenu].DownMenu;
        NowMenuStruct.BackMenu = MenuStruct[NowMenuStruct.NowMenu].BackMenu;
        NowMenuStruct.EnterMenu = MenuStruct[NowMenuStruct.NowMenu].EnterMenu;
        if(XCDis()==0xff)                     //如当前菜单不在显示菜单行列,需更新当前显示菜单,即实现滚屏
        {
                if(TempKeyValue==DOWNKEY)
                        for(i=0;i<4;i++)
                                NowMenuStruct.MenuGroup=MenuStruct[NowMenuStruct.NowMenu].DownMenuGroup;
                if(TempKeyValue==UPKEY||TempKeyValue==ENTERKEY||TempKeyValue==BACKKEY)
                        for(i=0;i<4;i++)
                                NowMenuStruct.MenuGroup=MenuStruct[NowMenuStruct.NowMenu].UpMenuGroup;
        }
}

void InitDisplay(void)
{       
        WritePicture(MenuStruct[NowMenuStruct.MenuGroup[0]].String,2,96,0,16,96);          //显示当前界面四个菜单
        WritePicture(MenuStruct[NowMenuStruct.MenuGroup[1]].String,2,96,2,16,96);
        WritePicture(MenuStruct[NowMenuStruct.MenuGroup[2]].String,2,96,4,16,96);
        WritePicture(MenuStruct[NowMenuStruct.MenuGroup[3]].String,2,96,6,16,96);
        CovDisplay(XCDis()*2,16,2,96);            //反显当前选中菜单
}

UCHAR XCDis(void)
{
        UCHAR x;
        for(x=0;x<4;x++)
        {
                if(NowMenuStruct.NowMenu == NowMenuStruct.MenuGroup[x])
                        return x;
        }       
        return 0xff;
}

在全局变量中定义菜单
我的一级菜单有7个选项,对应索引为1-7,如下定义:
Menu MenuStruct[42]=
{
  {0,0,0,0,0,{0,0,0,0},{0,0,0,0},(const UCHAR **)NONE,0,NULL                                                                  },
  {1,7,2,1,10,{1,2,3,4},{5,6,7,1},(const UCHAR **)FSSet,0,NULL                                                        //发送接收设置
  },
  {2,1,3,2,1,{2,3,4,5},{6,7,1,2},(const UCHAR **)DSet,0,NULL                                                                //数据包设置
  },
  {3,2,4,3,8,{3,4,5,6},{7,1,2,3},(const UCHAR **)ZDCheck,0,NULL                                                        //终端信息查询
  },
  {4,3,5,4,1,{4,5,6,7},{1,2,3,4},(const UCHAR **)TMSet,1,SetTime                                           //时间设置
  },       
  {5,4,6,5,1,{5,6,7,1},{2,3,4,5},(const UCHAR **)DCheck,0,NULL                                      //历史数据查询
  },
  {6,5,7,6,12,{6,7,1,2},{3,4,5,6},(const UCHAR **)FYZSet,0,NULL                                                        //频率阈值设置
  },
  {7,6,1,7,1,{7,1,2,3},{4,5,6,7},(const UCHAR **)DW,0,NULL                                                                //电网噪声仪
  },
.......
}
其中10为1的子菜单
8为3的子菜单
12为6的子菜单,其他的有的还没做

再定义
MenuRam NowMenuStruct;
初始化成1索引
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
95条回答
unsv
1楼-- · 2020-02-03 01:05
4楼的方法好,俺不喜欢反白  !麻烦
bad_fpga
2楼-- · 2020-02-03 03:11
 精彩回答 2  元偷偷看……
shamork
3楼-- · 2020-02-03 05:42
mark 等高手现身
gongxd
4楼-- · 2020-02-03 10:17
附源代码和例子

名称:GXD任意层深度菜单 v1.1
特点:可以在液晶LCM上显示最大254层深度的菜单,可以非常方便的使用和移植
作者:中国传惠 TranSmart  gongxd@126.com
日期:2009-8-2

历史:
2009-8-2 添加N层菜单功能,修改屏幕参数定义
2009-3-4 初始版本

编译环境:

IDE-Version:
uVision3 V3.33
Copyright (c) Keil Elektronik GmbH / Keil Software, Inc 2006

Tool Version Numbers:
工具链路径:C:KeilC51BIN
C Compiler: C51.Exe V8.05a
Assembler: A51.Exe
Linker/Locator: BL51.Exe V6.00
Librarian: LIB51.Exe V4.24
Hex Converter: OH51.Exe V2.6
CPU DLL: S8051.DLL V3.06
Dialog DLL: DP51.DLL V2.48b
Target DLL: C:KEILVW_C.DLL
Dialog DLL: TP51.DLL V2.48b

版权声明:
义务:
1.如果您在使用中发现任何BUG,请通知gongxd@126.com,我会及时改正,并给您一份最新的代码
2.请保留本声明

权利:
如果您同意履行上面的义务,您就可以完全免费将代码应用于任何商业非商业用途
但本代码版权归中国传惠gongxd@126.com 所有,否则严禁使用本代码

建议:
如果您作了什么改进希望能通知gongxd@126.com,最好能共享一下,
我也会给您一份 最新 的代码,共同进步嘛

后话:大家都不容易,如果您觉得这东西有点用,就尽情传播吧


点击此处下载 ourdev_466578.rar(文件大小:5K) (原文件名:GXD菜单1.1.rar)



//========================================== 用户配置参数============================

void init_Menu();//菜单初始化

void UpdateMenuPanelkey(unsigned char MenuKeyCode);//菜单按键更新

//菜单按键参数定义 根据实际键码修改
#define MenuKey_Null 0
#define MenuKey_Ok 0x05
#define MenuKey_Cancel 0x06
#define MenuKey_Up 0x07
#define MenuKey_Down 0x08


//===========================屏幕参数配置============
//一屏幕最大显示的行数
#define  ScreenHLine            4
//菜单深度,最低1层,最大254层
#define  MenuDeep               1

//菜单条目前面的指示位置列
#define  MenuPointX             0
//菜单条目前面的指示字符
#define  MenuPointASCII         '>'

//菜单条目显示的起始列
#define  MenuItemDisplayStartX  1
//菜单条目显示的起始行
#define  MenuItemDisplayStartY  0



//================================================== 用户配置参数====================



//菜单响应函数声明头文件=======================================================================
#include "Menu_Function.h"
//菜单处理函数
extern void MenuFuntion1();
extern void MenuFuntion2();

//菜单资源文件
#include "Menu_res.h"===========================================================================
//菜单条目格式
//{要显示的的菜单文本,子菜单号,功能函数地址)


MenuItemStruct code MenuMain[]={
{"主1 条目1",1,Null},
{"主1 条目2",2,Null},
{"主1 条目3",3,Null},
{"功能函数1",MenuHasFunction,MenuFuntion1},
{"主1 条目5",0,Null},
};

MenuItemStruct code MenuSub1[]={
{"次1 条目1",0,Null},
{"次1 条目2",0,Null},
{"功能函数2",MenuHasFunction,MenuFuntion2},
{"次1 条目4",0,Null},
{"次1 条目5",0,Null},
{"次1 条目6",0,Null},
};

MenuItemStruct code MenuSub2[]={
{"次2 条目1",0,Null},
{"次2 条目2",0,Null},
{"次2 条目3",0,Null},
};

MenuItemStruct code MenuSub3[]={
{"次3 条目1",0,Null},
{"次3 条目2",0,Null},
{"次3 条目3",0,Null},
{"次3 条目4",0,Null},
{"次3 条目5",0,Null},
{"次3 条目6",0,Null},
{"次3 条目7",0,Null},
{"次3 条目8",0,Null},
{"次3 条目9",0,Null},
};

//全部菜单列表        
MenuPanelStruct code MenuPanel[]={
{MenuPanelID(MenuMain)},
{MenuPanelID(MenuSub1)},
{MenuPanelID(MenuSub2)},
{MenuPanelID(MenuSub3)},
};
jchqxl
5楼-- · 2020-02-03 13:44
谢谢
sange
6楼-- · 2020-02-03 13:55
mark

一周热门 更多>