一、前言,本文的OLED多级菜单UI为一个综合性的STM32小项目,使用多传感器与OLED显示屏实现智能终端的效果。项目中的多级菜单UI使用了较为常见的结构体索引法去实现功能与功能之间的来回切换,搭配DHT11,RTC,LED,KEY等器件实现高度智能化一体化操作。
后期自己打板设计结构,可以衍生为智能手表等小玩意。目前,项目属于裸机状态(CPU占用率100%),后期可能会加上RTOS系统。
二、硬件实物图,
温度计:
游戏机:
三、硬件引脚图
四、多级菜单,随着工业化和自动化的发展,如今基本上所有项目都离不开显示终端。而多级菜单更是终端显示项目中必不可少的组成因素,其实 TFT-LCD 屏幕上可以借鉴移植很多优秀的开源多级菜单(GUI,比如:LVGL),而0.96寸的OLED屏幕上通常需要自己去适配和编程多级菜单。
网上的普遍采用的多级菜单的方案是基于索引或者结构树,其中,索引法居多。索引法的优点:可阅读性好,拓展性也不错,查找的性能差不多是最优,就是有点占用内存空间。
4.1 索引法多级菜单实现,网上关于索引法实现多级菜单功能有很多基础教程,笔者就按照本项目中的具体实现代码过程给大家讲解一下索引法实现多级菜单。特别说明:本项目直接使用了正点原子的精英板作为核心板,所以读者朋友复现代码还是很简单的。
首先,基于索引法实现多级菜单的首要条件是先确定项目中将使用到几个功能按键(比如:向前,向后,确定,退出等等)本项目中,笔者使用到了3个按键:下一个(next),确定(enter),退出(back)。所以,接下首先定义一个结构体,结构体中一共有5个变量(3+2),分别为:当前索引序号(current),向下一个(next),确定(enter),退出(back),当前执行函数(void)。其中,标红的为需要设计的按键(笔者这里有3个),标绿的则为固定的索引号与该索引下需要执行的函数。
接下来就是定义一个数组去决定整个项目菜单的逻辑顺序(利用索引号)
这里解释一下这个数组中各元素的意义,由于我们在前面先定义了Menu_table结构体,结构体成员变量分别与数组中元素对应。比如:{0,0,1,0,(*home)},代表了索引号为0,按向下键(next)转入索引号为0,按确定键(enter)转入索引号为1,按退出键(back)转入索引号为0,索引号为0时执行home函数。
在举一个例子帮助大家理解一下,比如,我们当前程序处在索引号为2(游戏界面),就会执行Playgame函数。此时,如果按下next按键,程序当前索引号就会变为3,并且执行索引号为3时候的Setting函数。如果按下enter按键,程序当前索引号就会变为6,并且执行索引号为6时候的ControlGame函数。如果按下back按键,程序当前索引号就会变为0,并且执行索引号为0时候的home函数。
再接下就是按键处理函数>
(1)由于是目前本项目是裸机状态下运行的,所以CPU占用率默认是100%的,所以这里使用按键支持连按时,对于菜单的切换更好些。
(2)可能部分索引号下的执行函数,需要使用到已经定义的3个按键(比如,本项目中的DInogame中)。所以,可以在需要差别化的索引号下去屏蔽原先的按键功能。如下>
(3)笔者这里是使用全屏刷新去切换功能界面,同时,没有启用高级算法去加速显示,所以可能在切换界面的时候效果一般。读者朋友可以试试根据自己的UI情况使用局部刷新,这样可能项目会更加丝滑一点。
本项目中的菜单索引图>
4.2 内部功能实现(简化智能手表),OLED就是正常的驱动与显示,有能力的读者朋友可以使用高级算法去加速OLED屏幕的刷新率,可以使自己的多级菜单切换起来更丝滑。
唯一需要注意的点就是需要去制作菜单里面的UI图标(注意图片大小是否合适)>
如果是黑白图片的话,可以直接使用PCtoLCD2002完美版进行取模>
4.3 KEY按键,KEY按键注意消抖(建议裸机情况下支持连续按动),同时注意自己实际硬件情况去进行编程(电阻是否存在上拉或者下拉)。
4.4 DinoGame实现,
谷歌公司最近比较流行的小游戏,笔者之前有文章进行了STM32的成功复刻。博客地址: 谷歌小恐龙在线 — 免费玩谷歌小恐龙 (dino.zone),4.5 LED控制和DHT11模块,LED和DHT11模块其实都属于外设控制,这里读者朋友可以根据自己的实际情况去取舍。需要注意的是尽可能适配一下自己多级菜单(外设控制也需要注意一下按键安排,可以参考笔者项目的设计)。
五、CubeMX配置,1、RCC配置外部高速晶振(精度更高)——HSE;,
2、SYS配置:Debug设置成Serial Wire(否则可能导致芯片自锁);,
3、I2C2配置:这里不直接使用CubeMX的I2C2,使用GPIO模拟(PB10:CLK;PB11:SDA),
4、RTC配置:年月日,时分秒;,
5、TIM2配置:由上面可知DHT11的使用需要us级的延迟函数,HAL库自带只有ms的,所以需要自己设计一个定时器;,
6、KEY按键配置:PE3,PE4和PA0设置为端口输入(开发板原理图),
7、时钟树配置>
8、文件配置,
六、代码,6.1 OLED驱动代码,此部分OLED的基本驱动函数,笔者使用的是I2C驱动的0.96寸OLED屏幕。所以,首先需要使用GPIO模拟I2C通讯。随后,使用I2C通讯去驱动OLED。(此部分代码包含了屏幕驱动与基础显示),oled.h:
oled.c:
6.2 谷歌小恐龙游戏图形绘制代码,该部分为整个项目代码的核心部分之一,任何一个游戏都是需要去绘制和构建游戏的图形以及模型的。好的游戏往往都具有很好的游戏模型和精美UI,很多3A大作都具备这样的特性。
dinogame.h:
dinogame.c代码:
6.3 谷歌小恐龙的运行控制代码,control.h:
control.c:
6.4 多级菜单核心代码>
menu.h:
menu.c:
七、总结与代码开源
总结:本项目目前还处于最初代版本,十分简易,后期笔者将抽时间去精进优化该多级菜单项目。其中,UI界面中的电池与信号目前都还处于贴图状态,后期笔者会加上库仑计测量电池电量等。文章中指出了需要注意的地方与可以改进的点,感兴趣的朋友可以彼此交流交流。