相信很多攻城狮都用过液晶屏,想写好一点的ui好像不太可能或且花费很多时间,直接写吧,感觉好像很零碎,coding都怕了。
下面介绍一个简单易用的菜单框架,你会发现它能做多层菜单而且结果清晰。
基本原理:
如上图液晶显示一屏我们定义为一个page,page中的项目定义为item;这样page就是item的容器了。当我们选中其中的一个item进去后是不是又是一个page呢,如下图。
这样的话每一个item的下面都对应一个page,这样是不是就构成一个多层的菜单了。
他们是什么关系呢?
一个page中有item,那么用结构体就可以实现啦;item下面又有page,那么在item中加一个page的指针指向item对应的page页。
前面都是从上到下的,那么怎么返回呢?
观察发现返回就是子page返回父page,这样在page结构体中假如一项父page的指针不就ok了。
具体实现请看源文件。
/******************************************************************************************************///主菜单//定义item项 //显示方式&序号 项目的名字 项目指向的页(page)const struct item main_item[]={ 0x00, 信息, &sms_page, 0x01, 设置, &setting_page, 0x02, 版本, &version_page, 0x03, 时间, &time_page, 0x04, 状态, 0, 0x05, 报警, 0, 0x06, 飞信, 0, 0x07, 问答, 0};//定义一个page 父页 该页的回调函数 该页的项 项的个数 const struct page mainpage={0,mainpagecallback,main_item,sizeof(main_item)/sizeof(struct item)};/*********************************************************************************************************/const struct page version_page={&mainpage,version_callback,0,0};/***************************************************************************************************************///定义item项 //显示方式&序号 项目的名字 项目指向的页(page)const struct item setting_item[]={ 0x10, 00.设0, 0, 0x11, 01.设1, 0, 0x12, 02.设2, 0, 0x13, 03.设3, 0, 0x14, 04.设4, 0, 0x15, 05.设5, 0, 0x16, 06.设6 你好, 0, 0x17, 07.设7, 0, 0x18, 08.设8, 0, 0x19, 09.设9, 0, 0x1a, 10.设10, 0 };const struct page setting_page={&mainpage,setting_callback,setting_item,sizeof(setting_item)/sizeof(struct item)};/***************************************************************************************************************/const struct page time_page={&mainpage,time_callback,0,0};/***************************************************************************************************************///定义item项 //显示方式&序号 项目的名字 项目指向的页(page)const struct item sms_item[]={ 0x10, 00., &sms_text_page, 0x11, 01., &sms_text_page, 0x12, 02., &sms_text_page, 0x13, 03., &sms_text_page, 0x14, 04., &sms_text_page, 0x15, 05., &sms_text_page, 0x16, 06., &sms_text_page, 0x17, 07., &sms_text_page, 0x18, 08., &sms_text_page, 0x19, 09., &sms_text_page, 0x1a, 10., &sms_text_page };const struct page sms_page={&mainpage,sms_callback,sms_item,sizeof(setting_item)/sizeof(struct item)};
menu.h:
#ifndef _menu_h_bab#define _menu_h_bab#include stm32f10x.h#include lcd.h#include key.h#define key_special 255 ///)使用,xx.为两位序号不要.一定要有,string是要显示的文字,最多能显示6个汉字 如果是两列显示则ptext,即为要显示的文本(最多2个汉字) */ const u8 typeandindex; const u8 *ptext; const struct page *pchildrenpage;};extern const struct page *ppage;void setmainpage(const struct page *pmainpage);void showmenu(const struct page *ppage);void showpage(const struct page *ppage);void showparentpage(void);void showitempage(void);void selpageitem(u8 itemindex);u8 menu_getselitem(void);void getshowlst(u8 *poutmin,u8 *poutmax);void keyselitem(u8 key);#endif
menu.c:
#include menu.h//保存选中的菜单项变量static u8 selitem=0;/**用于当前lcd列表中显示着哪几项高4位:最大序号低4为:最小序号*/static u8 listshow=0x00;const struct page *ppage;void selitemoflist(u8 index);void setmainpage(const struct page *pmainpage){ ppage=pmainpage;}/**获得当前选中的菜单项@return 返回菜单序号*/u8 menu_getselitem(void){ return selitem;}/**获取当前显示列表的范围@param poutmin 当前显示的最小序号@param poutmax 当前显示的最大序号*/void getshowlst(u8 *poutmin,u8 *poutmax){ *poutmin=listshow&0x0f; *poutmax=listshow>>4;}void showlist(u8 min,u8 max){ u8 i=0,index=0; #if menu_debug if(max-min>3) { lcd_clr_scr(); lcd_write_str(0,0,err:showlist>3); while (1); } if ((ppage->pitem[0].typeandindex & 0x10)==0)///<如果是使用列表方式 { lcd_clr_scr(); lcd_write_str(0,0,不是列表类型不能不能列出); while (1); } #endif lcd_clr_scr(); for (index=min;indexpitem[index].ptext); } listshow=(max
pitem[i].ptext); } } selpageitem(0);///function(key_special); } };/**显示父页(parentpage)*/void showparentpage(void){ ppage=ppage->pparent; showpage(ppage);}/**显示项目(item)下对应的页(page)*/void showitempage(void){ //如果该项下没有页,这警告或返回 if (ppage->pitem[menu_getselitem()].pchildrenpage ==0) { #if menu_debug lcd_clr_scr(); lcd_write_str(0,0,该项下无显示请修正); while (1); #else return; #endif } ppage=ppage->pitem[menu_getselitem()].pchildrenpage; //获得菜单项(item)对应的page showpage(ppage);}/**选择page中的item项@param itemindex page中item的索引号 0~7*/void selpageitem(u8 itemindex){ ///检查是否有错误调用#if menu_debug if (itemindex>=8) { lcd_write_str(0,0,设置菜单项溢出); return; }#endif///清除上次选中的 if (selitem4; min=listshow&0x0f; if (index>max) ///<超出最大当前显示的序号 { lcd_write_str(menu_getselitem()-min,0, ); min+=1; max+=1; showlist(min,max); listshow=(max=min)///); } else ///<低于最小当前显示最小序号 { lcd_write_str(menu_getselitem()-min,0, ); min-=1; max-=1; showlist(min,max); listshow=(maxpitem[0].typeandindex & 0x10)///itemnum-1)) break;; selitemoflist(index); break; } return; } switch(key) { case key_up: index=menu_getselitem()-1; if(indexitemnum-1; selpageitem(index); break; case key_down: index=menu_getselitem()+1; if(index>(ppage->itemnum-1)) index=0; selpageitem(index); break; case key_left: case key_right: index=menu_getselitem(); if (index(ppage->itemnum-1)) return; //右没有item项,无法选中右边项;所以返回 index+=4; //右边有item时把index定位到右边的item } else index-=4; //因为右边有item项时,左边一定有item项;因为是按顺序安排的 selpageitem(index); break; }} 篇幅有限,menuapp代码未贴出。
基于MCS-96单片机和数据融合技术实现机器人系统的应用方案
LED灯杆显示屏搭载智慧灯杆需求加速增长
SED电视机工作原理
氯霉素快速检测系统设备的原理及用途是什么
新能源补贴政策的逐渐退坡 比亚迪成最大补贴赢家
分享一个STM32菜单框架
浅谈3D打印技术与机器人自动化技术如何打印出球鞋
HGW35CC、EGH15CA、EGH20CA、EGH25SA、EGH30CA型号替换指南
面对网络攻击可以做些什么有效措施
如何提升天线的性能,影响它的因素有哪些
基于MAX5922的PSE系统电路的应用设计与实现
全新高性能、超值型APM32F465系列工业级MCU
剖析三元材料专利分布及技术走向 为我国专利申请人在该领域的专利布局提供参考
核电厂能够运营80多年才能真正的存活下来?
DEI ARINC 429线路接收器和接收器接口参数
OpenAI GPT-4升级?AI原生应用百度地图AI向导:已成功预判
光伏连接器企业快可电子创业板上市
半导体光刻工艺 光刻—半导体电路的绘制
宜科OS10S和OSM70系列光电传感器为物流设备高效运行保驾护航
AKH-0.66双M8双绕组电流互感器线缆的特点