目录
概述
1. 软硬件信息
1.1 开发版硬件
1.2 软件版本信息
2 编译LVGL为.lib
2.1 准备工作
2.2 编译.lib
3 验证.lib
3.1 Keil中加载.lib
3.2 Keil配置头文件路径
3.3 编译代码
4 应用程序
4.1 主函数中初始化接口
4.2 LVGL demo测试
4.2.1 编写测试代码
4.2.2 编译和测试
源代码下载地址:
应用lvgl的.lib的一个范例(stm32-f407-lvgl-lib-ui-proj)资源-CSDN文库
概述
本文主要介绍如何将lvgl的源文件转化为.lib文件,以及大简化加载lvgl源代码的繁琐步骤。随着lvgl的版本升级越来越高,其源代码也越来越多,项目中加载这些文件也是一个繁琐的任务,本文写作的目的就是为了简化这一操作。使用.LIB文件的方式,极大的简化添加源代码的过程更便于平台的移植。
未使用.lib库的lvgl项目文件结构
使用lib库后的项目文件结构:
1. 软硬件信息
1.1 开发版硬件
软硬件信息 | 版本信息 |
---|---|
STM32 MCU | STM32F407IGTx |
Keil | MDK ARM 5.38 |
STM32CubeMX | V6.8.1 |
调试工具:st-link | ST-LINK/V2-1 |
1.2 软件版本信息
软件信息 | 版本信息 |
---|---|
STM32 HAL | STM32Cube_FW_F4_V1.27.1 |
LVGL | V8.4.0 |
2 编译LVGL为.lib
2.1 准备工作
在将lvgl库编译为.lib库之前,必须保证lvgl已经被正确的移植到板卡中中,且设计一个简单的UI,保证其能正常工作。
笔者使用lvgl源代码版本为V8.4.0,其在Keil IED中的代码结构如下:
2.2 编译.lib
使用.lib文件能极大的简化源文件的加载过程,在实际的项目开发过程中,程序员很少会去更改第三方的库函数。所以,为了简化代码结构,会把第三方的库,编译生成一个.LIB文件。其编译步骤如下:
1)disable 非第三方的源文件
该项目的目的是把lvgl的源代码打包称为一个.LIB文件。那么非lvgl源代码相关的文件就没有必要编译到该.lib中。
在Keil IED上右键点击源代码文件夹,不要勾选如下两个checkbox。依次操作其他源文件目录。
完成操作后,可以看见如下架构:
2)编译lvgl库文件
完成以上配置之后,此时就可以编译 工程代码。编译成功后会看见如下信息:
3 验证.lib
3.1 Keil中加载.lib
由于lvgl的库文件和LCD显示和touch功能密切相关,在添加.LIB之前,必须保证LCD显示功能和Touch功能都能正常工作。
1)下载lvgl源代码v8.4.0,将如下四个目录或者文件放在GUI/lvgl目录下
把lvgl源代码放在工程目录下的原因:
上文已经将lvgl的.c文件编译成了.lib文件,项目中在调用.lib中的函数时,需要.h文件进行索引。而这些.h文件被放在lvgl的源文件下多个目录中,项目中只需添加头文件的路径即可,无需添加.c文件
2) 准备.lib文件
将.lib文件放在GUI/lvgl目录下
3) Keil中添加文件
GUI/lvgl: 该目录下放置lvgl.lib文件
GUI/lvgl_port: 该目录下放置和lvgl相关的接口函数文件,包括LCD接口函数,触摸屏接口
3.2 Keil配置头文件路径
在Keil中,需要配置如下几个头文件的路径
3.3 编译代码
完成以上配置之后,就可以编译代码,编译结果如下:
4 应用程序
4.1 主函数中初始化接口
1)在main.c文件中引用lvgl相关的头文件
2)初始化lvgl相关的接口
代码116行: 初始化lvgl
代码118行: 初始化lvgl-lcd相关接口
代码120行: 初始化lvgl-touch相关接口
注意点: 先初始化lcd display, 在初始化touch
代码129行: 调用lvgl tick
代码129行: 调用lvgl task函数
3)完成以上函数之后,重新编译代码,如果代码编译成功,就可以设计UI了
4.2 LVGL demo测试
4.2.1 编写测试代码
创建一个GUI/demo文件夹,在该文件夹中创建如下如下文件
编写如下测试代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : lv_mainstart.c
* Description : lvgl demo
* LVGL ver : V8.4.0
*
******************************************************************************
* @attention
*
* Copyright (c) 2024~2029 mingfei.tang
* All rights reserved.
*
*************************************************************************
*/
/* USER CODE END Header */
#include "demo.h"
#include "lvgl.h"
#include <stdio.h>
#define scr_act_width() lv_obj_get_width(lv_scr_act())
#define scr_act_height() lv_obj_get_height(lv_scr_act())
static lv_obj_t *switch_cool;
static lv_obj_t *switch_heat;
static lv_obj_t *switch_dry;
static const lv_font_t *font;
static void switch_event_cb(lv_event_t *e)
{
lv_obj_t *target = lv_event_get_target(e);
if(target == switch_cool)
{
if(lv_obj_has_state(switch_cool, LV_STATE_CHECKED))
{
lv_obj_clear_state(switch_heat, LV_STATE_CHECKED);
}
}
else if(target == switch_heat)
{
if(lv_obj_has_state(switch_heat, LV_STATE_CHECKED))
{
lv_obj_clear_state(switch_cool, LV_STATE_CHECKED);
}
}
}
static void lv_example_label(void)
{
if (scr_act_width() <= 320)
{
font = &lv_font_montserrat_14;
}
else if (scr_act_width() <= 480)
{
font = &lv_font_montserrat_24;
}
else
{
font = &lv_font_montserrat_26;
}
lv_obj_t *label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Control Center");
lv_obj_set_style_text_font(label, font, LV_STATE_DEFAULT);
lv_obj_align(label, LV_ALIGN_CENTER, 0, -scr_act_height() / 3 );
}
static void lv_example_switch1(void)
{
lv_obj_t *obj_cool = lv_obj_create(lv_scr_act());
lv_obj_set_size(obj_cool,scr_act_height() / 3, scr_act_height() / 3 );
lv_obj_align(obj_cool, LV_ALIGN_CENTER, -scr_act_width() / 4, 0 );
lv_obj_t *label_cool = lv_label_create(obj_cool);
lv_label_set_text(label_cool, "Cool");
lv_obj_set_style_text_font(label_cool, font, LV_STATE_DEFAULT);
lv_obj_align(label_cool, LV_ALIGN_CENTER, 0, -scr_act_height() / 16 );
switch_cool = lv_switch_create(obj_cool);
lv_obj_set_size(switch_cool,scr_act_height() / 6, scr_act_height() / 12 );
lv_obj_align(switch_cool, LV_ALIGN_CENTER, 0, scr_act_height() / 16 );
lv_obj_add_event_cb(switch_cool, switch_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
}
static void lv_example_switch2(void)
{
lv_obj_t *obj_heat = lv_obj_create(lv_scr_act());
lv_obj_set_size(obj_heat,scr_act_height() / 3, scr_act_height() / 3 );
lv_obj_align(obj_heat, LV_ALIGN_CENTER, 0, 0 );
lv_obj_t *label_heat = lv_label_create(obj_heat);
lv_label_set_text(label_heat, "Heat");
lv_obj_set_style_text_font(label_heat, font, LV_STATE_DEFAULT);
lv_obj_align(label_heat, LV_ALIGN_CENTER, 0, -scr_act_height() / 16 );
switch_heat = lv_switch_create(obj_heat);
lv_obj_set_size(switch_heat,scr_act_height() / 6, scr_act_height() / 12 );
lv_obj_align(switch_heat, LV_ALIGN_CENTER, 0, scr_act_height() / 16 );
lv_obj_add_event_cb(switch_heat, switch_event_cb, LV_EVENT_VALUE_CHANGED, NULL);
}
static void lv_example_switch3(void)
{
lv_obj_t *obj_dry = lv_obj_create(lv_scr_act());
lv_obj_set_size(obj_dry,scr_act_height() / 3, scr_act_height() / 3 );
lv_obj_align(obj_dry, LV_ALIGN_CENTER, scr_act_width() / 4, 0 );
lv_obj_t *label_dry = lv_label_create(obj_dry);
lv_label_set_text(label_dry, "Dry");
lv_obj_set_style_text_font(label_dry, font, LV_STATE_DEFAULT);
lv_obj_align(label_dry, LV_ALIGN_CENTER, 0, -scr_act_height() / 16 );
switch_dry = lv_switch_create(obj_dry);
lv_obj_set_size(switch_dry,scr_act_height() / 6, scr_act_height() / 12 );
lv_obj_align(switch_dry, LV_ALIGN_CENTER, 0, scr_act_height() / 16 );
lv_obj_add_state(switch_dry, LV_STATE_CHECKED|LV_STATE_DISABLED);
}
void lv_mainstart(void)
{
lv_example_label();
lv_example_switch1();
lv_example_switch2();
lv_example_switch3();
}
4.2.2 编译和测试
编写完成以上代码后,在main函数中调用:lv_mainstart()
编译代码,下载文件至板卡中,运行结果如下:
触动switch button
触动之后UI的变化