仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
制作出来的LCD12864菜单实物图如下:
单片机源程序如下:
- /*
- 名称:GXD LCD多层菜单 v1.2
- 作者:TranSmart
- 特点:
- 可以在液晶LCM上显示最大254层深度的菜单,可以非常方便的使用和移植。
- 字符型显示适用于St7920控制芯片。
- 图像显示适用于st7656控制芯片,不带字库要自己实现汉字字符显示
- 在图像模式下支持焦点菜单反白,
- 焦点菜单反白流程是:
- 1.调用 LCD_disp_SetReverse(1),打开液晶反白显示,以后的输出都是反白显示
- 2.输出焦点菜单内容
- 3.调用 LCD_disp_SetReverse(0),关闭液晶反白显示,以后的输出都是正常显示
- 可以根据此流程,在各种控制芯片上实现反白显示。
- 历史:
- 2009-9-22 添加在图形模式下焦点行反白的功能
- 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:\Keil\C51\BIN\
- 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:\KEIL\VW_C.DLL
- Dialog DLL: TP51.DLL V2.48b
- 版权声明:
- 义务:
- 1.如果您在使用中发现任何BUG,请通知gongxd@126.com,我会及时改正,并给您一份最新的代码
- 2.请保留本声明
- 权利:
- 如果您同意履行上面的义务,您就可以完全免费将代码应用于任何商业非商业用途
- 但本代码版权归中国传惠gongxd@126.com 所有,否则严禁使用本代码
- 建议:
- 如果您作了什么改进希望能通知gongxd@126.com,最好能共享一下,
- 我也会给您一份 最新 的代码,共同进步嘛
- 后话:大家都不容易,如果您觉得这东西有点用,就尽情传播吧
- */
- #include "menu.h"
- #include "menu_res.h"
- //菜单是否更新 1是 0否
- unsigned char MenuDisPlayUpdate;
- //所有菜单板的个数
- #define MenuAllCount sizeof(MenuPanel)/sizeof(MenuPanelStruct)
- Menu_Statestruct Menu_State;//菜单状态定义
- //=================================================================================栈函数
- //栈大小,菜单深度
- #define StackSize MenuDeep
- //声明堆栈元素类型
- typedef Menu_Statestruct StackElementType;
- //栈元素数组声明
- StackElementType MenuParentStack[StackSize];
- //栈顶
- unsigned char StackTOP;
- //栈初始化
- void StackINI()
- {
- StackTOP=0;
- }
- //测试栈是否空 1 是 0 否
- unsigned char StackEmpty()
- {
- return StackTOP==0;
- }
- //测试栈是否满 1 是 0 否
- unsigned char StackFull()
- {
- return StackTOP==StackSize;
- }
- //出栈
- StackElementType StackPOP()
- {
- if (StackTOP==0)
- {
- return MenuParentStack[0];
- }
- StackTOP--;
- return MenuParentStack[StackTOP];
- }
- //入栈
- void StackPush(StackElementType INElement)
- {
- if (StackTOP==StackSize)
- {
- return;
- }
- MenuParentStack[StackTOP]=INElement;
- StackTOP++;
- }
- //=================================================================================菜单函数
- //已经到最顶了
- void StackEmptyErr()
- {
- unsigned char code MenuTopErrMsg[]=
- {"已经到最顶了"};
- LCD_disp_CLS();
- LCD_disp_printR(MenuTopErrMsg,1,1);
- delayms(300);
- LCD_disp_CLS();
- //显示主菜单
- Menu_State.CurrentPanel=0;//本级菜单的菜单索引号
- Menu_State.ItemStartDisplay=0; //显示第一项对应的菜单条目索引
- Menu_State.FocusLine=1; //焦点在屏上是第几项
- }
- //菜单达到最大深度,栈满提示函数
- void StackFullErr()
- {
- unsigned char code MenuTopErrMsg[]=
- {"菜单栈满无法继续"};
- LCD_disp_CLS();
- LCD_disp_printR(MenuTopErrMsg,0,1);
- delayms(300);
- LCD_disp_CLS();
- }
- //默认菜单处理函数
- void voidNull()
- {
- }
- //光标所在行菜单项显示
- void UpdatedisplayMenu_Focus(unsigned char *MenuTxttmp)
- {
- #if FocusReverse==1
- //图像反色显示 0 否 1是,执行此命令后的所有操作均是按照设置显示
- LCD_disp_SetReverse(1);
- #endif
- //显示菜单项
- LCD_disp_printR(MenuTxttmp,MenuItemDisplayStartX,Menu_State.FocusLine+MenuItemDisplayStartY);
-
- //是否显示每行菜单前的指示 0 否 1是 ,推荐字符液晶使用,图形液晶用反白
- #if FocusPointDisply==1
- //显示前面的指针
- LCD_setpos(MenuPointX,Menu_State.FocusLine+MenuItemDisplayStartY);
- LCD_disp_Putchar(MenuPointASCII);
- #endif
-
- #if FocusReverse==1
- //图像反色显示 0 否 1是,执行此命令后的所有操作均是按照设置显示
- LCD_disp_SetReverse(0);
- #endif
- }
- //菜单显示更新函数
- void UpdatedisplayMenuPanel()
- {
- unsigned char i,DisplayLenCount;
- MenuItemStruct *p;
- p=MenuPanel[Menu_State.CurrentPanel].MenuPanelItem+Menu_State.ItemStartDisplay;
- DisplayLenCount=MenuPanel[Menu_State.CurrentPanel].MenuItemCount-Menu_State.ItemStartDisplay ;
- if (DisplayLenCount>ScreenHLine)
- {
- DisplayLenCount=ScreenHLine;
- }
- LCD_disp_CLS();
- for (i=0;i<DisplayLenCount;i++)
- {
- if (i==Menu_State.FocusLine)
- {
- //光标所在行菜单项显示,可以自定义反白显示等
- UpdatedisplayMenu_Focus(p->MenuTxt);
- }
- else
- {
- LCD_disp_printR(p->MenuTxt,MenuItemDisplayStartX,i+MenuItemDisplayStartY);
- }
- p++;
- }
- }
- //按键处理函数
- void UpdateMenuPanelkeyInner(unsigned char MenuKeyCode)
- {
- unsigned char i;
- //父菜单堆栈临时元素
- Menu_Statestruct tmpParent;
- //菜单是否更新 1是 0否
- MenuDisPlayUpdate=1;
- switch (MenuKeyCode)
- {
- //一直按着向上键
- case MenuKey_UpCon:
- case MenuKey_Up:
- if (Menu_State.FocusLine>0)
- {
- Menu_State.FocusLine--; //焦点在屏上是第几项
- }
- else
- {
- if (Menu_State.ItemStartDisplay>0)
- {
- Menu_State.ItemStartDisplay--;
- }
- else
- {
- Menu_State.ItemStartDisplay=MenuPanel[Menu_State.CurrentPanel].MenuItemCount-1;
- }
- }
- break;
- //一直按着向下键
- case MenuKey_DownCon:
- case MenuKey_Down:
- if ((Menu_State.ItemStartDisplay+Menu_State.FocusLine)<MenuPanel[Menu_State.CurrentPanel].MenuItemCount-1)
- {
- if (Menu_State.FocusLine<ScreenHLine-1 )
- {
- Menu_State.FocusLine++; //焦点在屏上是第几项
- }
- else
- {
- Menu_State.ItemStartDisplay++; //显示第一项对应的菜单条目索引
- }
- }
- else
- {
- Menu_State.FocusLine=0;
- Menu_State.ItemStartDisplay=0;
- }
- break;
- case MenuKey_Ok:
- i=Menu_State.FocusLine+Menu_State.ItemStartDisplay;
- if ((MenuPanel[Menu_State.CurrentPanel].MenuPanelItem+i)->MenuChildID==MenuNoChild)
- {
- (*((MenuPanel[Menu_State.CurrentPanel].MenuPanelItem+i)->CurrentOperate))();
- }
- else
- {
- if (StackFull()==0)
- {
- //父菜单显示在屏幕上的第一条条目
- tmpParent.ItemStartDisplay=Menu_State.ItemStartDisplay;
- //焦点在屏上是第几项
- tmpParent.FocusLine=Menu_State.FocusLine;
- //父菜单号
- tmpParent.CurrentPanel=Menu_State.CurrentPanel;//本级菜单的菜单索引号
- //入栈
- StackPush(tmpParent);
- Menu_State.CurrentPanel=(MenuPanel[Menu_State.CurrentPanel].MenuPanelItem+i)->MenuChildID;//父菜单的菜单索引号
- Menu_State.ItemStartDisplay=0; //显示第一项对应的菜单条目索引
- Menu_State.FocusLine=0; //焦点在屏上是第几项
-
- }
- else
- {
- //菜单达到最大深度,栈满提示函数
- StackFullErr();
- }
- };
- break;
- //一直按着返回键
- case MenuKey_CancelCon:
- case MenuKey_Cancel:
- //测试栈是否空 1 是 0 否
- if( StackEmpty()==0)
- {
- tmpParent=StackPOP();
- Menu_State.CurrentPanel=tmpParent.CurrentPanel;
- Menu_State.ItemStartDisplay=tmpParent.ItemStartDisplay; //显示第一项对应的菜单条目索引
- Menu_State.FocusLine=tmpParent.FocusLine; //焦点在屏上是第几项
-
- }
- else
- {
- //菜单已经到最顶了,栈空提示函数
- StackEmptyErr();
- }
- break;
- default:
- //菜单是否更新 1是 0否
- MenuDisPlayUpdate=0;
- break;
- }
- }
- void UpdateMenuPanelkey(unsigned char MenuKeyCode)
- {
- if (MenuKeyCode==MenuKey_Null)
- {
- return;
- }
- //弄这两个函数并列目的是减小RAM使用
- UpdateMenuPanelkeyInner(MenuKeyCode);//更新按键
- //菜单是否更新 1是 0否
- if (MenuDisPlayUpdate==1)
- {
- UpdatedisplayMenuPanel();//更新菜单显示
- }
- }
- void init_Menu()
- {
- //菜单栈初始化
- StackINI();
- Menu_State.CurrentPanel=0;//本级菜单的菜单索引号
- Menu_State.ItemStartDisplay=0; //显示第一项对应的菜单条目索引
- Menu_State.FocusLine=1; //焦点在屏上是第几项
- UpdatedisplayMenuPanel();//更新菜单
- }
复制代码
所有资料51hei提供下载:
ST7565 串行液晶驱动 多层液晶菜单 Proteus仿真 ST7565 串行液晶驱动.rar
(136.09 KB, 下载次数: 210)
|