目录
概述
1 系统软硬件
1.1 软件版本信息
1.2 ST7796-LCD
1.3 MCU IO与LCD PIN对应关系
2 认识LVGL
2.1 LVGL官网
2.2 下载V8.4.0
3 移植LVGL
3.1 硬件驱动实现
3.2 添加LVGL库文件
3.3 移植和硬件相关的代码
3.3.1 驱动接口相关文件介绍
3.3.2 重新接口函数
3.4 配置.h文件
3.5 Keil中配置源代码路径
4 文件架构编译配置
4.1 项目文件架构
4.2 编译配置
5 测试
5.1 测试代码实现
5.2 测试案例
测试视频:
N32G45XVL-STB之移植LVGL(8.4.0)
概述
本文主要介绍在N32G45XVL-STB移植lvgl-8.4.0的详细步骤,包括加载文件的方法,Keil中加载文件目录和路径,修改和LCD驱动层相关的接口,keil中配置编译参数,笔者使用LVGL提供的vgl-8.4.0\demos\stress案例,验证移植的代码是否可以正常运行。
1 系统软硬件
1.1 软件版本信息
软硬件信息 | 版本信息 |
---|---|
MCU类型 | N32G457VEL7 |
Keil | MDK ARM 5.38 |
调试工具:DAP | CMSIS-DAP |
1.2 ST7796-LCD
LCD的PIN引脚功能介绍
序号 | 模块引脚 | 引脚说明 |
1 | VCC | 屏电源正 |
2 | GND | 屏电源地 |
3 | LCD_CS | 液晶屏片选控制信号,低电平有效 |
4 | LCD_RST | 液晶屏复位控制信号,低电平复位 |
5 | LCD_RS | 液晶屏命令/数据选择控制信号 高电平:数据,低电平:命令 |
6 | SDI(MOSI) | SPI总线写数据信号(SD卡和液晶屏共用) |
7 | SCK | SPI总线时钟信号(SD卡和液晶屏共用) |
8 | LED | 液晶屏背光控制信号(如需要控制,请接引脚,如不需要控制,可以不接) |
9 | SDO(MISO) | SPI总线读数据信号(SD卡和液晶屏共用) |
10 | CTP_SCL | 电容触摸屏IIC总线时钟信号(无触摸屏的模块不需连接) |
11 | CTP_RST | 电容触摸屏复位控制信号,低电平复位(无触摸屏的模块不需连接) |
12 | CTP_SDA | 电容触摸屏IIC总线数据信号(无触摸屏的模块不需连接) |
13 | CTP_INT | 电容触摸屏IIC总线触摸中断信号,产生触摸时,输入低电平到主控(无触摸屏的模块不需连接) |
14 | SD_CS | SD卡片选控制信号,低电平有效(不使用SD卡功能,可不接) |
实体LCD Port对应关系如下图所示
1.3 MCU IO与LCD PIN对应关系
N32G457VEL7 PIN引脚 | LCD PIN引脚 |
---|---|
PA.07 | MOSI |
PA.06 | MISO |
PA.05 | SCK |
PD.04 | CS |
PD.05 | RST |
PD.06 | RS |
2 认识LVGL
2.1 LVGL官网
LVGL是最流行的免费和开源嵌入式图形库,可为任何MCU, MPU和显示类型创建漂亮的UI。基于这个特点,其可以在一般的MCU上都能运行的,本文选取STM32F407芯片作为主控MCU,实现该UI库的移植。
官方网址:LVGL — Light and Versatile Embedded Graphics Library
https://lvgl.io/
登录网址后,可以看见如下页面,目前最新版本已经升级到 LVGL v8.4 and v9.1 are released!:
2.2 下载V8.4.0
软件下载链接如下:
https://github.com/lvgl/lvgl/releases/tag/v8.4.0
下载完成代码后,解压代码,其文件结构如下:
文件夹examples: 应用实例代码,目录
文件夹src: lvgl的源代码目录
头文件 lvgl.h: lvgl源代码引用文件
头文件lv_conf_template.h: lvgl编译项目配置文件
3 移植LVGL
3.1 硬件驱动实现
在移植LVGL库之前,必须保证LCD驱动已经触摸屏的相关驱动程序已经实现,其实现案例,参考笔者文章:
N32G45XVL-STB之SPI接口驱动LCD-CSDN博客
N32G45XVL-STB之移植FT6336触摸屏芯片驱动-CSDN博客
3.2 添加LVGL库文件
1)lvgl-8.4.0\src\core
添加该目录下的所有.c文件到工程目录中,该目录下的文件包括:
2) lvgl-8.4.0\src\draw
该目录下的文件包括两部分,文件夹中的和绘图相关,文件一级目录的通用.c文件
2.1) 添加一级目录下的文件
添加如下文件到项目中
2.2)二级目录下的文件
这两个文件夹下的.c文件必须加载到项目中
3)lvgl-8.4.0\src\extra
添加如下一级目录和二级目录下所有的.c文件至项目
4) lvgl-8.4.0\src\font
添加如下所有.c文件至项目
5)lvgl-8.4.0\src\hal
添加如下所有.c文件至项目
6)lvgl-8.4.0\src\misc
添加如下所有.c文件至项目
7)lvgl-8.4.0\src\widgets
添加如下所有.c文件至项目
3.3 移植和硬件相关的代码
3.3.1 驱动接口相关文件介绍
在\lvgl-8.4.0\examples\porting目录有3个.c文件
1)LCD显示相关接口函数库: lv_port_disp_template.c
2) 触摸屏/按键相关函数库: lv_port_indev_template.c
3)文件操作行管函数库: lv_port_fs_template.c
3.3.2 重新接口函数
1)重写lv_port_disp_template.c
将 lv_port_disp_template.c 添加到项目,重写干文件中的代码,具体如下:
/**
* @file lv_port_disp_templ.c
*
*/
/* Includes ------------------------------------------------------------------*/
#include "lv_port_disp_template.h"
#include "lvgl.h"
#include "lcd_drv.h"
/* Private includes ----------------------------------------------------------*/
#define MY_DISP_HOR_RES LCD_H
#define MY_DISP_VER_RES LCD_W
/* Private function prototypes -----------------------------------------------*/
static void disp_init(void);
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
/* Private user code ---------------------------------------------------------*/
static void lcd_draw_fast_rgb_color(int16_t sx, int16_t sy,
int16_t ex, int16_t ey,
uint16_t *color)
{
LCD_drawfast_RGB_color(sx, sy, ex, ey, color);
}
static void disp_init(void)
{
/*You code here*/
LCD_Init();
//LCD_direction(2);
LCD_direction(1);
LCD_Clear(WHITE);
}
void lv_port_disp_init(void)
{
static lv_disp_drv_t disp_drv;
static lv_disp_draw_buf_t draw_buf_dsc_1;
static lv_color_t buf_1[MY_DISP_VER_RES * 8];
disp_init();
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_VER_RES * 8);
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = lcddev.width;
disp_drv.ver_res = lcddev.height;
disp_drv.flush_cb = disp_flush;
disp_drv.draw_buf = &draw_buf_dsc_1;
lv_disp_drv_register(&disp_drv);
}
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
lcd_draw_fast_rgb_color(area->x1, area->y1, area->x2, area->y2, (uint16_t *)color_p);
lv_disp_flush_ready(disp_drv);
}
/* END of this file */
2)重写lv_port_indev_template.c
将 lv_port_indev_template.c 添加到项目,重写干文件中的代码,具体如下:
/**
* @file lv_port_indev_templ.c
*
*/
/*Copy this file as "lv_port_indev.c" and set this value to "1" to enable content*/
/*********************
* INCLUDES
*********************/
#include "lv_port_indev_template.h"
#include "lvgl.h"
#include "usr_touch.h"
/* 触摸屏 */
static void touchpad_init(void);
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static bool touchpad_is_pressed(void);
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y);
lv_indev_t * indev_touchpad; // 触摸屏
stru_pos st_Pos;
/**
* @brief 初始化并注册输入设备
* @param 无
* @retval 无
*/
void lv_port_indev_init(void)
{
static lv_indev_drv_t indev_drv;
/*------------------
* 触摸屏
* -----------------*/
/* 初始化触摸屏(如果有) */
touchpad_init();
/* 注册触摸屏输入设备 */
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = touchpad_read;
indev_touchpad = lv_indev_drv_register(&indev_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/*------------------
* 触摸屏
* -----------------*/
/**
* @brief 初始化触摸屏
* @param 无
* @retval 无
*/
static void touchpad_init(void)
{
usr_touchInit();
}
/**
* @brief 图形库的触摸屏读取回调函数
* @param indev_drv : 触摸屏设备
* @arg data : 输入设备数据结构体
* @retval 无
*/
static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
static lv_coord_t last_x = 0;
static lv_coord_t last_y = 0;
/* 保存按下的坐标和状态 */
if(touchpad_is_pressed())
{
touchpad_get_xy(&last_x, &last_y);
data->state = LV_INDEV_STATE_PR;
}
else
{
data->state = LV_INDEV_STATE_REL;
}
/* 设置最后按下的坐标 */
data->point.x = last_x;
data->point.y = last_y;
}
/**
* @brief 获取触摸屏设备的状态
* @param 无
* @retval 返回触摸屏设备是否被按下
*/
static bool touchpad_is_pressed(void)
{
usr_ScanTouchProcess( &st_Pos );
if( st_Pos.status_bit.tpDown ){
st_Pos.status_bit.tpDown = 0;
return true;
}
return false;
}
/**
* @brief 在触摸屏被按下的时候读取 x、y 坐标
* @param x : x坐标的指针
* @arg y : y坐标的指针
* @retval 无
*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
/*Your code comes here*/
(*x) = st_Pos.xpox[0];
(*y) = st_Pos.ypox[0];
}
/* End of this file */
3.4 配置.h文件
在lvgl-8.4.0根目录下有两个.h文件,其分别为:
头文件 lvgl.h: lvgl源代码引用文件
头文件lv_conf_template.h: lvgl编译项目配置文件
修改lv_conf_template.h -----> lv_conf.h
实际项目中的文件名称如下:
3.5 Keil中配置源代码路径
在keil中将lvgl源代码的路径配置到项目中,方便编译。其具体配置如下:
4 文件架构编译配置
4.1 项目文件架构
项目中和lvgl库相关的文件架构如下:
4.2 编译配置
完成文件加载和路径配置后,需要使能lvgl的源代码,需要再lv_conf.h文件中作相关的修改,修改方法如下:
5 测试
5.1 测试代码实现
1)初始化LVGL
在使用UI接口实现绘图功能之前,必须初始化lvgl,初始化接口函数如下:
2) 刷新UI功能
完成代码加载到项目之后,还需要在main.c函数调用两个函数lv_tick_inc()和lv_task_handler(),用于刷新UI和响应按键。具体方法如下:
5.2 测试案例
使用lvgl-8.4.0\demos\stress下的测试案例,进行LVGL功能测试
添加该文件到项目中:
运行结果如下: