【原创分享】单片机菜单功能的设计(节点)----2009.07
2013-08-23 09:38
357 查看
恩,上次由于总经理有说要做一个彩屏的LCD遥控器,呵呵,用ARM或者AVR32,真高级。还好 我都曾经弄过。
由于屏幕还在挑选中 (NAKIA的那几款手机的不错 资料也多),自己有个 给个休假的同事拿走了 哎。所以先做了个简单的菜单。
恩 首先要把参考资料告诉大家 《基于节点编号的通用树状菜单设计方法与实现》这个PDF给了我很大的提示,基本思路还是与上相同 但是 其方法中的 子项的处理感觉模糊。
所以 用了自己的方法写了个完整的 建立在 TS-12664-3的字库型液晶上。换屏只是换LCD部分程序,影响不大 这里主要是菜单的实现。
基于节点编号的通用树状菜单设计方法与实现一文对节点的方法解析得是很清楚的,而我的有点偏差,ID定义还是一样方法,只是一个菜单的项的子菜单定义有别
ID:1
遥控器--->子项为11
收音机--->子项为12
电视机--->子项为13
还是看看完整的程序吧。
算是一个很简单的程序了,由于TS-12864-3的反白存在很大问题绘图模式来实现会扰屏,放弃,用了‘<---'来标示。
ENTER时进入下级菜单,ESC时返回上级菜单,UP,DOWN选择菜单项
不知道大家有注意到 这样的方法的缺陷没有,其实有两个致命的缺陷
1.菜单项不能多余10个
2.深度不能过多
第一个问题 由于是放大10倍 所以 菜单项的数目就不能多于10个 否则菜单项的ID与 子菜单重复了
第二个问题 由于用16为整数时 就是65536 也就是5层深度,如果高于5层 就要用长整形 很明显不划算
所以此方法 仅仅是实现一个菜单的设计,同时仅适用于简单的菜单设计 如果还是有兴趣的朋友 可以一起探讨下用什么样的方法能处理的更好
呵呵 我也是在追索。
最后附图几张破手机拍的不够清晰 还是能看 O(∩_∩)O~
由于屏幕还在挑选中 (NAKIA的那几款手机的不错 资料也多),自己有个 给个休假的同事拿走了 哎。所以先做了个简单的菜单。
恩 首先要把参考资料告诉大家 《基于节点编号的通用树状菜单设计方法与实现》这个PDF给了我很大的提示,基本思路还是与上相同 但是 其方法中的 子项的处理感觉模糊。
所以 用了自己的方法写了个完整的 建立在 TS-12664-3的字库型液晶上。换屏只是换LCD部分程序,影响不大 这里主要是菜单的实现。
基于节点编号的通用树状菜单设计方法与实现一文对节点的方法解析得是很清楚的,而我的有点偏差,ID定义还是一样方法,只是一个菜单的项的子菜单定义有别
ID:1
遥控器--->子项为11
收音机--->子项为12
电视机--->子项为13
还是看看完整的程序吧。
#include "avr/io.h" #include "lcd/lcd.h" #include "delay/delay.h" //#include "data.h" #define NULL 0 #define MENUNO 10 //菜单数目 #define PRONO 4 //程序数目 #define uchar unsigned char #define uint unsigned int #define KEYPORT PORTD #define KEYPIN PIND typedef struct menu{ uint ID; //菜单ID char *name[10]; //菜单项描叙 uchar total,cur,line; //总项,当前选择项,以及屏幕当前停留在哪行(1-4行); struct menu *esc; }MENU; //我的菜单项的结构定义 MENU menus[MENUNO]={ { 1,{"遥控器","收音机","学习机","电视机","VCD","音响"}, 6,0,0,NULL }, { 11,{"三星","LG","康佳"}, 3,0,0,NULL }, { 12,{"建设中"}, 1,0,0,NULL }, { 13,{"建设中"}, 1,0,0,NULL }, { 14,{"建设中"}, 1,0,0,NULL }, { 15,{"建设中"}, 1,0,0,NULL }, { 16,{"建设中"}, 1,0,0,NULL }, { 111,{"TM79","TM85","TM86","TM87"}, 4,0,0,NULL }, { 112,{"建设中"}, 1,0,0,NULL }, { 113,{"建设中"}, 1,0,0,NULL }, }; volatile uchar i,j,temp,data,lin,keyflag,key; volatile MENU *pmenu,*ptemp; volatile uint menuid[MENUNO]={1,11,12,13,14,15,16,111,112,113}; volatile char *se="<--"; void tm79pro(void); void tm85pro(void); typedef struct menup{ uint ID; void (*mp)(); }MP; volatile MP menupro[PRONO]={ {1111,tm79pro}, {1112,tm85pro} }; //-----------------------------------------------// //---------------程序区--------------------------// //-----------------------------------------------// void tm79pro(void) { uchar j; char *p="你选择的是TM79"; clr_screen(); lcd_pos(1,0); for(j=0;j<16;j++) { lcd_wdat(*(p+j)); } } void tm85pro(void) { uchar j; char *p="你选择的是TM85"; clr_screen(); lcd_pos(1,0); for(j=0;j<16;j++) { lcd_wdat(*(p+j)); } } uchar menuidcheck(uint id) { uchar i; for(i=0;i<MENUNO-1;i++) { if(id==menuid[i]) return 1; } return 0; } MENU *getmenu(uint id) { uchar i; for(i=0;i<MENUNO-1;i++) { if(id==menuid[i]) return &menus[i]; } return NULL; } //当前只定义ESC键各个地址 void menuinit(void) { for(i=0;i<MENUNO-1;i++) { //menus[i].enter=getmenu(menus[i].ID*10+menus[i].cur+1); //获取下个子项菜单地址 如果没有 //没有下层菜单 则为空 if(menus[i].ID/10==0) menus[i].esc=&menus[0]; else menus[i].esc=getmenu(menus[i].ID/10); } } //显示当前菜单的内容 void display(void) { uchar i,j,num,curr,start; char *name; num=pmenu->total; curr=pmenu->cur; lin=pmenu->line; if(num>4) num=4; start=curr-lin; clr_screen(); for(i=0;i<num;i++) { name=pmenu->name[start]; lcd_pos(i+1,0); for(j=0;j<16;j++) { if((*(name+j))==('\0')) break; lcd_wdat(*(name+j)); } if(i==lin) { for(j=0;j<16;j++) { if((*(se+j))==('\0')) break; lcd_wdat(*(se+j)); } } start++; } // changeb(lin); } uchar keyscan(void) { uchar i; if((KEYPIN|0xe4)==0xff) { keyflag=0; return 0; } delay1ms(100); if((KEYPIN|0xe4)==0xff) return 0; for(i=0;i<7;i++) { if((KEYPIN&(1<<i))==0) { if(i!=2) return (i+1); } } return 0; } void runpro(void) { uint tempID; uchar i; tempID=(pmenu->ID)*10+(pmenu->cur)+1; for(i=0;i<PRONO;i++) { if(tempID==menupro[i].ID) { menupro[i].mp(); } } } int main(void) { pmenu=menus; keyflag=0; DDRB=0XFF; PORTB=0X00; DDRA=0XFF; PORTA=0X00; DDRD=0X00; PORTD=0XFF; menuinit(); lcd_init(); display(); while(1) { key=keyscan(); if(key!=0) { if(keyflag==0) { keyflag=1; if(key==1) //UP { if((pmenu->cur)!=0) { pmenu->cur-=1; if((pmenu->line)!=0) pmenu->line-=1; display(); } } else if(key==2) //DOWN { if((pmenu->cur)!=((pmenu->total)-1)) { pmenu->cur+=1; if((pmenu->line)!=3) pmenu->line+=1; display(); } } else if(key==4) //ENTER { ptemp=getmenu((pmenu->ID)*10+(pmenu->cur)+1); if(ptemp!=NULL) { pmenu=ptemp; display(); } else runpro(); } else if(key==5) //ESC { pmenu->cur=0; pmenu->line=0; pmenu=pmenu->esc; display(); } } } } }
算是一个很简单的程序了,由于TS-12864-3的反白存在很大问题绘图模式来实现会扰屏,放弃,用了‘<---'来标示。
ENTER时进入下级菜单,ESC时返回上级菜单,UP,DOWN选择菜单项
不知道大家有注意到 这样的方法的缺陷没有,其实有两个致命的缺陷
1.菜单项不能多余10个
2.深度不能过多
第一个问题 由于是放大10倍 所以 菜单项的数目就不能多于10个 否则菜单项的ID与 子菜单重复了
第二个问题 由于用16为整数时 就是65536 也就是5层深度,如果高于5层 就要用长整形 很明显不划算
所以此方法 仅仅是实现一个菜单的设计,同时仅适用于简单的菜单设计 如果还是有兴趣的朋友 可以一起探讨下用什么样的方法能处理的更好
呵呵 我也是在追索。
最后附图几张破手机拍的不够清晰 还是能看 O(∩_∩)O~
相关文章推荐
- {单片机}分享一个按键液晶多级菜单设计方法
- [原创]JWFD工作流引擎设计----节点匹配搜索算法(用于解决条件异步汇聚问题)
- 实现Web页面中级联菜单的设计/实现动态加载列表框/实现自动刷新页面/实现Web页面的局部动态更新/实现自动完成功能
- 开发人员系统功能设计常用办公软件分享
- 开发人员系统功能设计常用办公软件分享
- mui 底部导航菜单功能(原创)
- Android入门教程(十)之-----Menu功能菜单设计 (转)
- 站内消息的设计2.0【原创分享】
- 功能测试机设计-MFC and C++ 以及单片机 C
- 开发人员系统功能设计常用办公软件分享
- [原创]通过点击节点或选择节点前checkbox实现树节点单选功能!
- 分享15个漂亮的导航菜单设计
- 开发人员系统功能设计常用办公软件分享
- 0) 原创的一套泛型源代码,用于改善STL的易用性,效率,功能增强。(拿出来和朋友们分享)
- c#小软件(SaveClassic)开发手记--(2)数据设计,IE右键菜单调用exe功能
- 对于想用OS但又觉得单片机资源太过紧张,状态机是个不错的选择---分享一种状态机设计方法
- 没有功能需求设计文档?对不起,拒绝开发!【分享】
- 站内消息的设计1.0【原创分享】
- [原创]有相同父节点的一组子节点中只能选择一个,实现树中节点的单选功能!
- 分享50个使用非比寻常导航菜单设计的创意网站