基于二叉树的多层的液晶菜单界面设计

以前用单片机做用户交互的菜单的时候,都比较痛苦,如何写一个复用性高,方便维护,可扩展性高的gui框架呢?当然可以自己动手写一个,这个过程充满了艰辛和挑战,现在我推荐一个很棒的框架,直接拿来用就行,也可以借鉴和学习其中的思路,一定会收获颇丰。
  知道有多少人折腾过液晶显示的菜单,我觉得很多人都应该搞过,我还记得以前大学参加电子设计竞赛获奖的作品,我就用到了一个12864,里面有菜单功能。
以前可能觉得菜单高大上,其实并不是想象中的复杂,本文为大家分享一个用单色屏做的菜单框架。
代码托管在github:
https://github.com/wujique/stm32f407/tree/sw_arch 
公众号回复菜单也可获得源码.
1、概述
本处所说的菜单是用在128*64这种小屏幕的菜单,例如下面这种,不是彩屏上的gui。
  2、菜单框架设计
作为一个底层驱动工程师,驱动写完了,是要写硬件测试程序的。这个测试程序,一般给测试部/硬件工程师用来测试硬件, 也会给工厂产线测试准成品。
开始的人偷懒,不想一秒就直接上,所有菜单都这样做,一层套一层
1void test_main(void) 2{ 3    while(1) 4    { 5        get_key(&key); 6        switch(key) 7        { 8            case 1: 9                test_key(); 10                break; 11            case 2: 12                test_lcd(); 13                break; 14            .... 15        } 16    } 17}
当菜单越来越多,就开始纠结了,这样写维护不便,看起来也不美,还浪费程序空间。
作为一个天天看《编程之美》的码农,决定改变现状。
搜索引擎找了很久,找到了两个参考:
《基于二叉树的多层的液晶菜单界面设计》 
《基于节点编号的通用树状菜单设计方法与实现.pdf》 
按照他们的设计方法,鼓捣了一个版本,能用,挺好,但是也纠结。因为他们用了树这种数据结构。对于程序运行来说,非常好,效率高。但是对于我来说,菜单代码是一次性的,但是菜单内容,却是会经常改的。让我用人脑去维护一个包含几十个上百个菜单的树,不容易。
想来想去,这些菜单到底有什么不好?对于我来说,为什么不好用?得出下面结论:
管得太宽 菜单,你就管菜单切换就行了,到了最低一层,也就是实际的测试功能,就不要管了。菜单切换是类似的,实际测试都是不同的。比如在菜单中,按键1,是进入第一个菜单。但是在测试中,按键1,功能都不一样。如果菜单连这个也要管,相同动作功能太多,无法进行统一抽象,就很难模块化。
出发点不一样 上面说到的菜单,出发点都是如何设计一个好的菜单数据结构,让程序快速,高效运行。我想要的却是一个容易维护的菜单结构,至于菜单的代码有多乱多纠结,没关系, 而且,几百上千个菜单,就算用轮询的方法,也不过几百us吧,没关系。
3、改进菜单
根据需求,我重新设计了一个菜单结构体
1/** 2 * @brief  菜单对象 3*/ 4typedef struct _strmenu 5{ 6    menulel l;     ///<菜单等级 7    char cha[menu_lang_buf_size];   ///中文 8    char eng[menu_lang_buf_size];   ///英文 9    menutype type;  ///菜单类型 10    s32 (*fun)(void);  ///测试函数 11 12} menu;
是的,就这么简单,每一个菜单都是这个结构体 用这个结构体填充一个列表,就是我们的菜单了、
1const menu emenulisttest[]= 2{ 3        menu_l_0,//菜单等级 4        测试程序,//中文 5        test,        //英文 6        menu_type_list,//菜单类型 7        null,//菜单函数,功能菜单才会执行,有子菜单的不会执行 8 9                menu_l_1,//菜单等级 10                lcd,//中文 11                lcd,        //英文 12                menu_type_list,//菜单类型 13                null,//菜单函数,功能菜单才会执行,有子菜单的不会执行 14                        menu_l_2,//菜单等级 15                        vspi oled,//中文 16                        vspi oled,        //英文 17                        menu_type_fun,//菜单类型 18                        test_oled,//菜单函数,功能菜单才会执行,有子菜单的不会执行 19 20                        menu_l_2,//菜单等级 21                        i2c oled,//中文 22                        i2c oled,        //英文 23                        menu_type_fun,//菜单类型 24                        test_i2coled,//菜单函数,功能菜单才会执行,有子菜单的不会执行 25 26 27                menu_l_1,//菜单等级 28                声音,//中文 29                sound,        //英文 30                menu_type_list,//菜单类型 31                null,//菜单函数,功能菜单才会执行,有子菜单的不会执行 32                        menu_l_2,//菜单等级 33                        蜂鸣器,//中文 34                        buzzer,        //英文 35                        menu_type_fun,//菜单类型 36                        test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行 37 38                        menu_l_2,//菜单等级 39                        dac音乐,//中文 40                        dac music,        //英文 41                        menu_type_fun,//菜单类型 42                        test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行 43 44                        menu_l_2,//菜单等级 45                        收音,//中文 46                        fm,        //英文 47                        menu_type_fun,//菜单类型 48                        test_test,//菜单函数,功能菜单才会执行,有子菜单的不会执行 49 50 51                menu_l_1,//菜单等级 52                触摸屏,//中文 53                tp,        //英文 54                menu_type_list,//菜单类型 55                null,//菜单函数,功能菜单才会执行,有子菜单的不会执行 56 57                        menu_l_2,//菜单等级 58                        校准,//中文 59                        calibrate,        //英文 60                        menu_type_fun,//菜单类型 61                        test_cal,//菜单函数,功能菜单才会执行,有子菜单的不会执行 62 63                        menu_l_2,//菜单等级 64                        测试,//中文 65                        test,        //英文 66                        menu_type_fun,//菜单类型 67                        test_tp,//菜单函数,功能菜单才会执行,有子菜单的不会执行 68 69                menu_l_1,//菜单等级 70                按键,//中文 71                key,        //英文 72                menu_type_fun,//菜单类型 73                test_key,//菜单函数,功能菜单才会执行,有子菜单的不会执行 74 75        /*最后的菜单是结束菜单,无意义*/                         76        menu_l_0,//菜单等级 77        end,//中文 78        end,        //英文 79        menu_type_null,//菜单类型 80        null,//菜单函数,功能菜单才会执行,有子菜单的不会执行 81};
这个菜单列表有什么特点和要求呢?1 需要一个根节点和结束节点 2 子节点必须跟父节点,类似下面结构
1----------------------------------------------- 2根节点 3        第1个1级菜单 4                       第1个子菜单 5                       第2个子菜单 6                       第3个子菜单 7        第2个1级菜单 8                       第1个子菜单 9                                     第1个孙菜单 10                                     第2个孙菜单 11                       第2个子菜单 12                       第3个子菜单 13        第3个1级菜单 14        第4个1级菜单 15        第5个1级菜单 16结束节点 17------------------------------------------------
第2个1级菜单有3个子菜单,子菜单是2级菜单,其中第1个子菜单下面又有2个孙菜单(3级菜单)。
维护菜单,就是维护这个列表,添加删除修改,非常容易。那菜单程序怎么样呢?管他呢。定义好菜单后,通过下面函数运行菜单,
1 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、最后说明
以上菜单框架来源屋脊雀工作室,适合初学者练习。我看下这个菜单框架,其实还有很多改进地方。
我当初大学电子设计竞赛用到类似结构体方式,但我那菜单框架用到了二级指针,可以做到无限极扩展,而且可以指向(跳转)任意菜单,方便按键进入、返回等操作。
本文就分享到这里,感兴趣的读者可以自己写一个菜单框架。
原文标题:值得学习的单片机菜单框架(附源码)
文章出处:【微信公众号:硬件攻城狮】欢迎添加关注!文章转载请注明出处。 


智能机器人2020年的发展隐藏哪些商机
华硕发布公告:表示11月份正在逐渐增加显卡产量
射频滤波器在手机终端射频前端中的地位和数量
单个I/O口驱动单个LED教程
驱动器前滤波器和电抗器的区别
基于二叉树的多层的液晶菜单界面设计
人工智能在军事上的应用并非遥不可及
AMD Ryzen新3A装机详解
PCB布局布线的规则
华为将打破小米称霸中国智能穿戴领域的局面
第十三课 C51循环语句
AMD yes!研华AIMB-229主板新品发布:搭载AMD Ryzen™嵌入式V2000处理器,释放视觉算力
雷柏VH300游戏耳机评测 提供了更为身临其境的游戏体验
2019国内储能锂电池市场规模将达52亿!
掌上神器L-MIX微型投影仪体验 值不值得买
室内定位市场深度剖析, UWB定位技术或将成为主流!
汽车雷达与驾驶安全简析
传感器产业的主导权之争日趋激化
2019款iPhone曝光依然是刘海屏设计一共有四种配色充电功率是5W
南卡骨传导耳机初体验,和同事一起分享