lvgl移植流程

移植准备

  1. 基于梁山派屏幕扩展板mcu屏幕源码Screen_MCU移植
  2. 下载lvgl 8.3版本源码下载地址:https://github.com/lvgl/lvgl
  3. 参考文档:Set-up a project — LVGL documentation

移植步骤

1. 删除源码

删除源码中不需要的文件夹,仅保留如下内容

  1. demos : lvgl综合案例
  2. examples :单个功能案例
  3. src : 源代码
  4. lv_conf_template.h : 重要的配置文件,里面存在非常多的开关
  5. lvgl.h : 头文件

将上述内容存放刀名为lvgl的文件夹中

2.导入lvgl到项目screen_mcu中

  1. 在screen_mcu项目中新建third_party文件夹
  2. 将第1个步骤中的lvgl文件夹拷入其中
  3. 将lvgl文件夹中的lv_conf_tempalate.h修改为lv_conf.h
  4. 把lv_conf.h的条件编译指令#if 0修改成#if 1

3.keil添加分组和头文件

1. 使用keil打开screen_mcu项目,添加如下分组

third_party/lvgl/example/porting
third_party/lvgl/src/core
third_party/lvgl/src/draw
third_party/lvgl/src/extra
third_party/lvgl/src/font
third_party/lvgl/src/gpu
third_party/lvgl/src/hal
third_party/lvgl/src/misc
third_party/lvgl/src/widgets

2. 添加LVGL相关的.c文件到相应分组,如下:

3. 添加头文件路径

4. 开启C99模式

移植显示
1把lv_port_disp_template.c/h的条件编译指令#if 0修改成#if 1
2lv_port_disp_template.h中包含输出设备驱动头文件lcd.h
3lv_port_disp_template.h中宏定义水平和竖直分辨率(默认横屏)

#define MY_DISP_HOR_RES 240 //水平分辨率#define MY_DISP_VER_RES 280 //垂直分辨率


5. 修改 lv_port_disp_template.c中 的 lv_port_disp_init 函数
配置图形数据缓冲模式
在lv_port_disp_init函数中选择一种缓冲模式,注释掉其它两种模式

image.png


修改宽高

disp_drv.hor_res = lcddev.width;
disp_drv.ver_res = lcddev.height;

 

6. 在disp_flush函数中配置打点输出

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{ST7789_Fill(area->x1,area->y1,area->x2,area->y2,(uint16_t*)color_p);/*IMPORTANT!!!*Inform the graphics library that you are ready with the flushing*/lv_disp_flush_ready(disp_drv);
}

 

4. 移植触摸

  1. 把lv_port_indev_tempalte.c/h的条件编译#if 0 修改成# if 1
  2. 在lv_port_indev_tempalte.c中裁剪输入设备
  • 只保留touchpad_xxx相关的方法,删除其它方法
  • lv_port_indev_init中只保留touchpad相关的代码
  • 在touchpad_init方法中执行触摸屏初始化CST816T_Init();
/*Initialize your touchpad*/
static void touchpad_init(void)
{GT1151_Init();              //触摸屏初始化
}

3. 配置触摸检测函数

/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{/*Your code comes here*/return CST816T_is_pressed();// return false;
}

4. 配置坐标获取函数

/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{/*Your code comes here*/CST816T_get_xy((uint16_t*)x,(uint16_t*)y);//(*x) = 0;//(*y) = 0;
}

