一个产品级MCU菜单框架设计
关注+星标公众号,不错过精彩内容
转自 | 嵌入式云IOT技术圈
微信公众号 | 嵌入式专栏
不知道有多少人折腾过液晶显示的菜单,我觉得很多人都应该搞过,我还记得以前大学参加电子设计竞赛获奖的作品,我就用到了一个12864,里面有菜单功能。
以前可能觉得菜单高大上,其实并不是想象中的复杂,本文为大家分享一个用单色屏做的菜单框架。
嵌入式专栏
1
概述
代码托管在github:
https://github.com/wujique/stm32f407/tree/sw_arch
本处所说的菜单是用在128*64这种小屏幕的菜单,例如下面这种,不是彩屏上的GUI。
嵌入式专栏
2
菜单框架设计
作为一个底层驱动工程师,驱动写完了,是要写硬件测试程序的。这个测试程序,一般给测试部/硬件工程师用来测试硬件, 也会给工厂产线测试准成品。
开始的人偷懒,不想一秒就直接上,所有菜单都这样做,一层套一层
void test_main(void)
{while(1){get_key(&key);switch(key){case 1:test_key();break;case 2:test_lcd();break;....}}
}
当菜单越来越多,就开始纠结了,这样写维护不便,看起来也不美,还浪费程序空间。
作为一个天天看《编程之美》的码农,决定改变现状。酷狗百度一番,找到了两个参考:《基于二叉树的多层的液晶菜单界面设计》 《基于节点编号的通用树状菜单设计方法与实现.pdf》 按照他们的设计方法,鼓捣了一个版本,能用,挺好,但是也纠结。因为他们用了树这种数据结构。对于程序运行来说,非常好,效率高。但是对于我来说,菜单代码是一次性的,但是菜单内容,却是会经常改的。让我用人脑去维护一个包含几十个上百个菜单的树,不容易。
想来想去,这些菜单到底有什么不好?对于我来说,为什么不好用?得出下面结论:
管得太宽 菜单,你就管菜单切换就行了,到了最低一层,也就是实际的测试功能,就不要管了。菜单切换是类似的,实际测试都是不同的。比如在菜单中,按键1,是进入第一个菜单。但是在测试中,按键1,功能都不一样。如果菜单连这个也要管,相同动作功能太多,无法进行统一抽象,就很难模块化。
出发点不一样 上面说到的菜单,出发点都是如何设计一个好的菜单数据结构,让程序快速,高效运行。我想要的却是一个容易维护的菜单结构,至于菜单的代码有多乱多纠结,没关系, 而且,几百上千个菜单,就算用轮询的方法,也不过几百us吧,没关系。
嵌入式专栏
3
改进菜单
根据需求,我重新设计了一个菜单结构体
/*** @brief 菜单对象
*/
typedef struct _strMenu
{MenuLel l; ///<菜单等级char cha[MENU_LANG_BUF_SIZE]; ///中文char eng[MENU_LANG_BUF_SIZE]; ///英文MenuType type; ///菜单类型s32 (*fun)(void); ///测试函数} MENU;
是的,就这么简单,每一个菜单都是这个结构体 用这个结构体填充一个列表,就是我们的菜单了
const MENU EMenuListTest[]=
{MENU_L_0,//菜单等级"测试程序",//中文"test", //英文MENU_TYPE_LIST,//菜单类型NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_1,//菜单等级"LCD",//中文"LCD", //英文MENU_TYPE_LIST,//菜单类型NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"VSPI OLED",//中文"VSPI OLED", //英文MENU_TYPE_FUN,//菜单类型test_oled,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"I2C OLED",//中文"I2C OLED", //英文MENU_TYPE_FUN,//菜单类型test_i2coled,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_1,//菜单等级"声音",//中文"sound", //英文MENU_TYPE_LIST,//菜单类型NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"蜂鸣器",//中文"buzzer", //英文MENU_TYPE_FUN,//菜单类型test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"DAC音乐",//中文"DAC music", //英文MENU_TYPE_FUN,//菜单类型test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"收音",//中文"FM", //英文MENU_TYPE_FUN,//菜单类型test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_1,//菜单等级"触摸屏",//中文"tp", //英文MENU_TYPE_LIST,//菜单类型NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"校准",//中文"calibrate", //英文MENU_TYPE_FUN,//菜单类型test_cal,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_2,//菜单等级"测试",//中文"test", //英文MENU_TYPE_FUN,//菜单类型test_tp,//菜单函数,功能菜单才会执行,有子菜单的不会执行MENU_L_1,//菜单等级"按键",//中文"KEY", //英文MENU_TYPE_FUN,//菜单类型test_key,//菜单函数,功能菜单才会执行,有子菜单的不会执行/*最后的菜单是结束菜单,无意义*/ MENU_L_0,//菜单等级"END",//中文"END", //英文MENU_TYPE_NULL,//菜单类型NULL,//菜单函数,功能菜单才会执行,有子菜单的不会执行
};
这个菜单列表有什么特点和要求呢?1 需要一个根节点和结束节点 2 子节点必须跟父节点,类似下面结构
-----------------------------------------------
根节点第1个1级菜单第1个子菜单第2个子菜单第3个子菜单第2个1级菜单第1个子菜单第1个孙菜单第2个孙菜单第2个子菜单第3个子菜单第3个1级菜单第4个1级菜单第5个1级菜单
结束节点
------------------------------------------------
第2个1级菜单有3个子菜单,子菜单是2级菜单,其中第1个子菜单下面又有2个孙菜单(3级菜单)。
维护菜单,就是维护这个列表,添加删除修改,非常容易。那菜单程序怎么样呢?管他呢。定义好菜单后,通过下面函数运行菜单,
emenu_run(WJQTestLcd, (MENU *)&WJQTestList[0], sizeof(WJQTestList)/sizeof(MENU), FONT_SONGTI_1616, 2);
-第1个参数是在哪个LCD上显示菜单, -第2个是菜单列表, -第3个是菜单长度, -第4个四字体, -第5则是行间距
注意:运行这个菜单需要有rtos,因为菜单代码是while(1)的,陷进去就不出来了。需要有其他线程(TASK)维护系统,例如按键扫描。
嵌入式专栏
4
菜单实现效果
相关文件:emenu.c、emenu.h、emenu_test.c
当前代码:
1实现了双列菜单,用数字键选择进入下一层。每页最多显示8个菜单(4*4键盘用1-8键)
2 实现了单列菜单,通过上下翻查看菜单,确认键进入菜单。3 天顶菜单未实现,谁有兴趣可以加上。
3 基于LCD驱动架构,这个简易菜单自适应于多种LCD。
效果如下,有需要的尽管拿去,不用谢。
显示效果
128*64 OLED
128*128 tft lcd
320*240 tft lcd
嵌入式专栏
5
最后说明
以上菜单框架来源屋脊雀工作室,适合初学者练习。我看下这个菜单框架,其实还有很多改进地方。
我当初大学电子设计竞赛用到类似结构体方式,但我那菜单框架用到了二级指针,可以做到无限极扩展,而且可以指向(跳转)任意菜单,方便按键进入、返回等操作。
本文就分享到这里,感兴趣的读者可以自己写一个菜单框架。
免责声明:本文素材来源网络,版权归原作者所有。如涉及作品版权问题,请与我联系删除。
------------ END ------------
推荐阅读:
精选汇总 | 专栏 | 目录 | 搜索
精选汇总 | ARM、Cortex-M
精选汇总 | ST工具、下载编程工具
关注微信公众号『嵌入式专栏』,底部菜单查看更多内容,回复“加群”按规则加入技术交流群。
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。
一个产品级MCU菜单框架设计相关推荐
- 一个开源经典的MCU菜单框架设计
来源:嵌入式专栏 不知道有多少人折腾过液晶显示的菜单,我觉得很多人都应该搞过,我还记得以前大学参加电子设计竞赛获奖的作品,我就用到了一个12864,里面有菜单功能. 以前可能觉得菜单高大上,其实并不是 ...
- 微信小程序 - 实践- 001-实现一个多TAB的菜单框架
1 前言: 多TAB的菜单框架,可以把不同内容的菜单选项进行分类,应该是常用的方法: 例如上面这个主界面由4个TAB菜单构成. 在微信给出的DEMO例子里面,也有相应的多TAB的使用, 在前一篇博客文 ...
- 值得学习的单片机菜单框架(附源码)
点击上方"小麦大叔",选择"置顶/星标公众号" 福利干货,第一时间送达 大家好,我是小麦,以前用单片机做用户交互的菜单的时候,都比较痛苦,如何写一个复用性高,方 ...
- 设计php框架_PHP微型框架设计
一.框架整体分析 在实现一个框架之前,我们需要了解这个框架应该达到一个怎样的效果,按照传统框架的思路,大致可以总结出以下这么几条: 1.实现MVC架构,将控制.逻辑.视图层进行分离. 2.封装各种函数 ...
- 战胜主导设计:一个整合性的分析框架
文章目录 一.引言 二.相关文献回顾 三.主导设计形成后的新进入企业的SWOT分析 (一)NE的优势分析 (二)NE的劣势分析 (三)NE的机会分析 (四)NE的威胁分析 四.结论 五.参考文献 一. ...
- JavaWeb框架设计之菜单设计
近来工作,要求自己搭建框架.从中遇到了这样一个诉求---动态菜单. 这个诉求在Java Web框架设计中属于最普遍的需求.那么我们来探讨下. 一般的Java Web框架的菜单层级都是为二级,那么在数据 ...
- SSM框架之酒店管理系统三(菜单数据库设计,菜单列表查询渲染)
SSM框架之酒店管理系统三(菜单数据库设计,菜单列表查询渲染) 参考LAYUI MINI官网给出的数据库设计规范 Java示例(spring) · layuimini开发手册 (99php.cn) 数 ...
- 干货!如何设计实现一个通用的分布式事务框架?
来源:https://www.bytesoft.org/ 一个TCC事务框架需要解决的当然是分布式事务的管理.关于TCC事务机制的介绍,可以参考TCC事务机制简介. TCC事务模型虽然说起来简单,然而 ...
- Dubbo面试 - 如何自己设计一个类似 Dubbo 的 RPC 框架?
Dubbo面试 - 如何自己设计一个类似 Dubbo 的 RPC 框架? 面试题 如何自己设计一个类似 Dubbo 的 RPC 框架? 面试官心理分析 说实话,就这问题,其实就跟问你如何自己设计一个 ...
最新文章
- 网页中嵌套网页flush_如何修改网页中的内容?
- golang中container/list包中的坑
- 如何用 JavaScript+Canvas 开发一款超级烧脑小游戏?
- matlab 矢量化编程(三) —— 软阈值函数
- fortran调用MKL函数库中的gemm的fortran95接口计算矩阵相乘
- 销售管理系统哪个好用?
- 【原创抖音互动无人直播项目大鱼吃小鱼,进入直播间的用户开始吃鱼,吃的鱼越多等级越高越厉害】
- 计算入瞳、出瞳位置及孔径大小
- 有多少程序员干到35岁,那么其他人去干什么了?
- Ubuntu 16.04 显示器分辨率低
- Android中Gson使用,flutter调用原生sdk
- 湖北地图html代码,echarts全国省市地图代码
- Robocup 2D 的学习
- 数学文化 卢卡斯数列和黄金分割
- nginx运行php程序
- Class文件结构分析
- cass如何导入tif格式_CASS导入坐标文件的方法,一般人我不告诉他!-DAT文件
- RK3229方案测评 RK3299方案设计定制 RK3299方案开发板 RK3229智能音响
- 2021-2027全球与中国智能迷你无人机服务市场现状及未来发展趋势
- java荣誉勋章下载_荣誉勋章2011BT版