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

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:由于我还没有外部输入,所以这里就没有配置

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显示图片:

 

 

 

标签:LV,显示,obj,0x00,lv,0xff,屏幕,lvgl
来源: https://www.cnblogs.com/caiya/p/15978839.html