• esp32 arduino 移植lvgl,oled显示,lvgl屏幕建立,屏幕切换,图片显示,手动发送事件,触发部件响应其对应的回调函数,label,bar,line,style简单使用,显示字体修改


    屏幕采用的是128*64的分辨率的OLED,驱动ic应该是SSD1306,这个刚好支持129*64的,但是就是单色屏,用的是IIC接口

    1,OLED设置:

    管脚配置如下:

    SSD1306Wire  display(0x3c, 4, 15);//实例化OLED显示,设置管脚,该方法输入参数:uint8_t _address, uint8_t _sda, uint8_t _scl

    由于我的OLED的库没有清除像素点的函数,而在lvgl的显示驱动函数中,需要设置一下,基于OLED显示的lvgl移植的关键点之一就是将LVGL的显示接口与

    OLED的显示接口对应,在显示驱动函数中实现。所以我在源库文件(OLEDDisplay.cpp)里添加了像素点清除函数如下所示:当然在OLEDDisplay.h声明也少不了,就不贴代码啦。

    void OLEDDisplay::clearPixel(int16_t x, int16_t y) {
      if (x >= 0 && x < 128 && y >= 0 && y < 64) {
        switch (color) {
          case WHITE:   buffer[x + (y / 8) * DISPLAY_WIDTH] &= ~(1 << (y & 7)); break;
          case BLACK:   buffer[x + (y / 8) * DISPLAY_WIDTH] |=  (1 << (y & 7)); break;
          case INVERSE: buffer[x + (y / 8) * DISPLAY_WIDTH] ^=  (1 << (y & 7)); break;
        }
      }
    }

    2,lvgl移植

    首先贴上官方基于arduino的LVGL库中的说明文档。

    <h1 align="center"> LVGL - Light and Versatile Graphics Library</h1>
    <p align="center">
    <a href="https://github.com/lvgl/lvgl/blob/master/LICENCE.txt"><img src="https://img.shields.io/badge/licence-MIT-blue.svg"></a>
    <a href="https://github.com/lvgl/lvgl/releases/tag/v7.0.0"><img src="https://img.shields.io/badge/version-7.0.0-blue.svg"></a>
    </p>
    
    <p align="center">
    <img src="https://lvgl.io/assets/images/img_1.png">
    </p>
    
    <p align="center">
    LVGL provides everything you need to create embedded GUI with easy-to-use graphical elements, beautiful visual effects and low memory footprint. 
    </p>
    
    <h4 align="center">
    <a href="https://lvgl.io">Website </a> &middot; 
    <a href="https://lvgl.io/demos">Live demo</a> &middot; 
    <a href="https://docs.lvgl.io/">Docs</a> &middot; 
    <a href="https://forum.lvgl.io">Forum</a> &middot;
    <a href="https://blog.lvgl.io/">Blog</a>
    </h4>
    
    ---
    
    - [Features](#features)
    - [Supported devices](#supported-devices)
    - [Quick start in a simulator](#quick-start-in-a-simulator)
    - [Add LVGL to your project](#add-lvgl-to-your-project)
    - [Learn the basics](#learn-the-basics)
    - [Examples](#examples)
    - [Release policy](#release-policy)
    - [Contributing](#contributing)
    
    
    ## Features
    * **Powerful building blocks** buttons, charts, lists, sliders, images, etc.
    * **Advanced graphics** with animations, anti-aliasing, opacity, smooth scrolling
    * **Simultaneously use various input devices** touchscreen, mouse, keyboard, encoder, buttons, etc.
    * **Simultaneously use multiple displays** i.e. monochrome and color display
    * **Multi-language support** with UTF-8 encoding, Bidirectional support, and Arabic text handling
    * **Fully customizable** graphical elements
    * **Hardware independent** to use with any microcontroller or display
    * **Scalable** to operate with little memory (64 kB Flash, 10 kB RAM)
    * **OS, External memory and GPU** supported but not required
    * **Single frame buffer** operation even with advances graphical effects
    * **Written in C** for maximal compatibility (C++ compatible)
    * **Micropython Binding** exposes [LVGL API in Micropython](https://blog.lvgl.io/2019-02-20/micropython-bindings)
    * **Simulator** to develop on PC without embedded hardware
    * **Tutorials, examples, themes** for rapid development
    * **Documentation** and API references
    
    ## Supported devices
    Basically, every modern controller  (which is able to drive a display) is suitable to run LVGL. The minimal requirements are:
    - 16, 32 or 64 bit microcontroller or processor
    - &gt; 16 MHz clock speed is recommended
    - Flash/ROM: &gt; 64 kB for the very essential components (&gt; 180 kB is recommended)
    - RAM: 
      - Static RAM usage: ~2 kB depending on the used features and objects types
      - Stack: &gt; 2kB (&gt; 8 kB is recommended)
      - Dynamic data (heap): &gt; 2 KB (&gt; 16 kB is recommended if using several objects).
        Set by `LV_MEM_SIZE` in *lv_conf.h*. 
      - Display buffer:  &gt; *"Horizontal resolution"* pixels (&gt; 10 &times; *"Horizontal resolution"* is recommended) 
    - C99 or newer compiler
    
    *Note that the memory usage might vary depending on the architecture, compiler and build options.*
    
    Just to mention some **platforms**:
    - STM32F1, STM32F3, [STM32F4](https://blog.lvgl.io/2017-07-15/stm32f429_disco_port), [STM32F7](https://github.com/lvgl/lv_port_stm32f746_disco_sw4stm32)
    - Microchip dsPIC33, PIC24, PIC32MX, PIC32MZ
    - NXP Kinetis, LPC, iMX
    - [Linux frame buffer](https://blog.lvgl.io/2018-01-03/linux_fb) (/dev/fb)
    - [Raspberry PI](http://www.vk3erw.com/index.php/16-software/63-raspberry-pi-official-7-touchscreen-and-littlevgl)
    - [Espressif ESP32](https://github.com/lvgl/lv_port_esp32)
    - Nordic nrf52
    - Quectell M66
    
    ## Quick start in a simulator
    The easiest way to get started with LVGL is to run it in a simulator on your PC without any embedded hardware. 
    
    Choose a project with your favourite IDE:
    
    |   Eclipse   |  CodeBlocks | Visual Studio | PlatformIO | Qt Creator |
    |-------------|-------------|---------------|-----------|------------|
    |  [![Eclipse](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//eclipse.jpg)](https://github.com/lvgl/lv_sim_eclipse_sdl) | [![CodeBlocks](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//codeblocks.jpg)](https://github.com/lvgl/lv_sim_codeblocks_win) | [![VisualStudio](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//visualstudio.jpg)](https://github.com/lvgl/lv_sim_visual_studio_sdl) |   [![PlatformIO](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//platformio.jpg)](https://github.com/lvgl/lv_platformio) | [![QtCreator](https://raw.githubusercontent.com/lvgl/docs/master/v7/misc//qtcreator.jpg)](https://blog.lvgl.io/2019-01-03/qt-creator) |
    | Cross-platform<br>with SDL<br>(Recommended on<br>Linux and Mac) | Native Windows | Windows<br>with SDL | Cross-platform<br>with SDL | Cross-platform<br>with SDL |
    
    
    ## Add LVGL to your project
    
    The steps below show how to setup LVGL on an embedded system with a display and a touchpad. 
    You can use the [Simulators](https://docs.lvgl.io/v7/en/html/get-started/pc-simulator) to get ready to use projects which can be run on your PC. 
    
    1. [Download](https://github.com/lvgl/lvgl/archive/master.zip) or [Clone](https://github.com/lvgl/lvgl) the library
    2. Copy the `lvgl` folder into your project
    3. Copy `lvgl/lv_conf_template.h` as `lv_conf.h` next to the `lvgl` folder, change the `#if 0` statement near the top of the file to `#if 1` and set at least `LV_HOR_RES_MAX`, `LV_VER_RES_MAX` and `LV_COLOR_DEPTH`.
    4. Include `lvgl/lvgl.h` where you need to use LVGL related functions.
    5. Call `lv_tick_inc(x)` every `x` milliseconds (should be 1..10) in a Timer or Task. It is required for the internal timing of LVGL.
    6. Call `lv_init()`
    7. Create a display buffer for LVGL
    ```c
    static lv_disp_buf_t disp_buf;
    static lv_color_t buf[LV_HOR_RES_MAX * 10];                     /*Declare a buffer for 10 lines*/
    lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);    /*Initialize the display buffer*/
    ```
    8. Implement and register a function which can copy a pixel array to an area of your display:
    ```c
    lv_disp_drv_t disp_drv;               /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);          /*Basic initialization*/
    disp_drv.flush_cb = my_disp_flush;    /*Set your driver function*/
    disp_drv.buffer = &disp_buf;          /*Assign the buffer to the display*/
    lv_disp_drv_register(&disp_drv);      /*Finally register the driver*/
        
    void my_disp_flush(lv_disp_t * disp, const lv_area_t * area, lv_color_t * color_p)
    {
        int32_t x, y;
        for(y = area->y1; y <= area->y2; y++) {
            for(x = area->x1; x <= area->x2; x++) {
                my_set_pixel(x, y, *color_p);  /* Put a pixel to the display.*/
                color_p++;
            }
        }
    
        lv_disp_flush_ready(disp);         /* Indicate you are ready with the flushing*/
    }
        
    ```
    9. Implement and register a function which can read an input device. E.g. for a touch pad:
    ```c
    lv_indev_drv_init(&indev_drv);             /*Descriptor of a input device driver*/
    indev_drv.type = LV_INDEV_TYPE_POINTER;    /*Touch pad is a pointer-like device*/
    indev_drv.read_cb = my_touchpad_read;      /*Set your driver function*/
    lv_indev_drv_register(&indev_drv);         /*Finally register the driver*/
    
    bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
    {
        data->state = my_touchpad_is_pressed() ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; 
        if(data->state == LV_INDEV_STATE_PR) touchpad_get_xy(&data->point.x, &data->point.y);
    
        return false; /*Return `false` because we are not buffering and no more data to read*/
    }
    ```
    10. Call `lv_task_handler()` periodically every few milliseconds in the main `while(1)` loop, in Timer interrupt or in an Operation system task. 
    It will redraw the screen if required, handle input devices etc. 
    
    For more detailed desription visit the [Porting](https://docs.lvgl.io/v7/en/html/porting/index.html) section of the documentation.
    
    ## Learn the basics
    
    In this section you can read the very basics of LVGL. 
    For a more detailed guide check the [Quick overview](https://docs.lvgl.io/v7/en/html/get-started/quick-overview.html#learn-the-basics) in the documentation. 
    
    ### Widgets (Objects)
    
    The graphical elements like Buttons, Labels, Sliders, Charts etc are called objects or widgets in LVGL. Go to [Widgets](https://docs.lvgl.io/v7/en/html/widgets/index) to see the full list of available types.
    
    Every object has a parent object. The child object moves with the parent and if you delete the parent the children will be deleted too. Children can be visible only on their parent.
    
    The *screen* are the "root" parents. To get the current screen call `lv_scr_act()`.
    
    You can create a new object with `lv_<type>_create(parent, obj_to_copy)`. It will return an `lv_obj_t *` variable which should be used as a reference to the object to set its parameters later. 
    The first parameter is the desired *parent*, the second parameters can be an object to copy (`NULL` if unused). 
    For example:
    ```c
    lv_obj_t * slider1 = lv_slider_create(lv_scr_act(), NULL);
    ```
    
    To set some basic attribute `lv_obj_set_<paramters_name>(obj, <value>)` function can be used. For example:
    ```c
    lv_obj_set_x(btn1, 30);
    lv_obj_set_y(btn1, 10);
    lv_obj_set_size(btn1, 200, 50);
    ```
    
    The objects have type specific parameters too which can be set by `lv_<type>_set_<paramters_name>(obj, <value>)` functions. For example:
    ```c
    lv_slider_set_value(slider1, 70, LV_ANIM_ON);
    ```
    
    To see the full API visit the documentation of the object types or the related header file (e.g. `lvgl/src/lv_objx/lv_slider.h`).
    
    
    To create a new screen pass `NULL` as the fisrt paramater of a *create* function:
    ```c
    lv_obj_t * scr2 = lv_obj_create(NULL, NULL);    /*Create a screen*/
    lv_scr_load(scr2);                              /*Load the new screen*/
    ```
    
    ### Styles
    Widgets are created with a default appearance but it can be changed by adding new styles to them. A new style can be created like this:
    ```c
    static lv_style_t style1; /*Should be static, global or dynamically allocated*/
    lv_style_init(&style1);
    lv_style_set_bg_color(&style1, LV_STATE_DEFAULT, LV_COLOR_RED);  /*Default background color*/ 
    lv_style_set_bg_color(&style1, LV_STATE_PRESSED, LV_COLOR_BLUE); /*Pressed background color*/
    ```
    
    The wigedt have *parts* which can be referenced via `LV_<TYPE>_PART_<PART_NAME>`. E.g. `LV_BTN_PART_MAIN` or `LV_SLIDER_PART_KNOB`. See the documentation of the widgets to see the exisitng parts.
    
    To add the style to a button:
    ```c
    lv_obj_add_style(btn1, LV_BTN_PART_MAIN, &style1);
    ```
    
    To remove all styles from a part of an object:
    ```cc
    lv_obj_reset_style_list(obj, LV_OBJ_PART_MAIN);
    ```
    
    Learn more in [Style overview](https://docs.lvgl.io/v7/en/html/overview/style) section.
    
    ### Events
    Events are used to inform the user if something has happened with an object. You can assign a callback to an object which will be called if the object is clicked, released, dragged, being deleted etc. It should look like this: 
    
    ```c
    lv_obj_set_event_cb(btn, btn_event_cb);     /*Assign a callback to the button*/
    
    ...
    
    void btn_event_cb(lv_obj_t * btn, lv_event_t event)
    {
        if(event == LV_EVENT_CLICKED) {
            printf("Clicked\n");
        }
    }
    ```
    
    Learn more about the events in the [Event overview](https://docs.lvgl.io/v7/en/html/overview/event) section. 
    
    
    ## Examples 
    
    ### Button with label
    ```c
    lv_obj_t * btn = lv_btn_create(lv_scr_act(), NULL);     /*Add a button the current screen*/
    lv_obj_set_pos(btn, 10, 10);                            /*Set its position*/
    lv_obj_set_size(btn, 100, 50);                          /*Set its size*/
    lv_obj_set_event_cb(btn, btn_event_cb);                 /*Assign a callback to the button*/
    
    lv_obj_t * label = lv_label_create(btn, NULL);          /*Add a label to the button*/
    lv_label_set_text(label, "Button");                     /*Set the labels text*/
    
    ...
    
    void btn_event_cb(lv_obj_t * btn, lv_event_t event)
    {
        if(event == LV_EVENT_CLICKED) {
            printf("Clicked\n");
        }
    }
    ```
    ![LVGL button with label example](https://docs.lvgl.io/v7/en/misc/simple_button_example.gif)
    
    ### Use LVGL from Micropython
    Learn more about [Micropython](https://docs.lvgl.io/en/html/get-started/micropython).
    ```python
    # Create a Button and a Label
    scr = lv.obj()
    btn = lv.btn(scr)
    btn.align(lv.scr_act(), lv.ALIGN.CENTER, 0, 0)
    label = lv.label(btn)
    label.set_text("Button")
    
    # Load the screen
    lv.scr_load(scr)
    ```
    
    ## Release policy
    LVGL follows the rules of [Semantic versioning](https://semver.org/):
    - Major versions for incompatible API changes. E.g. v5.0.0, v6.0.0
    - Minor version for new but backward-compatible functionalities. E.g. v6.1.0, v6.2.0
    - Patch version for backward-compatible bug fixes. E.g. v6.1.1, v6.1.2
    
    Branches:
    - `master` most recent version, patches are merged directly here. 
    - `dev` merge new features here until they are merged into `master`.
    - `release/vX` there is a branch for every major version to allow adding specific, not forward compatible fixes.
    
    LVGL has a monthly periodic release cycle.
    - **1st Tuesday of the month** 
      - Make a major, minor, or patch release from `master` depending on the new features.
      - After that merge only patches into `master` and add new features into the `dev`.
    - **3rd Tuesday of the month** 
      - Make a patch release from `master`.
      - After that merge the new features from the `dev` to `master` branch. 
      - In the rest of the month merge only patches into `master` and new features into `dev` branch.
      
    ## Contributing
    To ask questions please use the [Forum](https://forum.lvgl.io).
    For development-related things (bug reports, feature suggestions) use [GitHub's Issue tracker](https://github.com/lvgl/lvgl/issues). 
    
    If you are interested in contributing to LVGL you can
    - **Help others** in the [Forum](https://forum.lvgl.io).
    - **Inspire people** by speaking about your project in [My project](https://forum.lvgl.io/c/my-projects) category in the Forum.
    - **Improve and/or translate the documentation.** Go to the [Documentation](https://github.com/lvgl/docs) repository to learn more
    - **Write a blog post** about your experiences. See how to do it in the [Blog](https://github.com/lvgl/blog) repository
    - **Report and/or fix bugs** in [GitHub's issue tracker](https://github.com/lvgl/lvgl/issues)
    - **Help in the developement**. Check the [Open issues](https://github.com/lvgl/lvgl/issues) especially the ones with [Help wanted](https://github.com/lvgl/lvgl/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) label and tell your ideas about a topic or implement a feature.
    
    Before sending Pull requests, please read the following guides:
    - [Contributing guide](https://github.com/lvgl/lvgl/blob/master/docs/CONTRIBUTING.md)
    - [Coding style guide](https://github.com/lvgl/lvgl/blob/master/docs/CODING_STYLE.md)

    ## Add LVGL to your project栏详细介绍了移植过程,部分过程解读:

    步骤3:配置lv_conf.h文件说明
    LV_HOR_RES_MAX LV_HOR_RES_MAX 宏的值,这个是告诉 littleVGL 你所用的液晶屏分辨率是多少,请根据自己手头液晶屏的实际分辨率大小相应设置

    LV_COLOR_DEPTH 颜色深度,最常见的设置就是 1 或者 16 ,1 是用于单色屏,16 是用于彩色屏,这里我设置成1,因为我用的OLED是单色屏

    LV_DPI 的值,默认值为 130(我的库默认是这个),把他设置到100,这个宏是用来调节界面缩放比例的,此值越大,控件分布的就越散,控件自身的间隔也会变大

    LV_MEM_SIZE 的大小,这个就是控制 littleVGL 中所谓的动态数据堆的大小,是用来给控件的创建动态分配空间的,我这里设置为 32KB 的大小

    当要使能某种字体时,找到对应的字体定义,设置为1,例如:#define LV_FONT_MONTSERRAT_12    1

    LV_USE_FILESYSTEM 的值,其默认值为 1,使能文件系统的功能 ,(might be required for images )

    接着可以设置 LV_THEME_LIVE_UPDATE, LV_USE_THEME_TEMPL,LV_USE_THEME_DEFAULT,LV_USE_THEME_ALIEN, LV_USE_THEME_NIGHT, LV_USE_THEME_MONO,
    LV_USE_THEME_MATERIAL, LV_USE_THEME_ZEN, LV_USE_THEME_NEMO 等宏的值为 1,即使能,这些宏都是跟 littleVGL自带的主题相关的,1表示使能对应主题,

    注意,在实际项目中,我们一般最多使能一个,如果我们项目根本就用不到其自带的主题,那么我们应该把这些宏全部禁止,因为这样可以节省 flash ram

    步骤5:littleVGL 提供心跳节拍 的函数:lv_tick_inc参考lv_conf.h的这段代码

    /* 1: use a custom tick source.
     * It removes the need to manually update the tick with `lv_tick_inc`) */
    #define LV_TICK_CUSTOM     1
    #if LV_TICK_CUSTOM == 1
    #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*/

    所以,其实在esp32 arduino中,不需要调用这个函数,但是在比如stm32等看别人是用定时器定时调用的。

    步骤8:配置显示,这里是移植的关键点,就是对应lvgl与OLED的接口,代码参考如下,显示驱动函数,在这里可知道上面定义的OLED像素点清除函数的作用了:

    /* Display flushing  
    1.把指定区域的显示缓冲区内容写入到屏幕上,你可以使用DMA或者其他的硬件加速器在后台去完成这个操作
    2.但是在完成之后,你必须得调用lv_disp_flush_ready()
    3.移植lvgl到对应屏幕上,需要对应lvgl的接口与显示的接口,在这里设置
    4.littleVGL 支持 4 种颜色深度,格式分为为 1 byte per pixel, RGB233, RGB565, ARGB8888,其对应的配置项值分别为 1, 8, 16, 32,在一般的实际项目中,最常用的为 1 和 16,当然如果你
      的处理器性能和资源都很高的话,那么你可以选择 32,占用 4 个字节,他会给你的项目带来更逼真的颜色效果,保证不失真,如果你选择的是 1,那么它只支持 2 种颜色,占用 1 个字节,在液晶
      屏上的表现就是显示与不显示的关系,常用于单色屏,比如 lcd12864,oled 等,当你选择的是 16时,那么他支持 65536 种颜色,占用 2 个字节,显示效果还是很不错的,同时对处理器的要求也不
      是很高,因此 16 成为了我们实际项目中最常用的设置值.Display flushing函数中lv_color_t* color_p变量传递回来的就是显示区第要显示的点的颜色值地址
    */
    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);
      /*刷新显示区每个点的像素值*/
      for (uint16_t y = area->y1; y <= area->y2; y++){
        for (uint16_t x = area->x1; x <= area->x2; x++){
          if(color_p->full != 0)display.setPixel(x, y);//由于我是用的OLED只有黑白,所以配置的2种颜色,当颜色值为1时设置该像素点
          else display.clearPixel(x, y);//由于我是用的OLED只有黑白,所以配置的2种颜色,当颜色值为0时设置清除像素点
          color_p++;
        }
      }
      display.display();//刷新OLED显示
      lv_disp_flush_ready(disp);/* Indicate you are ready with the flushing 最后必须得调用,通知 lvgl 库你已经 flushing 拷贝完成了*/
    }

    步骤9:由于我还没有外部输入,所以这里就没有配置

    lvgl简介:

    littleVGL 可以说是这 2 年才刚开始流行的一个小型开源嵌入式 GUI ,具有界面精美,消耗资源小,可移植度高,响应式布局等特点,全库采用纯 c 语言开发,

    littleVGL 的主要特性如下:
    具有非常丰富的内置控件,buttons, charts, lists, sliders, images
    高级图形效果:动画,反锯齿,透明度,平滑滚动
    支持多种输入设备,touchpad, mouse, keyboard, encoder
    支持多语言的 UTF-8 编码
    支持多个和多种显示设备,例如同步显示在多个彩色屏或单色屏上
    完全自定制的图形元素
    硬件独立于任何微控制器或显示器
    可以缩小到最小内存 (64 kB Flash, 16 kB RAM)
    支持操作系统、外部储存和 GPU(非必须)
    仅仅单个帧缓冲设备就可以呈现高级视觉特效
    使用 C 编写以获得最大兼容性(兼容 C++)
    支持 PC 模拟器
    为加速 GUI 设计,提供教程,案例和主题,支持响应式布局
    提供了在线和离线文档
    基于自由和开源的 MIT 协议

    littleVGL 的要求如下:
    1632 64 位的单片机(微控制器)或处理器
    微处理器的主频最好高于 16MHZ
    Flash/ROM:如果只用 littleVGL 核心组件的话,则至少需要 64kB 的容量,如果想完整使用的
    ,最好保证 180kB 以上的容量
    RAM:
        o 静态 RAM: 大约 8 16 kB,这取决于你所用的组件功能和 objects 控件对象类型
        o : 至少为 2Kb,一般推荐值为 4kB

        o 动态数据(): 至少 4kB,如果你用到了多个或多种控件的话,那么最好设置为 16kB 以上,这个是可以通过 lv_conf.h 配置文件中的 LV_MEM_SIZE 宏来定义的
        o 显示缓冲区: 至少要比水平分辨率像素要大,一般推介值为 10 倍的水平分辨率素”,取个例子,假如我们屏幕的水平分辨率为480个像素,采用16位的颜色深度进行显
    ,即一个像素占 2 个字节,那么推介的显示缓冲区大小为 10*480*2=9600 个字节
    C99 或更新的编译器,如果是用 keil 开发的话,一定得勾选”c99”模式,否则编译会报错的
    基本的 c(或者 c++)语言知识,:指针,结构体,回调函数

    3,我的程序说明

    cpu:dsp32,IDE:arduino

    程序功能

    1,esp32串口调用

    2,OLED显示

    3,esp32管脚输入输出使用

    4,lvgl窗口建立,在OLED显示

    lvgl使用功能:

    建立了三个屏幕,按键控制屏幕切换

    在屏幕上添加控件:label,bar,line,img等

    label,bar,line,style简单使用,显示字体修改

    手动发送事件,触发部件响应其对应的回调函数

    .c文件存储图片数据,窗口显示,lvgl官方的在线图片转.c文件工具链接:https://lvgl.io/tools/imageconverter

    ps:我的程序源码如下,注释都挺清楚的,LVGL的学习可以参考正点原子手把手教你学littleVGL【轻量级开源GUI】,正点原子资料下载网站:http://www.openedv.com/docs/index.html

    主程序:

    #include <lvgl.h>
    #include "SSD1306Wire.h" // alias for `#include "SSD1306Wire.h"`
    #include "caiya_gui.h"
    
    SSD1306Wire  display(0x3c, 4, 15);//实例化OLED显示,设置管脚,该方法输入参数:uint8_t _address, uint8_t _sda, uint8_t _scl
    
    /*Create a display buffer for LVGL*/
    static lv_disp_buf_t disp_buf;
    static lv_color_t buf[LV_HOR_RES_MAX * 10];/*Declare a buffer for 10 lines*/
    
    USER_DATA user_data = {{"xixi"},0};//初始化一下用于回调函数传输数据的结构体
    
    /* Display flushing  
    1.把指定区域的显示缓冲区内容写入到屏幕上,你可以使用DMA或者其他的硬件加速器在后台去完成这个操作
    2.但是在完成之后,你必须得调用lv_disp_flush_ready()
    3.移植lvgl到对应屏幕上,需要对应lvgl的接口与显示的接口,在这里设置
    4.littleVGL 支持 4 种颜色深度,格式分为为 1 byte per pixel, RGB233, RGB565, ARGB8888,其对应的配置项值分别为 1, 8, 16, 32,在一般的实际项目中,最常用的为 1 和 16,当然如果你
      的处理器性能和资源都很高的话,那么你可以选择 32,占用 4 个字节,他会给你的项目带来更逼真的颜色效果,保证不失真,如果你选择的是 1,那么它只支持 2 种颜色,占用 1 个字节,在液晶
      屏上的表现就是显示与不显示的关系,常用于单色屏,比如 lcd12864,oled 等,当你选择的是 16时,那么他支持 65536 种颜色,占用 2 个字节,显示效果还是很不错的,同时对处理器的要求也不
      是很高,因此 16 成为了我们实际项目中最常用的设置值.Display flushing函数中lv_color_t* color_p变量传递回来的就是显示区第要显示的点的颜色值地址
    */
    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);
      /*刷新显示区每个点的像素值*/
      for (uint16_t y = area->y1; y <= area->y2; y++){
        for (uint16_t x = area->x1; x <= area->x2; x++){
          if(color_p->full != 0)display.setPixel(x, y);//由于我是用的OLED只有黑白,所以配置的2种颜色,当颜色值为1时设置该像素点
          else display.clearPixel(x, y);//由于我是用的OLED只有黑白,所以配置的2种颜色,当颜色值为0时设置清除像素点
          color_p++;
        }
      }
      display.display();//刷新OLED显示
      lv_disp_flush_ready(disp);/* Indicate you are ready with the flushing 最后必须得调用,通知 lvgl 库你已经 flushing 拷贝完成了*/
    }
    
    //显示器接口初始化
    void lv_port_disp_init(void)
    {
      lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);/*Initialize the display buffer*/
      /*Implement and register a function which can copy a pixel array to an area of your display:*/
      lv_disp_drv_t disp_drv;/*Descriptor of a display driver*/
      lv_disp_drv_init(&disp_drv);/*Basic initialization*/
      /*设置屏幕的显示大小,我这里是为了支持多个屏幕,采用动态获取的方式如果你是用于实际项目的话,可以不用设置,
      那么其默认值就是 lv_conf.h 中LV_HOR_RES_MAX 和 LV_VER_RES_MAX 宏定义的值*/
      disp_drv.hor_res = 128;
      disp_drv.ver_res = 64;
      disp_drv.flush_cb = my_disp_flush;/*Set your driver function*/
      disp_drv.buffer = &disp_buf;/*Assign the buffer to the display*/
      lv_disp_drv_register(&disp_drv);/*Finally register the driver*/
    }
    
    void setup()
    {
      Serial.begin(115200); /* prepare for possible serial debug */
      pinMode(2,OUTPUT);//设置管脚2位输出,连接的LED
      digitalWrite(2,1);//管脚2输出1
      pinMode(0,INPUT_PULLUP);//管脚0位输入,连接的按键
      /*想要使用 littleVGL 的任务管理系统,就必须得调用 lv_task_core_init 进行初始化一下,但是好处在于不需要我们自己去手动调用了,littleVGL 内部已经帮我们完成了初始化调用
       * 在 lv_init 函数中可以看到 lv_task_core_init 函数的调用,而我们又在 main 函数中调用了lv_init 函数,所以我们完全可以不用去理会 lv_task_core_init 这个 API 接口*/
      lv_init();//lvgl系统初始化
      display.init();//oled驱动初始化
      lv_port_disp_init();//显示器接口初始化
      set_caiya_gui();//GUI初始化
      lv_scr_load_anim(scr1, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 500, 5000, false); // 加载屏幕scr1,动画效果为LV_SCR_LOAD_ANIM_FADE_ON,切换时间为500ms,延迟5000ms后从第一屏开始切换,切换完成后不删除原来的屏幕
    }
    int flag = 0;
    void loop()
    {
      /*periodically every few milliseconds in the main `while(1)` loop, in Timer interrupt or in an Operation system task. It will redraw the screen if required, handle input devices etc.*/
      lv_task_handler(); /* let the GUI do its work */
      delay(5);
      if(digitalRead(0)==0)
      {
        while(digitalRead(0)==0);
        digitalWrite(2,!digitalRead(2));
        flag++;
        if(flag==1){
          lv_scr_load_anim(scr2, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 500, 0, false);
        }
        else if(flag==2){
          lv_scr_load_anim(scr1, LV_SCR_LOAD_ANIM_MOVE_RIGHT, 500, 0, false);
          flag=0;
        }
        //手动发送事件
        //方式 1:发送用户自定义事件,同时携带用户自定义数据
        user_data.age=(unsigned char)flag;
        Serial.println(user_data.age);
        /*手动发送事件进行触发,同时可以携带用户自定义的数据
        函数参数:lv_obj_t * obj, lv_event_t event, const void * data*/
        lv_event_send(label2,USER_EVENT_1,&user_data);
         
      }
    
      
    }

    lvgl GUI窗口搭建的.c,.h源码:

    #ifndef CAIYA_GUI_H
    #define CAIYA_GUI_H
    
    #ifdef __cplusplus
    extern "C" {  //extern "C"表示编译生成的内部符号名使用C约定。这样在c++文件中也可以调用对应c函数
    #endif
    
    #include "lvgl.h"
    
    
    /*    1.在 littleVGL 中任何对象都可以注册事件,这是在新版本中才加入的特性,分为通用事件和专用事件,总共支持 20 种事件类型,这是一个总和哈,并不是指每一个对象都具有 20 种事件
        类型,事件可以是由 littleVGL 库自身触发的,也可以是由外部物理操作触发的,比如触摸,点击等等,当然了,我们也可以通过调用 lv_event_send 接口来手动发送事件进行触发,同时可以携
        带用户自定义的数据.
        2.这里需要注意 event 参数,系统是自带了 20 种事件类型,其对应的值是从 0 到 19,除了给event 参数传系统自带的事件外,其实我们还可以传用户自定义的事件的,范围为:[20,255]*/
    #define USER_EVENT_START 20
    #define USER_EVENT_1 (USER_EVENT_START+1) //用户自定义事件 1
    
    //构建一个用户自定义数据结构体,当然了,如果你的用户数据简单,可以不用结构体
    typedef struct{
          char name[20];
          unsigned char age;
    }USER_DATA;
    
    
    
        //extern lv_img_dsc_t screen_buffer;
        extern lv_obj_t* scr1;
        extern lv_obj_t* scr2;
        extern lv_obj_t* label2;
        
    
    
        void set_caiya_gui(void);
        static void btn_event_cb(lv_obj_t * obj,lv_event_t event);
    
    
    #ifdef __cplusplus
    } /* extern "C" */
    #endif
    
    #endif  
    /*********************
     *      INCLUDES
     *********************/
    #include "caiya_gui.h"
    
    
    /*Use this macro to declare an image in a c file
        #define LV_IMG_DECLARE(var_name) extern const lv_img_dsc_t var_name;
        建议:声明的图片名字为图片数据文件的文件名,然后littleVGL 用lv_img_dsc_t 结构体对图片数据进行一次封装的变量名也要使用文件名*/
    LV_IMG_DECLARE(myimage1);
    
    lv_obj_t* scr1;
    lv_obj_t* scr2;
    
    lv_obj_t* label2;
    
    static lv_point_t line_points[] = { {5, 25}, {30, 50}, {50, 30}, {80, 80}, {100, 30} };
    
    
    lv_obj_t * line;
    
    void set_caiya_gui(void)
    {
        /*设置默认屏幕*/
        //创建bar
        /*Create style*/
        static lv_style_t style;
        lv_style_init(&style);//初始化样式
        lv_style_set_border_width(&style, LV_STATE_DEFAULT, 4);//设置样式的边框宽度
        lv_style_set_bg_color(&style, LV_STATE_DEFAULT, LV_COLOR_BLACK);//设置样式的背景颜色
        lv_obj_t* bar = lv_bar_create(lv_scr_act(), NULL);//在默认屏上创建bar对象 lv_scr_act()表示当前屏幕
        /*apply the new style*/
        lv_obj_add_style(bar, LV_LABEL_PART_MAIN, &style);
        lv_obj_set_size(bar, 140, 20);//设置bar尺寸
        lv_obj_align(bar, NULL, LV_ALIGN_CENTER, 0, 0);//校准bar在屏幕中的位置 居中
        lv_bar_set_anim_time(bar, 2000);//设置bar的动画时间
        lv_bar_set_value(bar, 100, LV_ANIM_ON);//设置值
        //创建label
        static lv_style_t style1;
        lv_style_init(&style1);
        lv_style_set_border_width(&style1, LV_STATE_DEFAULT, 2);
        lv_style_set_text_font(&style1,LV_STATE_DEFAULT,&lv_font_montserrat_12);//设置字体大小  需要去lv_conf.H文件中设置对应字体定义为1 例如#define LV_FONT_MONTSERRAT_12    1
        lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
        lv_obj_add_style(label, LV_LABEL_PART_MAIN, &style);
        /*设置label文本为长文本模式
            void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode);
            参数:
            label: 标签对象
            long_mode: 长文本模式
            LV_LABEL_LONG_EXPAND, 自动扩展对象的大小来包裹文本内容
            保持对象的宽度不变,当文本内容的宽度超过对象的宽度时会
            自动换行,然后同时自动扩展对象的高度来包裹文本内容的高度
            LV_LABEL_LONG_BREAK,
            保持对象的大小不变,当文本内容太长显示不下时,
            会在文本末尾显示...三个点的省略号
            LV_LABEL_LONG_DOT,
            保持对象的大小不变,当文本内容太长显示不下时,会自动循环向前向后滚动文本
            LV_LABEL_LONG_SROLL,
            保持对象的大小不变,当文本内容太长显示不下时,会自动循环环形滚动文本
            LV_LABEL_LONG_SROLL_CIRC,
            LV_LABEL_LONG_CROP, 保持对象大小不变,超过的文本内容将会被剪切掉*/
        lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL);
        /*设置文本对齐方式
            void lv_label_set_align(lv_obj_t * label, lv_label_align_t align);
            参数:
            label: 标签对象
            align: 水平方向上的文本对齐方式
            LV_LABEL_ALIGN_LEFT, //文本左对齐
            LV_LABEL_ALIGN_CENTER, //文本居中对齐
            LV_LABEL_ALIGN_RIGHT,//文本右对齐*/
        lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
        lv_obj_set_pos(label, 10, 0);//设置对象位置
        lv_obj_set_size(label, 108, 20);
        /*设置动态文本(字符串形式)
            void lv_label_set_text(lv_obj_t * label, const char * text);
            参数:
            label: 标签对象
            text: 新的文本内容,文本内容要是’\0’空字符结尾,如果传 NULL 的话,那么代表刷新当前文本内容*/
       lv_label_set_text(label, "let us begining......");
        
        /*设置默认屏幕
            我们再来了解另外一个核心概念 Screen 屏幕对象,屏幕对象是一个特殊的对象,因为他自己没有父对象,所以它以这样的方式来创建:
            lv_obj_t * screen = lv_obj_create(NULL, NULL);
            默认情况下,littleVGL 会为显示器创建一个 lv_obj 类型的基础对象来作为它的屏幕,即最
            顶层的父类,可以通过 lv_scr_act()接口来获取当前活跃的屏幕对象*/
            
        /*创建屏幕1*/
        scr1 = lv_obj_create(NULL, NULL);  // 创建新屏幕但未加载到显示
        /*lv_img 就是一个图片控件,它就是根据你传入的图片源来显示你想要的图片,littleVGL 为了提供最大的灵活性,它支持如下三种图片源方式:
            1) 内部 C 数组,用 lv_img_dsc_t 结构体来进行描述
            2) 外部存储文件,比如 SD 卡或者 U 盘上的图片文件
            3) LV_SYMBOL_XXX 形式的图标字体或者文本,此时 lv_img 图片就相当于一个 lv_label 标签控件
            如果你确定好图片源之后,就可以通过 lv_img_set_src(img, src)接口来显示此图片,此接口内部会自动判断出 src 是属于哪一种图片源方式,然后选择相应的解析程序把图片给显示出来.*/
        lv_obj_t* img1 = lv_img_create(scr1, NULL);
        lv_img_set_src(img1, &myimage1);
        lv_obj_set_pos(scr1, 0, 0);
        lv_obj_set_size(scr1, 128, 64);
        
        /*创建屏幕2*/
        scr2 = lv_obj_create(NULL, NULL);   // 创建新屏幕但未加载到显示
        label2 = lv_label_create(scr2, NULL);         // 创建label
        lv_label_set_long_mode(label2, LV_LABEL_LONG_SROLL);
        lv_label_set_align(label2, LV_LABEL_ALIGN_CENTER);
        lv_obj_set_pos(label2, 44, 0);
        lv_obj_set_size(label2, 40, 20);
        lv_label_set_text(label2, "TWO");
        static lv_style_t style_line;
        lv_style_init(&style_line);
        lv_style_set_line_width(&style_line, LV_STATE_DEFAULT, 8);
        lv_style_set_line_rounded(&style_line, LV_STATE_DEFAULT, true);
        line = lv_line_create(scr2, NULL);
        lv_line_set_points(line, line_points, 5);     /*Set the points*/
        lv_obj_add_style(line, LV_LINE_PART_MAIN, &style_line);     /*Set the points*/
        lv_obj_align(line, NULL, LV_ALIGN_CENTER, 0, 0);
       /*事件回调函数
        void lv_obj_set_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb);
        参数:
        obj: 对象句柄
        event_cb: 事件回调函数*/
       lv_obj_set_event_cb(label2,btn_event_cb);
    }
    
    
    
    
    
    //事件回调函数 这个函数的自己写的
    static void btn_event_cb(lv_obj_t * obj,lv_event_t event)
    {
        static unsigned char i=0;
     if(event==USER_EVENT_1)
       {
       //用户自定义事件 1
       //获取用户自定义数据
       USER_DATA* data = (USER_DATA*)lv_event_get_data();
       if(data->age==1){
           i++;
           if(i>10)i=0;
           if(i%2)lv_line_set_points(line, line_points, 3);     /*Set the points*/
            else lv_line_set_points(line, line_points, 5);     /*Set the points*/
       } 
       if(data->age==1) lv_label_set_text_fmt(label2, "back successful!-%d", i);  // lv_label_set_text_fmt()它就是pintf("%d user", user_num)实现
       }
    }

    图片数据.c源码:

    //#include "E:\DC BREAKER\ESP32\Project\libraries\lvgl\src\lv_examples\lv_examples.h"
    #include "lvgl.h"
    
    /* #define LV_ATTRIBUTE_MEM_ALIGN说明
        With size optimization (-Os) the compiler might not align data to
        * 4 or 8 byte boundary. This alignment will be explicitly applied where needed.
        * E.g. __attribute__((aligned(4))) 
     */
    #ifndef LV_ATTRIBUTE_MEM_ALIGN
    #define LV_ATTRIBUTE_MEM_ALIGN
    #endif
    #ifndef LV_ATTRIBUTE_IMG_2
    #define LV_ATTRIBUTE_IMG_2
    #endif
    const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_2 uint8_t my_map[] = {
      0xff, 0xff, 0xff, 0xff,     /*Color of index 0*/
      0x00, 0x00, 0x00, 0xff,     /*Color of index 1*/
    
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x58, 0x0c, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x1a, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x10, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x81, 0x34, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0xa5, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x48, 0xa4, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x4a, 0xfe, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x40, 0x47, 0xe0, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x7f, 0xff, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x02, 0x60, 0x00, 0xff, 0xfa, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xff, 0xe0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x01, 0xfc, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x03, 0x18, 0x03, 0xff, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x01, 0xfe, 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdf, 0xff, 0xf4, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x7f, 0xff, 0xfc, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x1f, 0xff, 0xfc, 0x1f, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x3f, 0xff, 0xfe, 0x18, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xbf, 0xff, 0xfe, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x01, 0x00, 0x07, 0xff, 0xff, 0xfe, 0x0f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0xff, 0xff, 0xfe, 0x07, 0xf0, 0x06, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0xfc, 0x38, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xfd, 0x03, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x80, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x07, 0xe1, 0xff, 0xf8, 0xff, 0xff, 0xbf, 0x20, 0x7f, 0xff, 0x0c, 0xc0, 0x00, 0x00, 
      0x00, 0x00, 0x07, 0xcf, 0xff, 0xc0, 0x7f, 0xff, 0x0f, 0xff, 0xc7, 0xff, 0xef, 0xc0, 0x00, 0x00, 
      0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfe, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    };
    
    /*littleVGL 会用lv_img_dsc_t 结构体对图片数据进行一次封装*/
    
    const lv_img_dsc_t myimage1 = {
      .header.cf = LV_IMG_CF_INDEXED_1BIT,//图片的转换格式
      .header.always_zero = 0,
      .header.reserved = 0,
      .header.w = 128,//图片的宽度
      .header.h = 64,//图片的高度
      .data_size = 1033,//C 数组的大小,单位为字节
      .data = my_map,//C 数组,也就是图片的核心像素数据
    };

    OLED显示图片:

     

  • 相关阅读:
    每日日报2020.12.1
    每日日报2020.11.30
    981. Time Based Key-Value Store
    1146. Snapshot Array
    565. Array Nesting
    79. Word Search
    43. Multiply Strings
    Largest value of the expression
    1014. Best Sightseeing Pair
    562. Longest Line of Consecutive One in Matrix
  • 原文地址:https://www.cnblogs.com/caiya/p/15978839.html
Copyright © 2020-2023  润新知