单片机菜单-菜单数据结构
在单片机中如果需要一个可以便于维护的菜单程序,那么设计一个便于封装的菜单数据结构就是必不可少的了。
最近观看B站UP主有手也不会发布的视频后,发现其写的菜单数据结构尤为好用,这里用于记录,有误之处还望大家指正!
按键采用Multibutton开源框架有兴趣可去GitHub上搜索,也可私信我,我发源码。
struct MenuItem
{unsigned char menu_cnt; //当前菜单项目总数unsigned char * display_str; //当前菜单要显示的字符void (*subs)(); //选择某一菜单后要显示的功能函数struct MenuItem *children_menus; //当前项目的子菜单struct MenuItem *parent_menus; //当前项目的父菜单
};
从头到尾依次是:本级菜单所拥有的项目总数,当前项目所需要显示的菜单信息,所需要执行对应的菜单项目的回调函数,当前菜单的子菜单也就是下一级菜单,当前菜单的父菜单也就是上一级菜单。
在这本例移植中我是用了OLED12864进行显示
菜单数据,在此例子中共有两级菜单,每级菜单有三个项目
struct MenuItem parent_menu[] = {{3, (unsigned char *) "meat", NULL, NULL, NULL},
{3, (unsigned char *) "vegetable", NULL, NULL, NULL},
{3, (unsigned char *) "drinks", NULL, NULL, NULL},
};struct MenuItem childeren_menu1[] = {{3, (unsigned char *) "pork", fun1, NULL, parent_menu},
{3, (unsigned char *) "beef", fun2, NULL, parent_menu},
{3, (unsigned char *) "mutton", fun3, NULL, parent_menu},
};struct MenuItem childeren_menu2[] = {{3, (unsigned char *) "cabbage", fun4, NULL, parent_menu},
{3, (unsigned char *) "tomato", fun5, NULL, parent_menu},
{3, (unsigned char *) "potato", fun6, NULL, parent_menu},
};struct MenuItem childeren_menu3[] = {{3, (unsigned char *) "milk", fun7, NULL, parent_menu},
{3, (unsigned char *) "cola", fun8, NULL, parent_menu},
{3, (unsigned char *) "orange juice", fun9, NULL, parent_menu},
};
菜单显示函数
select_menu //此变量是菜单结构体指针
select_item_num //此变量是记录当前要显示本级菜单的第几个项目
void menu_display(void)
{unsigned char i;OLED_SetScreen(0);//清除OLED的缓存,即清屏for (i = 0;i < select_menu->menu_cnt;i++) {OLED_ShowString(32, i*12, (select_menu+i)->display_str, FONT_SIZE);//OLED显示对应的菜单项目名字信息if (i == select_item_num) OLED_ShowString(16, i*12, "->", FONT_SIZE);//如果是对应的项目则显示}OLED_RefreshGram();//将数据写入OLED中并显示
}//主循环中放入如下
//allow_switch表示是否允许切换 while(1){if (allow_switch) {allow_switch = 0;menu_display();}}
按键1单击表示本级菜单向下移动,双击表示返回上一级菜单
按键2单击表示本级菜单向上移动,双击表示进入下一级菜单
按键1处理回调函数
//recode变量可忽略,用于我自己的调试
void button1_callback_fun(void *btn, uint8_t event)
{unsigned char i;if ((event & SINGLE_CLICK) == SINGLE_CLICK) {//单击LED1_TOGGLE;//LED1翻转,用于调试时便于观察allow_switch = 1;//允许切换select_item_num++;//显示项目往下移if (select_item_num >= select_menu->menu_cnt) select_item_num = 0;//如果大于最大的显示项目回到第一个显示项目} else if ((event & DOUBLE_CLICK) == DOUBLE_CLICK) {//双击LED2_TOGGLE;//LED2翻转,用于调试时便于观察for (i = 0;i < select_menu->menu_cnt;i++) {//遍历是本级菜单哪一个项目要进入上一级菜单if (i == select_item_num) {//找到要进入上一级菜单的项目allow_switch = 1;//允许切换if ((select_menu->parent_menus != NULL) && (recode != 1)) {//上一级菜单是否为空select_menu = (select_menu+select_item_num)->parent_menus;//将菜单指针定位到上一级菜单select_item_num = 0;//回到上一级菜单从第一个项目开始}else if (recode == 1) {//可忽略recode = 0;}}}delay_ms(500);}}
按键2处理回调函数
void button2_callback_fun(void *btn, uint8_t event)
{unsigned char i;if ((event & SINGLE_CLICK) == SINGLE_CLICK) {//单击LED2_TOGGLE;//LED2翻转,用于调试时便于观察allow_switch = 1;//允许切换select_item_num--;//菜单往上移if (select_item_num < 0) select_item_num = select_menu->menu_cnt-1;//如果回到第一个项目仍然需要往上移,则回到最后一个项目} else if ((event & DOUBLE_CLICK) == DOUBLE_CLICK) {//双击LED3_TOGGLE;//LED3翻转,用于调试时便于观察for (i = 0;i < select_menu->menu_cnt;i++) {//遍历是本级菜单哪一个项目要进入下一级菜单if (i == select_item_num) {//找到要进入下一级菜单的项目allow_switch = 1;//允许切换if (select_menu->children_menus != NULL) select_menu = (select_menu+select_item_num)->children_menus;//下一级菜单是否为空else if (select_menu->subs != NULL) (select_menu+select_item_num)->subs();//如果回调函数不为空则执行对应的回调函数select_item_num = 0;//显示第一个项目}}delay_ms(500);}
}
单片机菜单-菜单数据结构相关推荐
- php 可编辑菜单,菜单的添加编辑
摘要: 上级菜单 菜单名称 排序 控制器 方法 菜单状态 保存 //加载layui的弹窗组件和form组件 layui.use(['layer','form'],function(){ var for ...
- 如何动态添加菜单/菜单项、子菜单、右键菜单
有关菜单的操作主要用到 CMenu 类,当然也可用相应 API 函数, CMenu 类只是 MFC 对 API 中操作菜单的函数的封装而已. 不过能用类就尽量用类,类的组织方式好呗,代码看着也舒服. ...
- GUI菜单——菜单条、菜单、子条目之间关系
菜单:注意区分三个概念:菜单条.菜单.菜单项 将菜单条添加到窗体,菜单条下面包括菜单,菜单下面可以使菜单或者菜单项 菜单项是最后一个.菜单后面有三角标示. 菜单条[文件] 子菜单--子条目 子条目 示 ...
- 基于CSS3飘带状3D菜单 菜单带小图标
这次我们要来分享一款很特别的CSS3菜单,菜单的外观是飘带状的,并且每一个菜单项有一个精美的小图标,鼠标滑过菜单项时,菜单项就会向上凸起,像是飘带飘动一样,形成非常酷的3D视觉效果.这款CSS3飘带状 ...
- 基于jQuery的下拉菜单菜单【02】,诸位上眼!!!
前言 接上次的话题,仍然是团队近期将会有大变化,最近确实有点蛋疼,对以后的规划神马的乱成一团,晚上也不想学习神马的了,有时候就什么都不做发现一晚上就莫名其妙的过去了...... 但是上班时候不行,没事 ...
- GTA5内置html菜单源码,【GTA5线上1.46版本免费内置菜单菜单】【5款目前最新可用的内置菜单可供选择】刷钱、套模型、无敌、传送...
功能上有线上刷钱,给其他玩家套模型 ,无敌 传送等等 首先先回答大家几个关于内置菜单的问题 1.内置菜单会封号嘛? 回答:外置菜单也会有几率封号,我只能说是挂都会有封号的几率,用内置就像抽烟的人对比不 ...
- android 菜单隐藏了,隐藏一些导航菜单菜单项 – Android
我有导航抽屉.当一些事件被调用时,我想从用户隐藏我的一个导航菜单项.我能做到吗 protected void onCreate(Bundle savedInstanceState) { super.o ...
- 使用window.createPopup创建无限级跨帧下拉菜单
我的BLOG搬家到自己的站点了 站点链接 RSS 先帖样子 使用层或者其他技术所实现的JS菜单不能解决的问题就是这些菜单不能跨帧,也就是说在Frame之间的时候无可奈何,所幸的是IE5+ ...
- 微信自定义菜单java_使用Java语言开发微信公众平台(八)——自定义菜单功能
随着上一篇文章的结束,我们已经实现了所有消息的类型的回复功能.今天,我们来学习更加高大上,也更加重要的自定义菜单功能. 一.了解自定义菜单 自定义菜单是微信公众平台最常用也是最重要的功能之一.根据微信 ...
最新文章
- PCA中transform等scikit-learn中系列API用法
- rabbitmq 启动报错 Failed to get nic info
- 【Linux】34. shell脚本判断当前年份是否正确
- Deep Neural Networks的Tricks
- php数组循环0到32,通过数组php循环
- 笑话(15) 这是地球
- 搜索引擎怎么收集的那么多内容?
- Alter-有意思的小游戏
- python协同过滤电影推荐_基于协同过滤的电影推荐系统的设计与实现
- NEC电影服务器型号,NEC数字电影放映一体机NC2300S-A+详细信息_产品参数_价格_联系方式_DAV数字音视工程网...
- Elasticsearch的Watcher插件
- 作为一个部门 Leader,居然不如一个实习生
- 为什么很多人说Python简单呢?
- Keras过拟合相关解决办法
- JAVA链表中的回文链表结构
- 对于arm嵌入式系统的一点认识
- fastjason 0day 漏洞修复
- Win10系统中耳机插入前后面板均没有声音
- OMPL官方教程学习State Validity Checking
- 继电器模块的的使用方法、引脚说明、内部结构、接线说明(超通俗超详细看了就能给别人讲)