提示

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*/
#if 1/**********************      INCLUDES*********************/
#include "lv_port_indev_template.h"
//#include "../../lvgl.h"
#include "cst816t.h"/**********************      DEFINES*********************//***********************      TYPEDEFS**********************//***********************  STATIC PROTOTYPES**********************/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);static void mouse_init(void);
static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static bool mouse_is_pressed(void);
static void mouse_get_xy(lv_coord_t * x, lv_coord_t * y);static void keypad_init(void);
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static uint32_t keypad_get_key(void);static void encoder_init(void);
static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static void encoder_handler(void);static void button_init(void);
static void button_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static int8_t button_get_pressed_id(void);
static bool button_is_pressed(uint8_t id);/***********************  STATIC VARIABLES**********************/
lv_indev_t * indev_touchpad;
lv_indev_t * indev_mouse;
lv_indev_t * indev_keypad;
lv_indev_t * indev_encoder;
lv_indev_t * indev_button;static int32_t encoder_diff;
static lv_indev_state_t encoder_state;/***********************      MACROS**********************//***********************   GLOBAL FUNCTIONS**********************/void lv_port_indev_init(void)
{/*** Here you will find example implementation of input devices supported by LittelvGL:*  - Touchpad*  - Mouse (with cursor support)*  - Keypad (supports GUI usage only with key)*  - Encoder (supports GUI usage only with: left, right, push)*  - Button (external buttons to press points on the screen)**  The `..._read()` function are only examples.*  You should shape them according to your hardware*/static lv_indev_drv_t indev_drv;/*------------------* Touchpad* -----------------*//*Initialize your touchpad if you have*/touchpad_init();/*Register a touchpad input device*/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**********************//*------------------* Touchpad* -----------------*//*Initialize your touchpad*/
static void touchpad_init(void)
{/*Your code comes here*/CST816T_Init();
}/*Will be called by the library to read the touchpad*/
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;/*Save the pressed coordinates and the state*/if(touchpad_is_pressed()) {touchpad_get_xy(&last_x, &last_y);data->state = LV_INDEV_STATE_PR;}else {data->state = LV_INDEV_STATE_REL;}/*Set the last pressed coordinates*/data->point.x = last_x;data->point.y = last_y;
}/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{/*Your code comes here*/return CST816T_is_pressed();// return false;
}/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{/*Your code comes here*/CST816T_get_xy((uint16_t*)x,(uint16_t*)y);//(*x) = 0;//(*y) = 0;
}#else /*Enable this file at the top*//*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

6.添加测试案例

测试音乐界面

  1. keil添加lvgl/demos/music文件夹下所有.c文件
  2. 添加相关头文件路径
..\..\third_party\lvgl\demos
..\..\third_party\lvgl\demos\music

3. 修改lv_conf.h中的

#define LV_USE_DEMO_MUSIC 0 改为 #define LV_USE_DEMO_MUSIC 1

#define LV_FONT_MONTSERRAT_12 0 改为 #define LV_FONT_MONTSERRAT_12 1

#define LV_FONT_MONTSERRAT_16 0 改为#define LV_FONT_MONTSERRAT_16 1

#define LV_USE_DEMO_MUSIC       0
改为
#define LV_USE_DEMO_MUSIC       1#define LV_FONT_MONTSERRAT_12 0
改为
#define LV_FONT_MONTSERRAT_12 1#define LV_FONT_MONTSERRAT_16 0
改为
#define LV_FONT_MONTSERRAT_16 1

 7.main.c主函数

#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include "main.h"
#include "bsp_basic_timer.h"#include "lcd.h"
#include "touch.h"#include "lvgl.h"#include "lv_demo_music.h"
#include "lv_conf.h"
#include "lv_port_disp_template.h"
#include "lv_port_indev_template.h"int main(void)
{nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 优先级分组systick_config();	lv_init();lv_port_disp_init();lv_port_indev_init();	lv_demo_music();while(1){lv_tick_inc(1);lv_timer_handler();delay_1ms(5);}
}

8.提高堆栈内存大小

修改startup_gd32f450_470.s中的Stack_Size

原始:
Stack_Size      EQU     0x00000400
修改后:
Stack_Size      EQU     0x00000800

9. 提供时钟

在Hardware下创建timer文件夹,文件夹下定义bsp_basic_timer.h和bsp_basic_timer.c文件,内容如下

bsp_basic_timer.h

#ifndef _BSP_BASIC_TIMER_H
#define _BSP_BASIC_TIMER_H#include "gd32f4xx.h"
#include "systick.h"
#include "stdio.h"
#include "lvgl.h"#define BSP_TIMER_RCU  				RCU_TIMER5            // 定时器时钟
#define BSP_TIMER      				TIMER5                // 定时器
#define BSP_TIMER_IRQ  				TIMER5_DAC_IRQn       // 定时器中断
#define BSP_TIMER_IRQHANDLER  TIMER5_DAC_IRQHandler // 定时器中断服务函数//#define BSP_TIMER_RCU  				RCU_TIMER2					// 定时器时钟
//#define BSP_TIMER      				TIMER2							// 定时器
//#define BSP_TIMER_IRQ  			  TIMER2_IRQn					// 定时器中断
//#define BSP_TIMER_IRQHANDLER  TIMER2_IRQHandler		// 定时器中断服务函数void basic_timer_config(uint16_t pre,uint16_t per); // 基本定时器配置#endif  /* BSP_BASIC_TIMER_H */

 bsp_basic_timer.c


