【平头哥RVB2601创意应用开发】环境监测终端03-使用LVGL设计界面
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">本篇文章介绍基于LVGL库在RVB2601开发板自带的OLED显示屏上设计界面。</span></span></span></span></p><p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span lang="EN-US" style="font-size:14.0pt"><span style="font-family:黑体">RVB2601</span></span><span style="font-size:14.0pt"><span style="font-family:黑体">开发板内置了一款分辨率为128*64的单色OLED显示屏,并且基于此平台移植完成了开源的LVGL GUI库。此前并没有使用过LVGL GUI库,这次正好尝试一下,因此在网上一通搜索教程。正好找到了别人翻译好的使用手册,附在本文附件中,有需要的同学可以下载。</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">首先设计界面草稿。如下图所示,我计划在屏幕上显示5行信息。第一行,标题,直接使用标签显示即可。第二行,温度,左边字段不需要更新,右边字段需要定时刷新,也全部使用标签显示。第三行和第四行分别是湿度和噪音水平,和温度显示采用一样方法。第五行计划做一个指示条,用来动态指示噪音的实时幅度,这样查看起来比较直观。</span></span></span></span></p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center" style="text-align:center"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">图1、界面草图</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">实际设计的时候遇到各种问题。首先是如何显示中文,经查询得知要自己制作内置字库并添加,看了几个教程,很繁琐的样子,本人犯懒了,决定跳过这个中文显示,改用英文也是一样。</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">下一个问题是默认使用的英文字体是“LV_FONT_MONTSERRAT_14”比较大,如果显示5行看着太挤了,通过更改配置项使用“LV_FONT_MONTSERRAT_12”字体相对好一点。我还试了改成更小的字体,有点惨不忍睹,都不能分辨了,有点像大片上的火星文。具体修改方法如下图。</span></span></span></span></p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center" style="text-align:center"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">图2、修改字体</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">接下来实际编程显示文字。做标题显示的时候,看到LVGL支持滚动显示,为了体现咱的学习成果,把原计划的两个单词的标题改成了一句话,让它在最上面滚动显示,比较好玩。具体设置方式参见下面代码。</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">在设置温度显示的时候,需要显示浮点数,我按照常规的方式写代码发现不能正常显示,然后查阅资料发现应该是为了提高效率,默认设置成了不支持浮点模式。本来想查手册改成支持浮点模式,后面看到有人采用了更妙的方法解决了。就是先将浮点数格式化成字符串,然后再以字符串显示就没问题了,我按照此方法操作,顺利解决此问题,具体方法参照下面代码。</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">最后一个要实现的是噪音指示条。经过反复查阅手册,最终确定使用进度条“LV_BAR”控件设计。直接按照手册简单例程搞上去后,发现两端都是圆角,不是我喜欢了类型。然后一通大搜索,网络是个好东西,又被我找到解决方案了,感兴趣的朋友可以参考以下帖子。</span></span></span></span></p>
<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span lang="EN-US" style="font-size:14.0pt"><span style="font-family:黑体"><a href="https://www.csdn.net/tags/MtTaEg4sMjI1OTA0LWJsb2cO0O0O.html" style="color:blue; text-decoration:underline">https://www.csdn.net/tags/MtTaEg4sMjI1OTA0LWJsb2cO0O0O.html</a></span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">经过我反复修改和调试,终于把界面框架搭建出来,显示效果如下图。</span></span></span></span></p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center" style="text-align:center"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">图3、界面框架</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">整个框架初始化代码如下。</span></span></span></span></p>
<pre>
<code class="language-cpp">lv_obj_t *pGui_label_temp;
lv_obj_t *pGui_label_humi;
lv_obj_t *pGui_label_noise;
lv_obj_t *pGui_bar_noise;
static void gui_label_create(void)
{
char cdata = { 0 };
lv_obj_t *p_label_title= lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(p_label_title, LV_LABEL_LONG_SROLL_CIRC); /*滚动显示*/
lv_obj_set_width(p_label_title, 160);
lv_label_set_text(p_label_title, "Hello EEWOLRD,This is a Environment Monitor based on RVB2601.");
lv_obj_align(p_label_title, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
lv_obj_t *p_label_temp = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(p_label_temp, LV_LABEL_ALIGN_LEFT);
lv_obj_set_pos(p_label_temp, 0, 12);
lv_obj_set_size(p_label_temp, 128, 64);
lv_label_set_text(p_label_temp, "Temperature:");
lv_obj_t *p_label_humi = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(p_label_humi, LV_LABEL_ALIGN_LEFT);
lv_obj_set_pos(p_label_humi, 0, 24);
lv_obj_set_size(p_label_humi, 128, 64);
lv_label_set_text(p_label_humi, "Humidity:");
lv_obj_t *p_label_noise = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(p_label_noise, LV_LABEL_ALIGN_LEFT);
lv_obj_set_pos(p_label_noise, 0, 36);
lv_obj_set_size(p_label_noise, 128, 64);
lv_label_set_text(p_label_noise, "Noise level:");
pGui_bar_noise = lv_bar_create(lv_scr_act(), NULL);
lv_obj_set_size(pGui_bar_noise, 120, 10);
lv_obj_align(pGui_bar_noise, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -1);
lv_bar_set_anim_time(pGui_bar_noise, 200);
lv_bar_set_range(pGui_bar_noise, 1, 100);
lv_bar_set_type(pGui_bar_noise, LV_BAR_TYPE_NORMAL);
lv_bar_set_value(pGui_bar_noise, 50, LV_ANIM_OFF);
lv_obj_set_style_local_radius(pGui_bar_noise, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, 0); /*Add a local style*/
lv_obj_set_style_local_bg_color(pGui_bar_noise, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLACK);
static lv_style_t style;
lv_style_init(&style);
lv_style_set_radius(&style, LV_STATE_DEFAULT, 0);//这里的参数0意思是进度条的指示器样式弧度为零,也就是直角。
lv_style_set_bg_color(&style, LV_STATE_DEFAULT, LV_COLOR_WHITE);//进度条背景颜色
lv_style_set_border_width(&style, LV_STATE_DEFAULT, 1); //进度条背景线条宽度
lv_style_set_border_color(&style, LV_STATE_DEFAULT, LV_COLOR_BLACK);//颜色
lv_style_set_pad_top(&style, LV_STATE_DEFAULT, 2);//指示器到背景四周的距离
lv_style_set_pad_bottom(&style, LV_STATE_DEFAULT, 2);
lv_style_set_pad_left(&style, LV_STATE_DEFAULT, 2);
lv_style_set_pad_right(&style, LV_STATE_DEFAULT, 2);
lv_obj_add_style(pGui_bar_noise, LV_BAR_TYPE_NORMAL, &style);//样式加到进度条中
//https://www.csdn.net/tags/MtTaEg4sMjI1OTA0LWJsb2cO0O0O.html
pGui_label_temp = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(pGui_label_temp, LV_LABEL_ALIGN_RIGHT);
lv_obj_set_pos(pGui_label_temp, 90, 12);
lv_obj_set_size(pGui_label_temp, 128, 64);
sprintf((char*)cdata, "%.1fC", 25.68);//格式化输出 浮点数转成字符串输出
lv_label_set_text_fmt(pGui_label_temp,"%s", (const char*)cdata);
pGui_label_humi = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(pGui_label_humi, LV_LABEL_ALIGN_RIGHT);
lv_obj_set_pos(pGui_label_humi, 90, 24);
lv_obj_set_size(pGui_label_humi, 128, 64);
sprintf((char*)cdata, "%.1f%%", 55.8);//格式化输出 浮点数转成字符串输出
lv_label_set_text_fmt(pGui_label_humi,"%s", (const char*)cdata);
pGui_label_noise = lv_label_create(lv_scr_act(), NULL);
lv_label_set_align(pGui_label_noise, LV_LABEL_ALIGN_RIGHT);
lv_obj_set_pos(pGui_label_noise, 90, 36);
lv_obj_set_size(pGui_label_noise, 128, 64);
lv_label_set_text_fmt(pGui_label_noise, "%ddB", 55);
}
static void gui_lvgl_task(void *arg)
{
lv_init();
/*Initialize for LittlevGL*/
oled_init();
/*Select display 1*/
// demo_create();
gui_label_create();
while (1) {
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
aos_msleep(5);
lv_tick_inc(1);
}
}
</code></pre>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">由于我还没有调通各个参数的检测程序,这块只好先创建一个任务,制造了模拟数据,让界面先动起来,展示效果。代码如下。</span></span></span></span></p>
<pre>
<code class="language-cpp">struct Result_S
{
float temp;
float humi;
int noise;
}res_data;
static void res_update_task(void *arg)
{
int num_temp = 200;
char cdata = { 0 };
while(1)
{
num_temp++;
if(num_temp>1000)
{
num_temp = 200;
}
res_data.temp = num_temp / 20.0;
res_data.humi = num_temp / 10.0;
res_data.noise = num_temp % 99;
sprintf((char*)cdata, "%.1fC", res_data.temp);//格式化输出 浮点数转成字符串输出
lv_label_set_text_fmt(pGui_label_temp,"%s", (const char*)cdata);
sprintf((char*)cdata, "%.1f%%", res_data.humi);//格式化输出 浮点数转成字符串输出
lv_label_set_text_fmt(pGui_label_humi,"%s", (const char*)cdata);
lv_label_set_text_fmt(pGui_label_noise, "%ddB", res_data.noise);
lv_bar_set_value(pGui_bar_noise, res_data.noise+1, LV_ANIM_OFF);
aos_msleep(500);
}
}</code></pre>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">界面动态效果如下。等将来把检测参数调通,将结果赋给对应的变量就能完成正式的界面显示。</span></span></span></span></p>
<p class="imagemiddle" style="text-align: center;"></p>
<p align="center" style="text-align:center"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">图4、动态显示效果</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"><span style="font-size:10.5pt"><span style="font-family:等线"><span style="font-size:14.0pt"><span style="font-family:黑体">至此,环境监测终端界面显示设计完成,通过此次实操,基本了解使用LVGL设计UI的过程,为后边设计UI又增加了一个新思路。</span></span></span></span></p>
<p style="text-indent:28.0pt; text-align:justify"></p>
<p>看到那个刷新的斜纹,总感觉是bug</p>
nmg 发表于 2022-4-11 10:33
看到那个刷新的斜纹,总感觉是bug
<p>单色OLED屏幕大多有这个问题,没找到这款屏的资料,不然可以研究一下刷新率</p>
sipower 发表于 2022-4-11 13:56
单色OLED屏幕大多有这个问题,没找到这款屏的资料,不然可以研究一下刷新率
<p>屏的资料板厂应该能要到</p>
我原来也想用LVGL进行展示,但是一但添加wifi,编译就会显示内存不足,编译不过,不知道你试了这方面的内容吗? lugl4313820 发表于 2022-4-13 19:45
我原来也想用LVGL进行展示,但是一但添加wifi,编译就会显示内存不足,编译不过,不知道你试了这方面的内容 ...
<p>这个还没试,如果不行的话,就考虑自己做ui程序</p>
sipower 发表于 2022-4-13 19:55
这个还没试,如果不行的话,就考虑自己做ui程序
<p>我是移植过来U8g2感觉还是占了很多资源,特别是字库,所以后期还是考虑换回自己的字库。</p>
lugl4313820 发表于 2022-4-13 20:19
我是移植过来U8g2感觉还是占了很多资源,特别是字库,所以后期还是考虑换回自己的字库。
<p>为了省资源,可以就做一张图片,把条目,抬头,单位什么的都做上,然后就做10个阿拉伯数字的字库就行了。<img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/lol.gif" width="48" /></p>
页:
[1]