首页 > 系统相关 >分析lvgl的代码启动过程,对比esp32,stm32,linux

分析lvgl的代码启动过程,对比esp32,stm32,linux

时间:2022-08-20 17:13:30浏览次数:61  
标签:disp lv tick esp32 drv stm32 LV linux indev

lvgl是gui层负责绘制gui并根据输入设备的事件来响应重绘 ,然后把绘制的缓冲区发送给显示驱动去实际显示。

以下代码参考lvgl arduino官方例程,gui guider模拟器例程,,零知 stm32 fsmc lvgl例程

第0步 时钟

时钟是lvgl绘制gui的节拍器。获取时钟   在这个文件里  ..\lvgl\src\hal\lv_hal_tick.c

在arduino 中时钟是从 millis()这个函数获得的

#define LV_TICK_CUSTOM 1
#if LV_TICK_CUSTOM
    #define LV_TICK_CUSTOM_INCLUDE "Arduino.h"         /*Header for the system time function*/
    #define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis())    /*Expression evaluating to current system time in ms*/
#endif   /*LV_TICK_CUSTOM*/

 

stm32使用硬件timer   

HardwareTimer *MyTim;
    /*Initialize the graphics library's tick*/
    MyTim = new HardwareTimer(TIM2);
    MyTim->setMode(2, TIMER_OUTPUT_COMPARE);  // In our case, channekFalling is configured but not really used. Nevertheless it would be possible to attach a callback to channel compare match.
    MyTim->setOverflow(1000/LVGL_TICK_PERIOD, HERTZ_FORMAT); // period in Hz
    MyTim->attachInterrupt(lv_tick_handler);
    MyTim->resume();



static void lv_tick_handler(HardwareTimer*)
{
    
    lv_tick_inc(LVGL_TICK_PERIOD);
}

linux等使用 mingw标准库   <stddef.h>  里的宏定义  sys_time

#if !LV_TICK_CUSTOM
/**
 * You have to call this function periodically
 * @param tick_period the call period of this function in milliseconds
 */
LV_ATTRIBUTE_TICK_INC void lv_tick_inc(uint32_t tick_period)
{
    tick_irq_flag = 0;
    sys_time += tick_period;
}
#endif

第一步 核心初始化

lv核心初始化 完成各种结构体与函数的初始化   

  lv_init();

第二步  硬件抽象层

硬件虚拟层需要 完成  display, input devices, tick     也就是与驱动的对接,与输入设备的对接   完成tick (节拍)?

1 先看display 

先实例化底层显示驱动    

 

SDL驱动      monitor_init();

TFT espi驱动      tft.begin();          /* TFT init TFT初始化*/ 

  tft.setRotation( 1 ); /* Landscape orientation, flipped 设置方向*/

 

创造缓冲区

    /*Create a display buffer  SDL样式的*/  
    static lv_disp_draw_buf_t disp_buf1;
    static lv_color_t buf1_1[480 * 10];
    lv_disp_draw_buf_init(&disp_buf1, buf1_1, NULL, 480 * 10);
lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);

完成display到实际底层驱动的填充函数

 

/* Display flushing 显示填充  espi样式  */
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
    uint32_t w = ( area->x2 - area->x1 + 1 );
    uint32_t h = ( area->y2 - area->y1 + 1 );

    tft.startWrite();
    tft.setAddrWindow( area->x1, area->y1, w, h );
    tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
    tft.endWrite();

    lv_disp_flush_ready( disp );
}

直接写GRAM样式

void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{

    u16 height,width;
    u16 i,j;
    width=area->x2 - area->x1+1;             //得到填充的宽度
    height=area->y2 - area->y1+1;            //高度
    for(i=0;i<height;i++)
    {
        LCD_SetCursor(area->x1,area->y1+i);       //设置光标位置
        LCD_WriteRAM_Prepare();     //开始写入GRAM
        for(j=0;j<width;j++)
        {
            LCD_TYPE->LCD_RAM=color_p->full;//写入数据
            color_p++;
        }
    }
    
    lv_disp_flush_ready(disp); /* tell lvgl that flushing is done */
}

 

 

