ST77903 QSPI + STM32H750 + RTThread + LVGL(三)
前言
前面我们屏也点亮了,底层驱动接口也做好了,现在加个LVGL的实际效果看看吧,lvgl在csdn有很多的参考文章,这里就不再具体普及了。。。。。
一、修改配置
代码如下(示例):
/* Maximal horizontal and vertical resolution to support by the library.*/
#define LV_HOR_RES_MAX (400)
#define LV_VER_RES_MAX (400)
/* Color depth:
* - 1: 1 byte per pixel
* - 8: RGB332
* - 16: RGB565
* - 32: ARGB8888
*/
#define LV_COLOR_DEPTH 32
LV没有RGB888-24BIT,只能选用ARGB8888-32BIT了,对于实际底层传输会有一些效率问题,这也没办法
二、行缓冲配置
代码如下(示例):
static lv_disp_buf_t disp_buf_1;
static uint32_t disp_cache[SRAM1_SIZE / 4] __attribute__ ((at(SRAM1_BASE)));
#define BUF1_ROWS (SRAM1_SIZE / (LV_HOR_RES_MAX * sizeof(lv_color_t)))
lv_disp_buf_init(&disp_buf_1, disp_cache, NULL, LV_HOR_RES_MAX * BUF1_ROWS);
LV会现在行缓冲区绘图,然后再传给显示屏FRAME BUFFER,行缓冲区可以尽量配置大一些,可以提高绘图效率
三、显示屏驱动接口
代码如下(示例):
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
lcdqspi_wait_te();
for (uint32_t y = area->y1; y <= area->y2; y++)
{
lcdqspi_draw_line(area->x1, area->x2, y, (uint32_t *)color_p);
color_p = color_p + area->x2 - area->x1 + 1;
//rt_kprintf("draw %d\r\n", y);
}
lv_disp_flush_ready(disp_drv);
}
前面的LCD驱动接口派上用处了,LV每次传输图形数据前,先等一下TE,然后用lcdqspi_draw_line来给底层FRAME BUFFER的每一行来更新数据
四、测试代码
代码如下(示例):
static lv_obj_t * gauge1;
void lv_ex_gauge_2(void)
{
/*Describe the color for the needles*/
static lv_color_t needle_colors[3];
needle_colors[0] = LV_COLOR_BLUE;
needle_colors[1] = LV_COLOR_RED;
needle_colors[2] = LV_COLOR_LIME;
LV_IMG_DECLARE(img_hand);
/*Create a gauge*/
gauge1 = lv_gauge_create(lv_scr_act(), NULL);
lv_gauge_set_scale(gauge1, 360, 60, 12);
lv_gauge_set_needle_count(gauge1, 3, needle_colors);
lv_gauge_set_range(gauge1, 0, 59);
lv_obj_set_size(gauge1, 400, 400);
lv_obj_align(gauge1, NULL, LV_ALIGN_CENTER, 0, 0);
//lv_gauge_set_formatter_cb(lv_obj_t * gauge, lv_gauge_format_cb_t format_cb)
//lv_gauge_set_needle_img(gauge1, &img_hand, 4, 4);
/*Allow recoloring of the images according to the needles' color*/
//lv_obj_set_style_local_image_recolor_opa(gauge1, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, LV_OPA_COVER);
// lv_obj_set_style_local_line_width(gauge1, LV_GAUGE_PART_MAJOR, LV_STATE_DEFAULT, 3);
//lv_obj_set_style_local_line_width(gauge1, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3);
/* 表盘长刻度线条宽度 */
lv_obj_set_style_local_line_width(gauge1, LV_GAUGE_PART_MAJOR, LV_STATE_DEFAULT, 0);
/* 表盘长刻度线条颜色 */
lv_obj_set_style_local_line_color(gauge1, LV_GAUGE_PART_MAJOR, LV_STATE_DEFAULT, LV_COLOR_RED);
/* 表盘短刻度线条宽度 */
lv_obj_set_style_local_line_width(gauge1, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 5);
/* 表盘短刻度线条颜色 */
lv_obj_set_style_local_line_color(gauge1, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
/* 表盘内LABEL字体颜色 LABEL数量和长刻度数量角度一致 */
lv_obj_set_style_local_text_color(gauge1, LV_GAUGE_PART_MAJOR, LV_STATE_DEFAULT, LV_COLOR_LIME);
/* 表盘内刻度盘与外框边缘的距离 */
lv_obj_set_style_local_pad_all (gauge1, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 10);
/* 表盘背景颜色 */
lv_obj_set_style_local_bg_color(gauge1, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
/* 表盘外框边缘颜色 */
//lv_obj_set_style_local_border_color(gauge1, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
lv_obj_set_style_local_line_width(gauge1, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 10);
/*Set the values*/
lv_gauge_set_value(gauge1, 0, 10);
lv_gauge_set_value(gauge1, 1, 20);
lv_gauge_set_value(gauge1, 2, 30);
}
void gauge_run(void)
{
static uint32_t hh = 30;
static uint32_t mm = 0;
static uint32_t ss = 0;
ss += 1;
if (ss > 59){ss = 0;mm++;}
if (mm > 59){mm = 0;hh++;}
if (hh > 59){hh = 0;}
lv_gauge_set_value(gauge1, 0, hh);
lv_gauge_set_value(gauge1, 1, mm);
lv_gauge_set_value(gauge1, 2, ss);
}
static void lvgl_entry(void* parameter)
{
uint8_t count = 0;
lv_init();
lv_port_disp_init();
lv_ex_gauge_2();
while (1)
{
lv_task_handler();
rt_thread_delay(LVGL_THREAD_PERIOD);
}
}
int lvgl_thread_init(void)
{
rt_thread_t th = RT_NULL;
th = rt_thread_create("lvgl", lvgl_entry, RT_NULL,
THREAD_LVGL_STACK, THREAD_LVGL_PRIO, THREAD_LVGL_TICK);
if (th != RT_NULL)rt_thread_startup(th);
return 0;
}
LV官网找一个仪表盘的范例,修改一下参数,简单能看了。。。。。
五、效果
LVGL Watch
总结
本来想做些炫彩一些的手表界面,但是H750内部只有128K,外部的QSPI W25Q本来是用来存储用户CODE的,现在被用来跑LCD,所以能用的空间就很少了,hal lib要20多K,rt-thread要20多K, lvgl内核要60多K,这三个加起来就要110K多了,只能象征性演示指针转动了
如果用H743,内部1M Flash,就可以做很多功能,外部再加sensor,加TP,就更像个watch了
参考以下官网:
https://www.rt-thread.org/
https://www.st.com/content/st_com/en.html
https://lvgl.io/