【FireBeetle 2 ESP32 C6开发板】5、适配lvgl 9.1-- lv_port完成lvgl设备适配文件
<div class='showpostmsg'>### 前言lvgl已经出到9.x版本了,github上的lv_port_esp32还是7.x版本,由于我自己有Linux和esp32两种设备的开发需求,esp32的RAM和Flash也不算小,
我打算直接使用9.1版本的lvgl,然后使用lvgl_esp32_drivers仓库,仓库地址是https://github.com/lvgl/lvgl_esp32_drivers.git
#### 创建LVGL适配文件
我们可以使用lvgl官方的示范文件,进行修改,就可以正确适配lvgl,并且完成屏幕和触摸屏的驱动启动。
官方示范文件的就是lvgl/examples/porting/lv_port_disp_template.c,以及lvgl/examples/porting/lv_port_indev_template.c
根据这个文件,我们创建一个lv_port.c文件,并输入以下内容。
```c
/**
* @File lv_port.c
*
*/
#include "esp_log.h"
#include <stdint.h>
#define TAG "lvgl"
/*Copy this file as "lv_port_disp.c" and set this value to "1" to enable
* content*/
#if 1
/*********************
* INCLUDES
*********************/
#include "driver/gpio.h"
#include "lv_port.h"
#include <stdbool.h>
/*********************
* DEFINES
*********************/
#ifndef MY_DISP_HOR_RES
#define MY_DISP_HOR_RES 280
#endif
#ifndef MY_DISP_VER_RES
#define MY_DISP_VER_RES 240
#endif
#define TP_RST_PIN 14
/**********************
* TYPEDEFS
**********************/
/**********************
*STATIC PROTOTYPES
**********************/
static void disp_init(void);
static void disp_flush(lv_display_t *disp, const lv_area_t *area,
lv_color_t *px_map);
static void touchpad_init(void);
static void touchpad_read(lv_indev_t *indev, lv_indev_data_t *data);
static bool touchpad_is_pressed(void);
static void touchpad_get_xy(int32_t *x, int32_t *y);
/**********************
*STATIC VARIABLES
**********************/
lv_display_t *disp;
lv_indev_t *indev_touchpad;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_port_disp_init(void) {
/*-------------------------
* Initialize your display
* -----------------------*/
disp_init();
/*------------------------------------
* Create a display and set a flush_cb
* -----------------------------------*/
disp = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);
lv_display_set_flush_cb(disp, disp_flush);
/* Example 2
* Two buffers for partial rendering
* In flush_cb DMA or similar hardware should be used to update the display in
* the background.*/
static lv_color_t buf_2_1;
static lv_color_t buf_2_2;
lv_display_set_buffers(disp, buf_2_1, buf_2_2, sizeof(buf_2_1),
LV_DISPLAY_RENDER_MODE_PARTIAL);
}
/**********************
* STATIC FUNCTIONS
**********************/
extern void lvgl_driver_init(void);
/*Initialize your display and the required peripherals.*/
static void disp_init(void) { /*You code here*/
lvgl_driver_init();
}
volatile bool disp_flush_enabled = true;
/* Enable updating the screen (the flushing process) when disp_flush() is called
* by LVGL
*/
void disp_enable_update(void) { disp_flush_enabled = true; }
/* Disable updating the screen (the flushing process) when disp_flush() is
* called by LVGL
*/
void disp_disable_update(void) { disp_flush_enabled = false; }
/*Flush the content of the internal buffer the specific area on the display.
*`px_map` contains the rendered image as raw pixel map and it should be copied
*to `area` on the display. You can use DMA or any hardware acceleration to do
*this operation in the background but 'lv_display_flush_ready()' has to be
*called when it's finished.*/
extern void disp_driver_flush(lv_display_t *drv, const lv_area_t *area,
lv_color_t *color_map);
static void disp_flush(lv_display_t *disp_drv, const lv_area_t *area,
lv_color_t *px_map) {
if (disp_flush_enabled) {
/*The most simple case (but also the slowest) to put all pixels to the
* screen one-by-one*/
lv_draw_sw_rgb565_swap(px_map, lv_area_get_size(area));
disp_driver_flush(disp_drv, area, px_map);
}
/*IMPORTANT!!!
*Inform the graphics library that you are ready with the flushing*/
lv_display_flush_ready(disp_drv);
}
void lv_port_indev_init(void) {
/*------------------
* Touchpad
* -----------------*/
/*Initialize your touchpad if you have*/
touchpad_init();
/*Register a touchpad input device*/
indev_touchpad = lv_indev_create();
lv_indev_set_type(indev_touchpad, LV_INDEV_TYPE_POINTER);
lv_indev_set_read_cb(indev_touchpad, touchpad_read);
}
/**********************
* STATIC FUNCTIONS
**********************/
/*------------------
* Touchpad
* -----------------*/
/*Initialize your touchpad*/
static void touchpad_init(void) {
}
extern bool touch_driver_read(lv_indev_t *indev_drv, lv_indev_data_t *data);
/*Will be called by the library to read the touchpad*/
static void touchpad_read(lv_indev_t *indev_drv, lv_indev_data_t *data) {
/*Save the pressed coordinates and the state*/
// if (!gpio_get_level(TP_RST_PIN)) {
touch_driver_read(indev_drv, data);
//}
}
#else /*Enable this file at the top*/
/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif
```
上面这个文件,一是将lvgl刷新屏幕的函数绑定了前面移植的lv_esp32_drivers屏幕刷新函数,二是将lvgl输入设备绑定到触摸屏,并且绑定触摸屏的读取函数。然后我们只需要在main函数里,调用初始化屏幕和触摸屏初始化函数,就可以了。
lv_port.h函数就很简单了,照抄过来就行了。
```c
/**
* @file lv_port_lcd_stm32_template.h
*
*/
/*Copy this file as "lv_port_disp.h" and set this value to "1" to enable content*/
#if 1
#ifndef LV_PORT_LCD_STM32_TEMPL_H
#define LV_PORT_LCD_STM32_TEMPL_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/* Initialize low level display driver */
void lv_port_disp_init(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PORT_LCD_STM32_TEMPL_H*/
#endif /*Disable/Enable content*/
```
#### 修正其他的错误
错误1、不知道为什么明明I2C相关头文件里是有I2C_NUM_0的定义,但是运行时报错i2c设备读取错误,在这个文件里直接加上相关定义,I2C触屏就可以正常工作了。
错误2、源码里初始化SPI设备时,DMA通道配置的参数是不正确的,运行时会报错SPI设备初始化错误,需要指定自动选取DMA通道配置选项。
搞定这两个,屏幕和触摸屏就完全可以正常使用啦。</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页:
[1]