作为一个成熟的项目,就必然不会只有一个方面的特点了,这里一般我们可能需要系统来进行调度,然后给一些可视化的UI,当然我前面有讲到HMI串口屏的使用,串口屏确实是非常不错的UI工具,但是一些比较小的项目就用不太到了,因此这里如果是一些低成本的DIY的项目,一般我们用OLED就足够了,足够mini,足够有感觉!
因此本文我决定记录下我在移植oled菜单的一些过程,同时也希望能帮助看到这篇文章的兄弟更快的上手OLED菜单!
1、按键驱动
这里我之前的文章讲到过一款开源的按键工具,这里为了节省代码量,我发现了一个更方便的驱动方式,下面就来介绍下:
1、硬件连接
这里肯定是越简单越好,所以这里就直接接上即可,也不做什么滤波电路了,当然有一个滤波自然是更好的哈哈哈,原理图如下所示:
下面是我用手焊的简易版本测试用的
可以看下背面就是按照原理图来进行的,如下所示
2、引脚功能配置
下面就是配置引脚模式了,因为这里引脚的另一端默认是接地的,所以我们这里接上IO口的这边就需要提前将其设置为上拉的模式,这样才不会影响我们的按键读取,使得每次都能有效检测到引脚电平的变化。
按键的扫面需要我们配置一个周期性的扫描函数,这里我们就有很多可以选择的方案了:
- 使用freertos建立扫描任务
- 裸机使用while循环来实现
- 使用定时器来实现周期性扫描
这里考虑到本身只是个测试用的demo工程,就不搞系统了,直接裸机,为了移植上的方便性,我这里也就使用定时器来生成了,这里我们配置定时器6来实现功能,配置如下:
3、程序设置
这里我们开始来配置程序,这里我对关键部门来做一下说明,说明如下:
首先是对我们按键读取做一个宏,这样方便我们进行后续的操作
扫描函数说明如下,主要是使用改方案可以很好的实现按键检测
在定时器中检查扫描函数
综上我们就可以实现按键的检测工作了,实测效果还是不错的,可以自行验证。源码如下:
void KeyScan(void)
{
static int keyCount = 0;
static int keyState = 0;
if (KEY_UP == 0 && keyState == 0)
{
keyCount++;
if (keyCount > 2 && KEY_UP == 0 && keyState == 0)
{
KeyUp();
keyState = 1;
}
}
else if (KEY_DOWN == 0 && keyState == 0)
{
keyCount++;
if (keyCount > 2 && KEY_DOWN == 0 && keyState == 0)
{
KeyDown();
keyState = 1;
}
}
else if (KEY_LEFT == 0 && keyState == 0)
{
keyCount++;
if (keyCount > 2 && KEY_LEFT == 0 && keyState == 0)
{
KeyLeft();
keyState = 1;
}
}
else if (KEY_RIGHT == 0 && keyState == 0)
{
keyCount++;
if (keyCount > 2 && KEY_RIGHT == 0 && keyState == 0)
{
KeyRight();
keyState = 1;
}
}
else if (KEY_ON == 0 && keyState == 0)
{
keyCount++;
if (keyCount > 2 && KEY_ON == 0 && keyState == 0)
{
KeyOk();
keyState = 1;
}
}
else if (KEY_OFF == 0 && keyState == 0)
{
keyCount++;
if (keyCount > 2 && KEY_OFF == 0 && keyState == 0)
{
keyState = 1;
}
}
else if (KEY_UP == 1 && KEY_DOWN == 1 && KEY_LEFT == 1 && KEY_RIGHT == 1 && keyState == 1)
{
keyCount = 0;
keyState = 0;
}
}
2、oled驱动
oled驱动可以见我之前的博客,这里不在进行介绍,之前有介绍过SPI还有IIC版本的,也都介绍了使用软件还有硬件的方式进行驱动,软件驱动的话就可以比较方便的进行其他型号单片机的移植了,下面是相关博客的链接,可以自行查阅:
SPI驱动:SPI写OLED(软硬件切换)
IIC驱动:stm32配置总结-iic的使用
3、菜单移植
1、菜单的思路
之前在网上也看到很多大佬讲过oled菜单,但是根绝实现起来都不太方便,最简单的肯定就是自己写好页面然后刷新,使用按键这样一个个的函数进行跳转,感觉这样就很麻烦了,不推荐使用这样的方式,如果菜单比较简单就还好,菜单一旦复杂就不行了,那也太难搞了!
所以这里我移植了另一位大佬的方案,感觉还是很不错的,感谢这位大佬,源地址如下:https://gitee.com/snqx-lqh/screen-design-using-gui/tree/master/2%E3%80%81STM32C8T6+IIC+OLED0.96GUI%E8%AE%BE%E8%AE%A1
首先我们看下菜单结构体,每个菜单结构体包含了菜单页的一些参数,说明如下:
- 菜单个数
- 滚动条长度(就是比如如果选用16的字体的话,一页最多显示四行,这样长度0,因为不需要滚动,如果需要显示大于4行,比如5行,这样菜单就需要滚动一下才能看到下面的一行,这样滚动条长度就是1了。)
- 菜单的名称等
- 菜单的功能函数
- 父级菜单
- 子菜单
其实这里比较重要的就还是父级菜单和子菜单,使用他们我们就可以进行菜单之间的跳转了!
文章来源:https://www.toymoban.com/news/detail-782317.html
2、菜单程序设计
上面介绍了菜单的思路,下面就可以看看菜单是怎么生成的了,不过在这之前可以看下作者设计的封面,封面显示如下所示:
可以看下程序上的设置:
这里时间上是使用了一个定时器来执行的,然后通过参数结构体进行更新,其中年月日的更新也在定时器中来执行,下面就可以看下菜单的定义了。主要是看子菜单和父级菜单的定义。
下面看给菜单添加的内容描述,这里如果我们后续要使用中文的话后面的显示函数也需要做相应的修改,所以这里为了整个过程显得不繁琐,就还是英文字符吧
下面是我之前说的滑动窗口的定义了
下面是箭头的刷新函数指示
效果如下:
下面是对于内部的定义的一些变量的刷新
子菜单的内部变量刷新效果如下所示:
之后就是把刚才定义的内容加入进去了
最后就是按键控制函数了,主要是一些逻辑上的选择,这里注意就是每次对索引值进行一次操作之后要刷新屏幕
在主函数中加入初始化还有刷新函数
最终效果如下所示:
文章来源地址https://www.toymoban.com/news/detail-782317.html
到了这里,关于OLED多级菜单记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!