千家信息网

LVGL在rt-thread上的移植是怎样的

发表于:2024-10-09 作者:千家信息网编辑
千家信息网最后更新 2024年10月09日,LVGL在rt-thread上的移植是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。显示驱动的编写首先按照rt-thread的
千家信息网最后更新 2024年10月09日LVGL在rt-thread上的移植是怎样的

LVGL在rt-thread上的移植是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

显示驱动的编写

首先按照rt-thread的lcd驱动框架完成驱动的编写,可参考如下结构体,完成相关函数的实现。

struct rt_device_graphic_ops{    void (*set_pixel) (const char *pixel, int x, int y);    void (*get_pixel) (char *pixel, int x, int y);    void (*draw_hline)(const char *pixel, int x1, int x2, int y);    void (*draw_vline)(const char *pixel, int x, int y1, int y2);    void (*blit_line) (const char *pixel, int x, int y, rt_size_t size);};

在完成函数编写后,进行操作结构体的定义。

struct rt_device_graphic_ops fsmc_lcd_ops ={    LCD_DrawPoint,    LCD_ReadPoint,    LCD_HLine,    RT_NULL,    LCD_BlitLine,};

然后,按照显示屏设备的具体信息进行填写,并将设备挂载到设备驱动列表。

int drv_lcd_hw_init(void){    rt_err_t result = RT_EOK;    struct rt_device *device = &_lcd.parent;    /* memset _lcd to zero */    memset(&_lcd, 0x00, sizeof(_lcd));    _lcd.lcd_info.bits_per_pixel = 16;    _lcd.lcd_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565;    device->type = RT_Device_Class_Graphic;#ifdef RT_USING_DEVICE_OPS    device->ops = &lcd_ops;#else    device->init = drv_lcd_init;    device->control = drv_lcd_control;#endif    device->user_data = &fsmc_lcd_ops;    rt_device_register(device, "lcd", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);    return result;}INIT_DEVICE_EXPORT(drv_lcd_hw_init);

rt-thread显示驱动与LVGL对接

关于lvgl的相关参数设备及移植的详细说明见 官方移植说明,在此不做过多说明。

此部分对接主要针对lv_port_disp.c文件中lvgl显示驱动和rt-thread驱动接口的对接部分做下介绍。

显示初始化

此部分主要完成显示设备的查找和打开操作。

/* Initialize your display and the required peripherals. */static void disp_init(void){    /*You code here*/    lcd_device = rt_device_find("lcd");    if (!lcd_device)    {        LOG_E("find %s failed!", "lcd");        return;    }    rt_device_open(lcd_device, RT_DEVICE_FLAG_RDWR);}

显示数据的刷写

该部分需要完成指定区域的显示像素内容的写入,可以进行像素点操作或行列操作,可以结合自己显示屏的特性进行调整,此部分刷入的方案也是会影响显示的刷新率,需要尽可以选择刷新速度最快的方案。

/* 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){    /*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)*/    //         rt_graphix_ops(lcd_device)->set_pixel((const char *)&color_p->full, x, y);    //         color_p++;    //     }    // }    int32_t y;    int32_t width;    for (y = area->y1; y <= area->y2; y++)    {        width =  (area->x2 - area->x1 + 1);        rt_graphix_ops(lcd_device)->blit_line((const char *)&color_p->full, area->x1, y, width);        color_p += width;    }    /* IMPORTANT!!!     * Inform the graphics library that you are ready with the flushing*/    lv_disp_flush_ready(disp_drv);}

系统调用

在lvgl中有两个函数是依赖于系统的调用:lv_tick_inc和lv_task_handler(),注意这两个函数不能放到一个线程中,就避免相关事件响应机制出错。 我们可以创建一个软件定时器和一个任务分别来处理lvgl的系统调用。

    rt_thread_t tid;    tid = rt_thread_create("lvgl_task", lvgl_task, RT_NULL, 4096, 20, 4);    if (tid != RT_NULL)        rt_thread_startup(tid);    rt_timer_t timer1 = rt_timer_create("timer1", lvgl_tick, RT_NULL, 10, RT_TIMER_FLAG_PERIODIC);    if (timer1 != RT_NULL)        rt_timer_start(timer1);

在lvgl_task中,我们周期调用lv_task_handler()函数即可。

static void lvgl_task(void *parameter){    while (true)    {        rt_thread_delay(10);        lv_task_handler();    }}

相应的,在软定时器中,我们根据软件定时器的间隔,在超时处理中对lv_tick_inc注入时间间隔即可。

static void lvgl_tick(void *parameter){    lv_tick_inc(10);}

至此,已经完成rt-thread与lvgl的移植对接工作,可以进行应用层代码的编写。

关于LVGL在rt-thread上的移植是怎样的问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

0