你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32H745I-DISCO GuiDemo 】GuiDemo 适配LVGL

[复制链接]
andey 发布时间:2025-2-25 15:14

简介

在上一篇帖子(【STM32H745I-DISCO GuiDemo 】GuiDemo 适配LTDC驱动)已经适配了LTDC 的驱动,可以将framebuff 的数据刷新到屏幕上显示,在此基础上我们继续适配LVGL,LVGL 的适配网上的教程也很多在此不做额外的赘述,LVGL 的代码相互之间的耦合没那么高,移植的重点主要是将代码加入到工程编译,并将底层的显示刷线接口对接到LCD显示就完成了移植适配过程,本地使用LVGL 8.3.10 的版本。

Frame_buffer 配置

开发环境本地使用的IAR,将LVGL 代码加入工程编译通过后,我们需要先对接LVGL显示相关的接口,适配显示相关的接口需要配置显存,之前的LTDC驱动程序是将Framebuffer 映射到了flash 空间,默认工程M7 使用的RAM大小为128K,屏幕为480*272 显示使用的RGB565的数据格式,一帧Framebuffer 数据大小

显示缓冲区大小 = 480 x 272 x 16 / 8 = 261120 字节 ≈ 255KB

显然内存资源是不够开发LVGL应用,修改linkfile 将SRAM1 512K空间作为,FrameBuffer 空间使用,定义section “.fb”用来分配显存空间。

sram1_link.png

添加如下代码适配LCD显示接口

void lv_port_disp_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();

    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/

    /**
     * LVGL requires a buffer where it internally draws the widgets.
     * Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
     * The buffer has to be greater than 1 display row
     *
     * There are 3 buffering configurations:
     * 1. Create ONE buffer:
     *      LVGL will draw the display's content here and writes it to your display
     *
     * 2. Create TWO buffer:
     *      LVGL will draw the display's content to a buffer and writes it your display.
     *      You should use DMA to write the buffer's content to the display.
     *      It will enable LVGL to draw the next part of the screen to the other buffer while
     *      the data is being sent form the first buffer. It makes rendering and flushing parallel.
     *
     * 3. Double buffering
     *      Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
     *      This way LVGL will always provide the whole rendered screen in `flush_cb`
     *      and you only need to change the frame buffer's address.
     */

    /* Example for 1) */
    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_1[LCD_WIDTH * LCD_HEIGHT] @ ".fb";                             /*A buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, LCD_WIDTH * LCD_HEIGHT);   /*Initialize the display buffer*/

    /*-----------------------------------
     * Register the display in LVGL
     *----------------------------------*/

    static lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/

    /*Set the resolution of the display*/
    disp_drv.hor_res = LCD_WIDTH;
    disp_drv.ver_res = LCD_HEIGHT;

    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = disp_flush;

    /*Set a display buffer*/
    disp_drv.draw_buf = &draw_buf_dsc_1;

    /*Required for Example 3)*/
    //disp_drv.full_refresh = 1;

    /* Fill a memory array with a color if you have GPU.
     * Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.
     * But if you have a different GPU you can use with this callback.*/
    //disp_drv.gpu_fill_cb = gpu_fill;

    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
    /*You code here*/
}

volatile bool disp_flush_enabled = true;

/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL
 */
void disp_enable_update(void)
{
    disp_flush_enabled = true;
}

/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL
 */
void disp_disable_update(void)
{
    disp_flush_enabled = false;
}

/*Flush the content of the internal buffer the specific area on the display
 *You can use DMA or any hardware acceleration to do this operation in the background but
 *'lv_disp_flush_ready()' has to be called when finished.*/
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    if(disp_flush_enabled) {
        /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/

        int32_t x;
        int32_t y;
        for(y = area->y1; y <= area->y2; y++) {
            for(x = area->x1; x <= area->x2; x++) {
                /*Put a pixel to the display. For example:*/
                /*put_px(x, y, *color_p)*/
                lcd_buff[y][x] = color_p->full;
                color_p++;
            }
        }
    }

    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

添加完LTDC 的frame 操作方式后,我们需要开启FreeRtos 的tick hook 来驱动LVGL 的运行时间,cubmx 配置如下

lvgl_tick.png

在对应的hook函数中增加lvgl 的计数器

/* USER CODE BEGIN 3 */
void vApplicationTickHook( void )
{
   /* This function will be called by each tick interrupt if
   configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
   added here, but the tick hook is called from an interrupt context, so
   code must not attempt to block, and only the interrupt safe FreeRTOS API
   functions can be used (those that end in FromISR()). */
   lv_tick_inc(1);
}

板子验证

LVGL TASK 中添加lvgl 的music demo 代码

/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN 5 */
    printf("lvgl benchmark demo started\r\n");

    //lv_port_pre_init();
    lv_init();
    lv_port_disp_init();
    //lv_port_indev_init();

    //s_lvgl_initialized = true;

    extern void lv_demo_music(void);
    lv_demo_music();

    //void lv_demo_keypad_encoder(void);
    //lv_demo_keypad_encoder();

    for (;;)
    {
        lv_task_handler();
        vTaskDelay(5);
    }
  /* USER CODE END 5 */
}

烧写到板子后,LVGL DEMO 已经按照预期的运行起来,后续可以基于LVGL开发 GUI 应用了

20250225-151257.gif

收藏 评论0 发布时间:2025-2-25 15:14

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版