【平头哥RVB2601创意应用开发】第三篇 GUI Demo
[复制链接]
本帖最后由 oxygen_sh 于 2022-5-14 18:35 编辑
LVGL,全称是Light and Versatile Graphics Library,是一个面向嵌入式应用的开源的图像代码库。在线文档可通过下面链接访问。
https://docs.lvgl.io/latest/en/html/get-started/index.html
- LVGL对单色屏的颜色适配问题
首先我比较关心显示颜色问题。因为LVGL主要是支持彩色显示的,而RVB2601板上显示屏为单色屏。因此在RVB2601上使用LVGL就需要在颜色上做适配。看下RVB2601 SDK里是怎么解决这个问题的。
下面是CH2601 SDK中LVGL 颜色配置。
在lv_conf.h中,color depth 配置为1
/* Color depth:
* - 1: 1 byte per pixel
* - 8: RGB332
* - 16: RGB565
* - 32: ARGB8888
*/
#define LV_COLOR_DEPTH 1
在lv_color.h中,找到lv_color_t的定义:
#if LV_COLOR_DEPTH == 1
typedef uint8_t lv_color_int_t;
typedef lv_color1_t lv_color_t;
typedef union {
uint8_t full; /*must be declared first to set all bits of byte via initializer list */
union {
uint8_t blue : 1;
uint8_t green : 1;
uint8_t red : 1;
} ch;
} lv_color1_t;
所以CH2601 SDK中LVGL使用的是每个R/G/B颜色分量采用单比特表示的颜色格式。因为RVB2601是单色屏,此颜色格式不能直接使用,需要进一步映射为单色(亮或暗)。
通过对oled_draw_point()研究,只要某一像素点的r/g/b颜色分量不是全0,在RVB2601单色屏上,该点就点亮。
void oled_draw_point(uint8_t r, uint8_t c, uint8_t t)
{
if (t) {
SET_BIT(g_oled_ram[r / 8][c], ((r % 8)));
} else {
CLR_BIT(g_oled_ram[r / 8][c], (r % 8));
}
}
- LVGL Porting研究
下面研究一下lvgl porting部分的实现。Porting部分代码一般位于lvgl_porting或oled目录下
oled.c和oled.h两个文件中。
- 显示缓冲区:
LVGL支持双缓冲区,buf1为必选实现,buf2为可选实现。双缓冲区设计使得当前图像帧显示和下一帧图像渲染可以并行进行,提高显示速度。
定义两个显示缓冲区。
static lv_color_t buf1[64 * 128];
static lv_color_t buf2[64 * 128];
调用lv_disp_buf_init函数,利用buf1和buf2对lvgl显示缓冲区对象disp_buf1进行初始化和绑定。
/*Create a display buffer*/
static lv_disp_buf_t disp_buf1;
lv_disp_buf_init(&disp_buf1, buf1, buf2, 64 * 128);
- 图像刷新
SDK中oled显示刷新函数为oled_flush(),其代码实现:
static void oled_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
oled_draw_frame((uint8_t(*)[Max_Column])color_p);
oled_reflesh();
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(disp_drv);
}
其中oled_draw_frame()和oled_reflesh()两个函数如下:
void oled_draw_frame(uint8_t p[Max_Row][Max_Column])
{
unsigned char i, j;
for (i = 0; i < Max_Row; i++) {
for (j = 0; j < Max_Column; j++) {
oled_draw_point(i, j, p[j]);
}
}
}
void oled_reflesh()
{
unsigned char i, j;
for (i = 0; i < 8; i++) {
Set_Start_Page(i);
Set_Start_Column(0x00);
for (j = 0; j < 128; j++) {
Write_Data(g_oled_ram[j]);
}
}
}
- Lvgl显示驱动初始化
初始化显示驱动,绑定图像缓冲区,绑定图形刷新函数,以及设定图像显示方向等设置。
然后调用lv_disp_drv_register()函数,对图像显示驱动进行注册。
/*Create a display*/
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
disp_drv.buffer = &disp_buf1;
disp_drv.flush_cb = oled_flush;
disp_drv.rotated = 0;
lv_disp_drv_register(&disp_drv);
- 使用LVGL LABEL组件显示文字
使用LVGL LABEL组件显示字符。可设置显示对齐方式,各种对齐方式的定义见下图。
也可以设置文字滚屏显示。具体见下面视频。
void lv_ex_label_1(void)
{
lv_obj_t * label1 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(label1, LV_LABEL_LONG_BREAK); /*Break the long lines*/
lv_label_set_recolor(label1, true); /*Enable re-coloring by commands in the text*/
lv_label_set_align(label1, LV_LABEL_ALIGN_CENTER); /*Center aligned lines*/
lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label "
"and wrap long text automatically.");
lv_obj_set_width(label1, 150);
lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, -30);
lv_obj_t * label2 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(label2, LV_LABEL_LONG_SROLL_CIRC); /*Circular scroll*/
lv_obj_set_width(label2, 150);
lv_label_set_text(label2, "It is a circularly scrolling text. ");
lv_obj_align(label2, NULL, LV_ALIGN_CENTER, 0, 30);
}
演示视频:
3-1
|