大家讨论下基于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索引
一般来说 这种菜单的可移植性比较不好!!
可移植性好的菜单又比较复杂 容易 出错!
以前写的 随便粘贴点 好像是3级的
INT8U SeqNum; // 数组Dict_Function中的某个元素在数组Dict_Function中位于第SeqNum位
struct {
INT8U IndexWork;
INT8U IndexUp;
INT8U IndexDown;
INT8U IndexEnter;
INT8U IndexBack;
void (*Ptr)(); // 网络或论文上有些源程序将Ptr命名为CurrentOperate,很显然:命名为CurrentOperate更好一点。
} code Dict_Function[] = {
// IndexWork
// | IndexUp
// | | IndexDown
// | | | IndexEnter
// | | | | IndexBack
// | | | | | (*Ptr)()
// | | | | | |
{0, 2, 1, 3, 0, Show_Screen0},
{1, 0, 2, 6, 1, Show_Screen1},
{2, 1, 0, 9, 2, Show_Screen2},
/***********************************/
{3, 5, 4, 12, 0, Show_Screen00},
{4, 3, 5, 13, 0, Show_Screen01},
{5, 4, 3, 14, 0, Show_Screen02},
//-------------------------------
{6, 8, 7, 15, 1, Show_Screen10},
{7, 6, 8, 16, 1, Show_Screen11},
{8, 7, 6, 17, 1, Show_Screen12},
//-------------------------------
{9, 11, 10, 18, 2, Show_Screen20},
{10, 9, 11, 19, 2, Show_Screen21},
{11, 10, 9, 20, 2, Show_Screen22},
/***********************************/
{12, 12, 12, 12, 3, Show_Screen000},
{13, 13, 13, 13, 4, Show_Screen010},
{14, 14, 14, 14, 5, Show_Screen020},
{15, 15, 15, 15, 6, Show_Screen100},
{16, 16, 16, 16, 7, Show_Screen110},
{17, 17, 17, 17, 8, Show_Screen120},
{18, 18, 18, 18, 9, Show_Screen200},
{19, 19, 19, 19, 10, Show_Screen210},
{20, 20, 20, 20, 11, Show_Screen220},
};
一周热门 更多>