#include "bsp_basic_timer.h"
//#include "bsp_led.h"/************************************************
函数名称 : basic_timer_config
功    能 : 基本定时器配置
参    数 : pre:时钟预分频值per:周期 
*************************************************/
void basic_timer_config(uint16_t pre,uint16_t per)
{/* 一个周期的时间T = 1/f, 定时时间time = T * 周期设预分频值位pre,周期位pertime = (pre + 1) * (per + 1) / psc_clk*/timer_parameter_struct timere_initpara; 							// 定义定时器结构体/* 开启时钟 */rcu_periph_clock_enable(BSP_TIMER_RCU); 							// 开启定时器时钟/* CK_TIMERx = 4 x CK_APB1  = 4x50M = 200MHZ */rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4); // 配置定时器时钟timer_deinit(BSP_TIMER);														  // 复位定时器/* 配置定时器参数 */timere_initpara.prescaler = pre-1;                    //  时钟预分频值 0-65535   psc_clk = CK_TIMER / pretimere_initpara.alignedmode = TIMER_COUNTER_EDGE;     // 边缘对齐                  timere_initpara.counterdirection = TIMER_COUNTER_UP;  // 向上计数    timere_initpara.period = per-1;                       // 周期  /* 在输入捕获的时候使用  数字滤波器使用的采样频率之间的分频比例 */timere_initpara.clockdivision = TIMER_CKDIV_DIV1;     // 分频因子         /* 只有高级定时器才有 配置为x,就重复x+1次进入中断 */    timere_initpara.repetitioncounter = 0;							  // 重复计数器 0-255  timer_init(BSP_TIMER,&timere_initpara);								// 初始化定时器/* 配置中断优先级 */nvic_irq_enable(BSP_TIMER_IRQ,3,2); 									// 设置中断优先级为 3,2/* 使能中断 */timer_interrupt_enable(BSP_TIMER,TIMER_INT_UP);       // 使能更新事件中断 /* 使能定时器 */timer_enable(BSP_TIMER);
}/************************************************
函数名称 : BSP_TIMER_IRQHandler
功    能 : 基本定时器中断服务函数 
参    数 : 无
返 回 值 : 无
作    者 : LC
*************************************************/
void BSP_TIMER_IRQHANDLER(void)
{/* 这里是定时器中断 */if(timer_interrupt_flag_get(BSP_TIMER,TIMER_INT_FLAG_UP) == SET){timer_interrupt_flag_clear(BSP_TIMER,TIMER_INT_FLAG_UP);  // 清除中断标志位 /* 执行功能 */lv_tick_inc(1);}
}

定义之后,keil添加.c文件和头文件即可

错误处理

错误一

.\Objects\GD32F450.axf: Error: L6218E: Undefined symbol __aeabi_assert (referred from qrcodegen.o).

解决方案:

设置如下即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/632646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QtCreator12无法识别Qt5.15.2的安卓SDK与NDK配置解决

解决方法: 设置JDK为JDK11 使用Android Studio下载 Android SDK Command-line Tools 10.0 打开Android SDK Location : 双击打开cmdline-tools 复制10.0中所有东西到latest中 点击Manage Kits并选择Devices 然后点击Android会弹出下图窗口,并自动更 安装完成 成功识别

股票套牢,如何解套?当下行情怎么赚钱?

今年开年大盘继续一路下行&#xff0c;今天更是直接跌破2800点&#xff0c;很多朋友都是套牢的阶段&#xff0c;这种时候我们怎样解套&#xff0c;在这种情况下&#xff0c;作为散户的我们又如何才可以赚到钱呢&#xff1f; 股票被套可以借用哪些工具解套&#xff1f;详细操作…

新数智空间:阿里云边缘云持续保持中国公有云市场第一

全球领先的 IT 市场研究和咨询公司 IDC 发布 《中国边缘云市场解读&#xff08;2023H1&#xff09;》报告 中国边缘公有云服务市场 阿里云持续第一 稳居市场第一&#xff0c;“边缘”逆势生长 近日&#xff0c;全球领先的 IT 市场研究和咨询公司 IDC 最新发布《中国边缘云市…

Git学习笔记(第2章):Git安装

官网地址&#xff1a;Githttps://git-scm.com/ Step1&#xff1a;查看Git的GNU协议 → 点击“Next” Step2&#xff1a;设置Git的安装位置(非中文、无空格的目录) → 点击“Next” Step3&#xff1a;选择Git的选项配置(推荐默认设置) → 点击“Next” Step4&#xff1a;设置Git…

POI实现Excel多行复杂表头导出

POI实现Excel多行复杂表头导出 1. pom文件添加POI相关依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.10-FINAL</version> </dependency> <dependency><groupId>o…

python代码练习:链表——分隔链表

参考知识&#xff1a; 什么是链表Optional有什么用 题目&#xff1a; 题目来源&#xff1a;力扣 代码&#xff1a; from typing import Optionalclass ListNode: 链表结点的数据类型 def __init__(self, val0,nextNone):self.val valself.next nextdef convert_to_linked…

index_jsp报错

今天跟着视频一模一样敲代码&#xff0c;一直报500 搜索了好几篇csdn&#xff0c;不断地修改添加的jstl.jar 和standard.jar&#xff0c;修改这两个jar包版本&#xff0c;还是报500 又看到说是因为tomcat10中存在jsp.jar&#xff0c;同时存在发生冲突&#xff0c;于是把tomcat…

字符型在内存中的存储

由于此字符型只占一个字节 所以它就不存在大端存储和小端存储。 字符型数据在内存中的存储的是ASCII码值转换成的二进制的补码&#xff08;有符号char的二进制也有原码&#xff0c;反码&#xff0c;补码之分&#xff09; 例 ↑的十进制的ASCII值为24 转换成二进制为00011000…

docker里Java服务执行ping命令模拟流式输出

文章目录 业务场景处理解决实现ping功能并实时返回输出实现长ping和中断请求docker容器找不到ping命令处理 业务场景 我们某市的客户&#xff0c;一直使用CS版本的信控平台&#xff0c;直接安装客户Windows server服务器上&#xff0c;主要对信号机设备进行在线管理、方案配时…

Peter:经济形势不好,一个最大的原因就是诚信道德的缺失 | 程客有话说002

《程客有话说》是我们最新推出的一个访谈栏目&#xff0c;邀请了一些国内外有趣的程序员来分享他们的经验、观点与成长故事&#xff0c;我们尝试建立一个程序员交流与学习的平台&#xff0c;也欢迎大家推荐朋友或自己来参加我们的节目&#xff0c;一起加油。本期我们邀请的程序…

实验一 安装和使用Oracle数据库

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

基于人工蚁群、蚁群、遗传算法的多目标任务分配

matlab2020a可运行 基于人工蚁群、蚁群、遗传算法的多目标任务分配资源-CSDN文库

MAC磁盘空间不足怎么清理?MAC清理磁盘空间的五种方法

MAC磁盘空间不足怎么清理&#xff1f;当我们使用苹果MAC一段时间后&#xff0c;就会有大量的垃圾文件占用磁盘空间&#xff0c;例如系统缓存文件、应用程序缓存文件、备份和重复文件、旧版的应用程序及其部件等&#xff0c;为了不影响电脑的后续使用&#xff0c;我们需要经常清…

对java的interface的理解

一个例子来让我们理解更加深刻 这是我们的整体文件布局 ①A是接口 ②B和C是用来实现接口的类 ③show是我们的运行函数&#xff0c;用来展示 A接口 接口中定义的方法可以不用去实现,用其他类去实现(必须实现) 关键字:interface public interface A { // public static …

恭喜所有纺织人,你最想要的小程序来了

随着互联网的普及和电子商务的快速发展&#xff0c;越来越多的商家开始涉足线上销售。而小程序商城作为一种轻量级的应用程序&#xff0c;正逐渐成为商家们热衷选择的销售平台。本文将通过实用指南的形式&#xff0c;为商家们详细介绍如何通过乔拓云网后台&#xff0c;自助搭建…

C语言:预处理详解

创作不易&#xff0c;来个三连呗&#xff01; 一、预定义符号 C语⾔设置了⼀些预定义符号&#xff0c;可以直接使⽤&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编…

【前后端的那些事】评论功能实现

文章目录 聊天模块1. 数据库表2. 后端初始化2.1 controller2.2 service2.3 dao2.4 mapper 3. 前端初始化3.1 路由创建3.2 目录创建3.3 tailwindCSS安装 4. tailwindUI5. 前端代码编写 前言&#xff1a;最近写项目&#xff0c;发现了一些很有意思的功能&#xff0c;想写文章&…

最新 生成pdf文字和表格

生成pdf文字和表格 先看效果 介绍 java项目&#xff0c;使用apache的pdfbox工具&#xff0c;可分页&#xff0c;自定义列 依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>2.0.22<…

css 前端实现通过css动画实现进度条动态加载效果

效果图 代码 CommonProcess.vue 进度条动态加载组件代码 <!-- 进度条组件 --> <template><div class"common_process"><div v-for"(item, index) in dataList" :key"processType index" class"common_process_item…

SPI传感器接口设计与优化:基于STM32的实践

SPI&#xff08;串行外设接口&#xff09;是一种常用的串行通信协议&#xff0c;用于在微控制器和外部设备之间进行全双工的高速数据传输。在本文中&#xff0c;我们将探讨如何基于STM32微控制器设计和优化SPI传感器接口&#xff0c;并提供相应的代码示例。 1. SPI传感器接口设…