Integración en el proyecto LVGL de una librería gráfica para microcontroladores

LVGL : biblioteca de gráficos ligera y versátil también conocida como LittleVGL.





La biblioteca admite una gran cantidad de microcontroladores como STM32, ESP32 y otros. Hasta ahora he logrado ejecutar un programa de demostración completo en ESP32 y STM32f429 Discovery. La biblioteca es de código abierto, admite una gran cantidad de elementos gráficos con temas oscuros y claros. Distribuido bajo la licencia MIT. Puede usarse libremente incluso en productos comerciales. Puede ver una demostración en línea interactiva sin instalarla en el dispositivo



La biblioteca admite la conexión de dos tipos de pantalla



  1. Directamente a través de la interfaz RGB donde el búfer estará en el lado de la MCU en la RAM interna o SDRAM externa
  2. A través de un controlador de pantalla externo. En este caso, la MCU puede comunicarse con el controlador de pantalla a través del bus SPI o I2C. Para mejorar el rendimiento, en este caso también se pueden utilizar búferes de renderizado intermedios dentro de la MCU.


Dos configuraciones de hardware típicas
MCU with TFT/LCD driver If your MCU has a TFT/LCD driver periphery then you can connect a display directly via RGB interface. In this case, the frame buffer can be in the internal RAM (if the MCU has enough RAM) or in the external RAM (if the MCU has a memory interface).



External display controller If the MCU doesn't have TFT/LCD driver interface then an external display controller (E.g. SSD1963, SSD1306, ILI9341) has to be used. In this case, the MCU can communicate with the display controller via Parallel port, SPI or sometimes I2C. The frame buffer is usually located in the display controller which saves a lot of RAM for the MCU.





Todo es muy flexible en este sentido. Si tiene un controlador, pero la biblioteca aún no tiene un puerto para este controlador, puede integrar fácilmente la biblioteca en su proyecto usted mismo.



La forma más fácil, pero también la más lenta, es reescribir la devolución de llamada del dibujo: my_flush_cb



void my_flush_cb(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, y;
    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            put_px(x, y, *color_p)
            color_p++;
        }
    }

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


put_px: esta es la representación de píxeles de su controlador. Debido al hecho de que el renderizado es píxel a píxel, esto es lento. La documentación de la biblioteca detalla otros métodos de integración más eficientes:



Integración de LVGL en el proyecto. El primero es inicializar la biblioteca, la pantalla y el sistema de entrada.




   lv_init();
   tft_init();
   touchpad_init();

   lv_demo_widgets();  //     


Dado que la biblioteca tiene un administrador de tareas dentro de sí misma. Sí, este es un sistema multiproceso, corrígeme si no es así, entonces necesitamos aumentar el contador interno del despachador llamando a lv_tick_inc



void * tick_thread (void *args)
{
      while(1) {
        usleep(5*1000);   /*Sleep for 5 millisecond*/
        lv_tick_inc(5);      /*Tell LVGL that 5 milliseconds were elapsed*/
    }
}


Además, es necesario transferir a la función los milisegundos que han pasado desde el momento de su última llamada, es decir, el tiempo desde el momento de la iteración anterior.



Para no desperdiciar recursos en un hilo adicional, puede llamar a esta función en una interrupción del temporizador. STM32 tiene un temporizador SysTick para tales fines:




void systickInit (uint16_t frequency)
{
   RCC_ClocksTypeDef RCC_Clocks;
   RCC_GetClocksFreq (&RCC_Clocks);
   (void) SysTick_Config (RCC_Clocks.HCLK_Frequency / frequency);
}

extern "C" void SysTick_Handler (void)
 {
      lv_tick_inc(1);    // 1 ms
 }


Temporizador SysTick
This timer is dedicated to real-time operating systems, but could also be used as a standard

downcounter. It features:



  • A 24-bit downcounter
  • Autoreload capability
  • Maskable system interrupt generation when the counter reaches 0
  • Programmable clock source.




También es necesario llamar a lv_task_handler en el ciclo. Se recomienda sacudirlo cada 5 ms para asegurar una buena respuesta. Intenté aumentar a 20 ms y el sistema seguía siendo bastante sensible y fluido. Se puede dejar como un bucle eterno o usar Thread



while(1) {
  lv_task_handler();
  my_delay_ms(5);
}


Los bucles deben estar en diferentes lugares. Cometí un error y metí lv_tick_inc y lv_task_handler en un bucle. Esto es lo que resultó: frenos



Cuando ambos métodos se dividieron en diferentes flujos en los intervalos correctos, todo funcionó de manera correcta y rápida:





La biblioteca tiene la capacidad de personalizar la cantidad de búferes internos:



  1. Un búfer cuando LVGL dibuja el contenido de la pantalla en un búfer y lo envía a la pantalla
  2. Dos búferes de pantalla parcial, mientras se procesan en un búfer, el contenido del otro búfer se envía para mostrarse en segundo plano
  3. Dos búferes de pantalla completa


El sitio tiene un conversor de fuentes e imágenes . Puede agregar de forma segura su fuente al proyecto o su icono en el menú. Además, puede cargar imágenes de forma opcional desde un almacenamiento externo, como CD-CARD, o desde una matriz de bytes ubicada en la memoria Flash interna.



¿Cómo usar el archivo generado en LittlevGL?
For C arrays

Copy the result C file into your LittlevGL project

In a C file of your application declare the image as: LV_IMG_DECLARE(my_image_name);

Set the image for an lv_img object: lv_img_set_src(img1, &my_image_name);

For external binary files (e.g. SD card)

Set up a new driver. To learn more read the Tutorial.

Set the image for an lv_img object: lv_img_set_src(img1, «S:/path/to/image»);



Otra característica importante y agradable de esta biblioteca es que puede usar el IDE de Eclipse en Linux y Windows para depurarlo.







Es bueno que la biblioteca OpenSource esté bien documentada. Hay muchos ejemplos y puertos. La biblioteca se ha convertido en una comunidad bastante grande .



Lancé un puerto para ESP32. Incluso cuando se usa mapeo para pines SPI, es decir, no los predeterminados, en los que se obtiene la mejor velocidad en baudios, todo funcionó sin ralentizaciones:



ESP32 ST7789 LVGL

ESP32 ILI9341 LVGL



Materiales relacionados
docs.lvgl.io/latest/en/html/porting/sys.html

Basic systick configuration on the STM32




All Articles