2829|7

281

帖子

7

TA的资源

一粒金砂(高级)

楼主
 

【平头哥RVB2601创意应用开发】环境监测终端03-使用LVGL设计界面 [复制链接]

 

本篇文章介绍基于LVGL库在RVB2601开发板自带的OLED显示屏上设计界面。

RVB2601开发板内置了一款分辨率为128*64的单色OLED显示屏,并且基于此平台移植完成了开源的LVGL GUI库。此前并没有使用过LVGL GUI库,这次正好尝试一下,因此在网上一通搜索教程。正好找到了别人翻译好的使用手册,附在本文附件中,有需要的同学可以下载。

首先设计界面草稿。如下图所示,我计划在屏幕上显示5行信息。第一行,标题,直接使用标签显示即可。第二行,温度,左边字段不需要更新,右边字段需要定时刷新,也全部使用标签显示。第三行和第四行分别是湿度和噪音水平,和温度显示采用一样方法。第五行计划做一个指示条,用来动态指示噪音的实时幅度,这样查看起来比较直观。

图1、界面草图

实际设计的时候遇到各种问题。首先是如何显示中文,经查询得知要自己制作内置字库并添加,看了几个教程,很繁琐的样子,本人犯懒了,决定跳过这个中文显示,改用英文也是一样。

下一个问题是默认使用的英文字体是“LV_FONT_MONTSERRAT_14”比较大,如果显示5行看着太挤了,通过更改配置项使用“LV_FONT_MONTSERRAT_12”字体相对好一点。我还试了改成更小的字体,有点惨不忍睹,都不能分辨了,有点像大片上的火星文。具体修改方法如下图。

图2、修改字体

接下来实际编程显示文字。做标题显示的时候,看到LVGL支持滚动显示,为了体现咱的学习成果,把原计划的两个单词的标题改成了一句话,让它在最上面滚动显示,比较好玩。具体设置方式参见下面代码。

在设置温度显示的时候,需要显示浮点数,我按照常规的方式写代码发现不能正常显示,然后查阅资料发现应该是为了提高效率,默认设置成了不支持浮点模式。本来想查手册改成支持浮点模式,后面看到有人采用了更妙的方法解决了。就是先将浮点数格式化成字符串,然后再以字符串显示就没问题了,我按照此方法操作,顺利解决此问题,具体方法参照下面代码。

最后一个要实现的是噪音指示条。经过反复查阅手册,最终确定使用进度条“LV_BAR”控件设计。直接按照手册简单例程搞上去后,发现两端都是圆角,不是我喜欢了类型。然后一通大搜索,网络是个好东西,又被我找到解决方案了,感兴趣的朋友可以参考以下帖子。

https://www.csdn.net/tags/MtTaEg4sMjI1OTA0LWJsb2cO0O0O.html

经过我反复修改和调试,终于把界面框架搭建出来,显示效果如下图。

图3、界面框架

整个框架初始化代码如下。

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[10] = { 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);
    }
}

由于我还没有调通各个参数的检测程序,这块只好先创建一个任务,制造了模拟数据,让界面先动起来,展示效果。代码如下。

struct Result_S
{                     
    float temp; 
	float humi; 
	int noise;
}res_data;                  

static void res_update_task(void *arg)
{
	int num_temp = 200;
	char cdata[10] = { 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);
	}
}

界面动态效果如下。等将来把检测参数调通,将结果赋给对应的变量就能完成正式的界面显示。

图4、动态显示效果

至此,环境监测终端界面显示设计完成,通过此次实操,基本了解使用LVGL设计UI的过程,为后边设计UI又增加了一个新思路。

LVGL Documentation.zip (5.34 MB, 下载次数: 12)

最新回复

我是移植过来U8g2感觉还是占了很多资源,特别是字库,所以后期还是考虑换回自己的字库。   详情 回复 发表于 2022-4-13 20:19
点赞 关注
 
 

回复
举报

5260

帖子

239

TA的资源

管理员

沙发
 

看到那个刷新的斜纹,总感觉是bug

加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身

点评

单色OLED屏幕大多有这个问题,没找到这款屏的资料,不然可以研究一下刷新率  详情 回复 发表于 2022-4-11 13:56
 
 
 

回复

281

帖子

7

TA的资源

一粒金砂(高级)

板凳
 
nmg 发表于 2022-4-11 10:33 看到那个刷新的斜纹,总感觉是bug

单色OLED屏幕大多有这个问题,没找到这款屏的资料,不然可以研究一下刷新率

点评

屏的资料板厂应该能要到  详情 回复 发表于 2022-4-12 16:24
 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

4
 
sipower 发表于 2022-4-11 13:56 单色OLED屏幕大多有这个问题,没找到这款屏的资料,不然可以研究一下刷新率

屏的资料板厂应该能要到

个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

6960

帖子

11

TA的资源

版主

5
 
我原来也想用LVGL进行展示,但是一但添加wifi,编译就会显示内存不足,编译不过,不知道你试了这方面的内容吗?

点评

这个还没试,如果不行的话,就考虑自己做ui程序  详情 回复 发表于 2022-4-13 19:55
 
 
 

回复

281

帖子

7

TA的资源

一粒金砂(高级)

6
 
lugl4313820 发表于 2022-4-13 19:45 我原来也想用LVGL进行展示,但是一但添加wifi,编译就会显示内存不足,编译不过,不知道你试了这方面的内容 ...

这个还没试,如果不行的话,就考虑自己做ui程序

点评

我是移植过来U8g2感觉还是占了很多资源,特别是字库,所以后期还是考虑换回自己的字库。  详情 回复 发表于 2022-4-13 20:19
 
 
 

回复

6960

帖子

11

TA的资源

版主

7
 
sipower 发表于 2022-4-13 19:55 这个还没试,如果不行的话,就考虑自己做ui程序

我是移植过来U8g2感觉还是占了很多资源,特别是字库,所以后期还是考虑换回自己的字库。

点评

为了省资源,可以就做一张图片,把条目,抬头,单位什么的都做上,然后就做10个阿拉伯数字的字库就行了。  详情 回复 发表于 2022-4-13 20:22
 
 
 

回复

281

帖子

7

TA的资源

一粒金砂(高级)

8
 
lugl4313820 发表于 2022-4-13 20:19 我是移植过来U8g2感觉还是占了很多资源,特别是字库,所以后期还是考虑换回自己的字库。

为了省资源,可以就做一张图片,把条目,抬头,单位什么的都做上,然后就做10个阿拉伯数字的字库就行了。

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表