SDL样式

monitor_flush

 

 

创造display

    /*Initialize the display初始化display*/
    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = LV_HOR_RES_MAX;
    disp_drv.ver_res = LV_VER_RES_MAX;
    disp_drv.flush_cb = my_disp_flush;//  这里就用到了填充函数
    disp_drv.buffer = &disp_buf;
    lv_disp_drv_register(&disp_drv);

 

 

2 再看输入层

先初始化硬件接口 

TFT-esp 这样  触摸屏

    uint16_t calData[5] = { 187, 3596, 387, 3256, 5 };
    tft.setTouch( calData ); // espi如果设置了touch cs 自动完成触摸的初始化

 独立的xpt2046驱动 触摸屏

XPT2046_Touchscreen ts(CS_PIN, irq_pin);

 模拟器的鼠标键盘

mouse_init();//在模拟器里也完成了触摸回调函数

其他的滚轮键盘编码器也同样原理

对接触摸驱动 完成触摸回调函数

espi

/*Read the touchpad*/
/*读取触摸板*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
{
    uint16_t touchX, touchY;

    bool touched = tft.getTouch( &touchX, &touchY, 600 );

    if( !touched )
    {
        data->state = LV_INDEV_STATE_REL;
    }
    else
    {
        data->state = LV_INDEV_STATE_PR;

        /*Set the coordinates*/
        data->point.x = touchX;
        data->point.y = touchY;

        Serial.print( "Data x " );
        Serial.println( touchX );

        Serial.print( "Data y " );
        Serial.println( touchY );
    }
}

 

xpt2046

bool my_touchpad_read(lv_indev_drv_t * indev, lv_indev_data_t * data)
{
    static lv_coord_t last_x = 0;
    static lv_coord_t last_y = 0;

    /*Save the state and save the pressed coordinate*/
    data->state = ts.touched() ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
    if(data->state == LV_INDEV_STATE_PR){
        TS_Point p = ts.getPoint();
        
        //convert to lcd position
        last_x = LV_HOR_RES-(p.x *LV_HOR_RES)/4095;       /*TODO save the current X coordinate*/
        last_y = LV_VER_RES-(p.y *LV_VER_RES)/4095;       /*TODO save the current Y coordinate*/
        
        Serial.print("touched:");
        Serial.print(last_x);Serial.print(",");Serial.println(last_y);
    } 

    /*Set the coordinates (if released use the last pressed coordinates)*/
    data->point.x = last_x;
    data->point.y = last_y;

    return false; /*Return `false` because we are not buffering and no more data to read*/
}

完成lvgl输入驱动与硬件驱动的对接

触摸样式

    /*Initialize the (dummy) input device driver*/
    /*初始化(虚拟)输入设备驱动程序*/
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init( &indev_drv );
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = my_touchpad_read;//上一步的在这用到了
    lv_indev_drv_register( &indev_drv );

模拟器样式 使用鼠标

   /* Add the mouse as input device
     * Use the 'mouse' driver which reads the PC's mouse*/
    mouse_init();
    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);          /*Basic initialization*/
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = mouse_read;         /*This function will be called periodically (by the library) to get the mouse position and state*/
    lv_indev_t * mouse_indev = lv_indev_drv_register(&indev_drv);

 

3 初始化节拍

arduino 自动完成此步骤

模拟器

    /* Tick init.
     * You have to call 'lv_tick_inc()' in periodically to inform LittelvGL about how much time were elapsed
     * Create an SDL thread to do this*/
    SDL_CreateThread(tick_thread, "tick", NULL);

stm32

 

    /*Initialize the graphics library's tick*/
    MyTim = new HardwareTimer(TIM2);
    MyTim->setMode(2, TIMER_OUTPUT_COMPARE);  // In our case, channekFalling is configured but not really used. Nevertheless it would be possible to attach a callback to channel compare match.
    MyTim->setOverflow(1000/LVGL_TICK_PERIOD, HERTZ_FORMAT); // period in Hz
    MyTim->attachInterrupt(lv_tick_handler);
    MyTim->resume();

说实话我没怎么看懂

 

第三步  开始绘制gui

硬件抽象层完成初始化   就可以开始绘制ui

从sceen里创建各种widget    给widget添加事件回调  然后在无线循环里调用lv_timer_handler(),它会按LVGL_TICK_PERIOD 设置的事件重复的响应输入事件来重绘ui

 

这里简单绘制个label

    /*Create a Label on the currently active screen在当前屏幕上生成一个label*/
    lv_obj_t * label1 =  lv_label_create(lv_scr_act(), NULL);// lv_sce_act()可以获得当前屏幕

    /*Modify the Label's text设置文本*/
    lv_label_set_text(label1, "Hello world!");
    
    lv_obj_set_pos(label1, 0, 230);

    /* Align the Label to the center
     * NULL means align on parent (which is the screen now)
     * 0, 0 at the end means an x, y offset after alignment*/
// 

 

再给他添加一个触摸点击事件  ,让自己的显示文本添加一个感叹号 

 

标签:disp,lv,tick,esp32,drv,stm32,LV,linux,indev
From: https://www.cnblogs.com/kyo413/p/16608162.html

相关文章

  • 备份软件Veritas NetBackup(NBU)8.1.1的Linux客户端部署
    企业级备份软件VeritasNetBackup(NBU)8.1.1的Linux客户端部署原创 yuanfan2012 WalkingCloud 2022-06-1300:00 发表于浙江收录于合集#Linux学习笔记268个#C......
  • Linux系统中/var/log下常见日志文件详解
    1)/var/log/secure记录登录系统存取数据的文件2)/var/log/message几乎所有的开机系统发生的错误都会在此记录3)/var/log/maillog记录邮件的存取和往来4)/var/log/cron记......
  • linux检测系统是否被入侵
    linux检测系统是否被入侵(上)入门小站 入门小站 2022-06-1823:08 发表于湖北收录于合集#Linux485个入侵者在入侵成功后,往往会留下后门以便再次访问被入侵的系......
  • linux启动过程
    Linux系统启动过程科教 科教无界 2022-06-0807:16 发表于浙江收录于合集#科教152个#编程技能69个#Linux11个Linux启动时我们会看到许多启动信息。Linu......
  • linux 上特殊的权限位
    通常我们文件一般三种权限名称:读、写、执行标识:r、w、x二进制:4、2、1特殊权限也有三种名称:setuid、setgid、粘连位标识:s、s、t二进制:4、2、1setuid场......
  • 复习:linux 基础命令复习二
    文件查看cat从头到尾显示-A \\整合命令-vET-b \\列出行号-E \\将结尾的断行字符($)显示出来-n \\列出行号,空白行也会标志行号-T \\将tab键以^I表示-......
  • linux各文件类型解压/压缩命令
    1、tar解压:tar-xvffilename.tar打包:tar-cvffilename.tarfilename2、gz解压:gunzipfilename.gzorgzip-dFileName.gz压缩:gzipFileName3......
  • Linux添加alias简化命令
    一、简介linuxalias是命令的一种别称,输入alias可以看到像下面这样的结果:aliasvi="vim"也即,输入vi后,被自动定向到vim这个命令了。alias的作用就是,可以简写命令。二......
  • Linux驱动开发十三.platform设备驱动——3.设备树下的platform驱动
    在上一章节我们使用了platform框架在没有设备树的时候是如何使用的,不过现在的大多数半导体厂商都把设备树给我们完善了。区别就是在没有设备树信息的时候需要我们自己想总......
  • lvgl8.3移植arduino-以esp32为例 lvgl库里例程的使用(踩坑记录)
    这次实验使用最新的lvgl,目前是8.3.1  依旧是先配置好espi,确保显示正常,并运行TFT_eSPI库中的Generic->Touch_calibrate示例获得屏幕触摸数据添加lvlg库 ,最好也......