溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

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

發(fā)布時(shí)間:2021-12-17 14:55:53 來(lái)源:億速云 閱讀:882 作者:柒染 欄目:互聯(lián)網(wǎng)科技

LVGL在rt-thread上的移植是怎樣的,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

顯示驅(qū)動(dòng)的編寫

首先按照rt-thread的lcd驅(qū)動(dòng)框架完成驅(qū)動(dòng)的編寫,可參考如下結(jié)構(gòu)體,完成相關(guān)函數(shù)的實(shí)現(xiàn)。

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);
};

在完成函數(shù)編寫后,進(jìn)行操作結(jié)構(gòu)體的定義。

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

然后,按照顯示屏設(shè)備的具體信息進(jìn)行填寫,并將設(shè)備掛載到設(shè)備驅(qū)動(dòng)列表。

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顯示驅(qū)動(dòng)與LVGL對(duì)接

關(guān)于lvgl的相關(guān)參數(shù)設(shè)備及移植的詳細(xì)說(shuō)明見(jiàn) 官方移植說(shuō)明,在此不做過(guò)多說(shuō)明。

此部分對(duì)接主要針對(duì)lv_port_disp.c文件中l(wèi)vgl顯示驅(qū)動(dòng)和rt-thread驅(qū)動(dòng)接口的對(duì)接部分做下介紹。

顯示初始化

此部分主要完成顯示設(shè)備的查找和打開(kāi)操作。

/* 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);
}

顯示數(shù)據(jù)的刷寫

該部分需要完成指定區(qū)域的顯示像素內(nèi)容的寫入,可以進(jìn)行像素點(diǎn)操作或行列操作,可以結(jié)合自己顯示屏的特性進(jìn)行調(diào)整,此部分刷入的方案也是會(huì)影響顯示的刷新率,需要盡可以選擇刷新速度最快的方案。

/* 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);
}

系統(tǒng)調(diào)用

在lvgl中有兩個(gè)函數(shù)是依賴于系統(tǒng)的調(diào)用:lv_tick_inc和lv_task_handler(),注意這兩個(gè)函數(shù)不能放到一個(gè)線程中,就避免相關(guān)事件響應(yīng)機(jī)制出錯(cuò)。 我們可以創(chuàng)建一個(gè)軟件定時(shí)器和一個(gè)任務(wù)分別來(lái)處理lvgl的系統(tǒng)調(diào)用。

    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中,我們周期調(diào)用lv_task_handler()函數(shù)即可。

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

相應(yīng)的,在軟定時(shí)器中,我們根據(jù)軟件定時(shí)器的間隔,在超時(shí)處理中對(duì)lv_tick_inc注入時(shí)間間隔即可。

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

至此,已經(jīng)完成rt-thread與lvgl的移植對(duì)接工作,可以進(jìn)行應(yīng)用層代碼的編寫。

關(guān)于LVGL在rt-thread上的移植是怎樣的問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI