NanoPi NEO移植LVGL8.3.5到1.69寸ST7789V屏幕
移植前准备
移植好fbtft屏幕驱动
参考链接:友善之臂NanoPi NEO利用fbtft驱动点亮1.69寸ST7789V2屏幕
获取源码
名称 | 地址 | 描述 |
---|---|---|
lvgl | https://github.com/lvgl/lvgl.git | lvgl-8.3.5 |
lv_drivers | https://github.com/lvgl/lv_drivers.git | lv_drivers-6.1.1 |
创建工程目录
创建工程目录
mkdir lvgl_display
下载的源码解压到该文件夹,将文件夹名称中的版本号去掉
mv lvgl-8.3.5 lvgl
mv lv_drivers-6.1.1 lv_drivers
将头文件复制到工程目录下,去掉名称中的template
lvgl_display/lvgl/lv_conf_template.h => lvgl_display/lv_conf.h
lvgl_display/lv_drivers/lv_drv_conf_template.h => lvgl_display/lv_drv_conf.h
工程目录下创建main.c,Makefile,创建文件夹build工程目录文件如下:
名称 | 描述 |
---|---|
main.c | 测试程序 |
Makefile | 编译脚本 |
lv_conf.h | lvgl配置文件 |
lv_drv_conf.h | lvgl驱动配置文件 |
lvgl | lvgl8.3.5源码 |
lv_drivers | lvgl驱动源码 |
build | 编译过程文件 |
ls
rwxrwxr-x 2 pi pi 16384 8月 13 11:22 build/
-rw-rw-r-- 1 pi pi 26339 8月 13 11:16 lv_conf.h
drwxrwxr-x 6 pi pi 4096 1月 4 2020 lv_drivers/
-rw-rw-r-- 1 pi pi 11196 8月 13 09:19 lv_drv_conf.h
drwxrwxr-x 10 pi pi 4096 2月 7 2023 lvgl/
-rw-rw-r-- 1 pi pi 2401 8月 13 11:22 main.c
-rw-rw-r-- 1 pi pi 1956 8月 13 11:05 Makefile
修改配置文件lv_drv_conf.h
将#if 0修改为#if 1
/*** @file lv_drv_conf.h**//** COPY THIS FILE AS lv_drv_conf.h*/#if 1 /*Set it to "1" to enable the content*/#ifndef LV_DRV_CONF_H
#define LV_DRV_CONF_H#include "lv_conf.h"
将宏USE_FBDEV的值改为1,使能frame buffer
设备
/*-----------------------------------------* Linux frame buffer device (/dev/fbx)*-----------------------------------------*/
#ifndef USE_FBDEV
# define USE_FBDEV 1
#endif#if USE_FBDEV
# define FBDEV_PATH "/dev/fb0"
#endif
修改lv_conf.h
将文件最开始的#if 0改为#if 1
/* clang-format off */
#if 1 /*Set it to "1" to enable content*/#ifndef LV_CONF_H
#define LV_CONF_H#include <stdint.h>
使能宏LV_MEM_CUSTOM为1
/*=========================MEMORY SETTINGS*=========================*//*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
#define LV_MEM_CUSTOM 1
#if LV_MEM_CUSTOM == 0/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/#define LV_MEM_SIZE (48U * 1024U) /*[bytes]*//*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/#define LV_MEM_ADR 0 /*0: unused*//*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/#if LV_MEM_ADR == 0#undef LV_MEM_POOL_INCLUDE#undef LV_MEM_POOL_ALLOC#endif#else /*LV_MEM_CUSTOM*/#define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/#define LV_MEM_CUSTOM_ALLOC malloc#define LV_MEM_CUSTOM_FREE free#define LV_MEM_CUSTOM_REALLOC realloc
#endif /*LV_MEM_CUSTOM*/
最后是比较关键的一个设置,TICK的配置,我们选择自己定义一个Tick定时器配置函数,在自己的应用程序中实现,源码用#if 0屏蔽
#if 0 //原始代码
/*Use a custom tick source that tells the elapsed time in milliseconds.*It removes the need to manually update the tick with `lv_tick_inc()`)*/
#define LV_TICK_CUSTOM 0
#if LV_TICK_CUSTOM#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*//*If using lvgl as ESP32 component*/// #define LV_TICK_CUSTOM_INCLUDE "esp_timer.h"// #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((esp_timer_get_time() / 1000LL))
#endif /*LV_TICK_CUSTOM*/#else //新代码
/*Use a custom tick source that tells the elapsed time in milliseconds.*It removes the need to manually update the tick with `lv_tick_inc()`)*/
#define LV_TICK_CUSTOM 1
#if LV_TICK_CUSTOM#define LV_TICK_CUSTOM_INCLUDE <stdint.h> /*Header for the system time function*/#define LV_TICK_CUSTOM_SYS_TIME_EXPR (custom_tick_get()) /*Expression evaluating to current system time in ms*/
#endif /*LV_TICK_CUSTOM*/
#endif
使能music例程
#define LV_FONT_MONTSERRAT_12 1
#define LV_FONT_MONTSERRAT_14 1
#define LV_FONT_MONTSERRAT_16 1/*Music player demo*/
#define LV_USE_DEMO_MUSIC 1
修改lv_drivers/display/fbdev.c
不修改可能导致系统崩溃
screensize = finfo.line_length * vinfo.yres;
main.c内容
#include "lvgl/lvgl.h"
//#include "lvgl/demos/lv_demos.h" //未使用 屏蔽
#include "lv_drivers/display/fbdev.h"
#include "lv_drivers/indev/evdev.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>#define DISP_BUF_SIZE (128 * 1024)int main(void)
{/*LittlevGL init*/lv_init();/*Linux frame buffer device init*/fbdev_init();/*A small buffer for LittlevGL to draw the screen's content*/static lv_color_t buf[DISP_BUF_SIZE];/*Initialize a descriptor for the buffer*/static lv_disp_draw_buf_t disp_buf;lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);/*Initialize and register a display driver*/static lv_disp_drv_t disp_drv;lv_disp_drv_init(&disp_drv);disp_drv.draw_buf = &disp_buf;disp_drv.flush_cb = fbdev_flush;//修改分辨率disp_drv.hor_res = 280;disp_drv.ver_res = 240;lv_disp_drv_register(&disp_drv);
#if 0 //未使用输入设备evdev_init();static lv_indev_drv_t indev_drv_1;lv_indev_drv_init(&indev_drv_1); /*Basic initialization*/indev_drv_1.type = LV_INDEV_TYPE_POINTER;/*This function will be called periodically (by the library) to get the mouse position and state*/indev_drv_1.read_cb = evdev_read;lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);/*Set a cursor for the mouse*/LV_IMG_DECLARE(mouse_cursor_icon)lv_obj_t * cursor_obj = lv_img_create(lv_scr_act()); /*Create an image object for the cursor */lv_img_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/lv_indev_set_cursor(mouse_indev, cursor_obj); /*Connect the image object to the driver*/
#endif/*Create a Demo*/lv_demo_music();/*Handle LitlevGL tasks (tickless mode)*/while(1) {lv_timer_handler();usleep(5000);}return 0;
}/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{static uint64_t start_ms = 0;if(start_ms == 0) {struct timeval tv_start;gettimeofday(&tv_start, NULL);start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;}struct timeval tv_now;gettimeofday(&tv_now, NULL);uint64_t now_ms;now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;uint32_t time_ms = now_ms - start_ms;return time_ms;
}
Makefile
#
# Makefile
#
CC ?= gcc
LVGL_DIR_NAME ?= lvgl
LVGL_DIR ?= ${shell pwd}
CFLAGS ?= -O3 -g0 -I$(LVGL_DIR)/ -Wall -Wshadow -Wundef -Wmissing-prototypes -Wno-discarded-qualifiers -Wall -Wextra -Wno-unused-function -Wno-error=strict-prototypes -Wpointer-arith -fno-strict-aliasing -Wno-error=cpp -Wuninitialized -Wmaybe-uninitialized -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits -Wsizeof-pointer-memaccess -Wno-format-nonliteral -Wno-cast-qual -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wformat-security -Wno-ignored-qualifiers -Wno-error=pedantic -Wno-sign-compare -Wno-error=missing-prototypes -Wdouble-promotion -Wclobbered -Wdeprecated -Wempty-body -Wtype-limits -Wshift-negative-value -Wstack-usage=2048 -Wno-unused-value -Wno-unused-parameter -Wno-missing-field-initializers -Wuninitialized -Wmaybe-uninitialized -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wtype-limits -Wsizeof-pointer-memaccess -Wno-format-nonliteral -Wpointer-arith -Wno-cast-qual -Wmissing-prototypes -Wunreachable-code -Wno-switch-default -Wreturn-type -Wmultichar -Wno-discarded-qualifiers -Wformat-security -Wno-ignored-qualifiers -Wno-sign-compare -std=c99
LDFLAGS ?= -lm
BIN = demo#Collect the files to compile
MAINSRC = ./main.cinclude $(LVGL_DIR)/lvgl/lvgl.mk
include $(LVGL_DIR)/lv_drivers/lv_drivers.mk
OBJ_DIR := $(LVGL_DIR)/build
#CSRCS +=$(LVGL_DIR)/my_ui/main.c
##################################### 收集需要编译的源文件 #####################################
CSRCS += $(LVGL_DIR)/main.c
##################################### 将文件名替换为.o文件 #####################################CXX_OBJCTS = $(patsubst %.c, $(OBJ_DIR)/%.o, $(notdir $(CSRCS)))SOURSE_DIR = $(dir $(CSRCS))vpath %.c $(SOURSE_DIR)$(OBJ_DIR)/%.o: %.c$(CC) $(CFLAGS) -c $< -o $@echo "CC $<"all: $(CXX_OBJCTS)$(CC) -o $(BIN) $(CXX_OBJCTS) $(LDFLAGS)
clean: rm -f $(BIN) $(CXX_OBJCTS)
效果展示
相关文章:

NanoPi NEO移植LVGL8.3.5到1.69寸ST7789V屏幕
移植前准备 移植好fbtft屏幕驱动 参考链接:友善之臂NanoPi NEO利用fbtft驱动点亮1.69寸ST7789V2屏幕 获取源码 名称地址描述lvglhttps://github.com/lvgl/lvgl.gitlvgl-8.3.5lv_drivershttps://github.com/lvgl/lv_drivers.gitlv_drivers-6.1.1 创建工程目录 创…...

阿里云服务区ECS,申请免费的服务器之后,如何使用xshell 登陆,找不到匹配的host key 算法
目录 1 问题2 解决 1 问题 当在阿里云免费领取服务器之后,使用xshell 登陆不上,提示 找不到匹配的host key 算法 或者 找不到匹配的keyexchange算法 咋解决 2 解决 在在服务器端配置文件:/etc/ssh/sshd_config # 在行尾增加",ecdh…...

【CTF-web】备份是个好习惯(查找备份文件、双写绕过、md5加密绕过)
题目链接:https://ctf.bugku.com/challenges/detail/id/83.html 经过扫描可以找到index.php.bak备份文件,下载下来后打开发现是index.php的原代码,如下图所示。 由代码可知我们要绕过md5加密,两数如果满足科学计数法的形式的话&a…...

C#和Java的大端位和小端位的问题
C#代码里就是小端序,Java代码里就是大端序, 大端位:big endian,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,也叫高尾端 小端位:little endian,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存…...

如何在 iOS 上安装并使用 ONLYOFFICE 文档
借助 iOS 版文档应用,您可在移动端设备上访问存储于 ONLYOFFICE 账户中的文件,查看和编辑现有文本文档、电子表格和演示文稿,创建新文档并对其进行整理,以及连接第三方云存储服务。您可与其他门户网站用户协作编辑文档,…...

【AI】如何用AI生成XMind思维导图
哈喽,大家好,我是木头左,物联网搬砖工一名,致力于为大家淘出更多好用的AI工具! 背景 随着人工智能技术的不断发展,越来越多的应用场景开始涉及到AI技术。在办公软件领域,XMind是一款非常受欢迎…...

k8s问题汇总
作者前言 本文章为记录使用k8s遇到的问题和解决方法,文章持续更新中… 目录 作者前言正常配置ingress,但是访问错误添加工作节点报错安装k8s报错使用kubectl命令报错container没有运行安装会出现kubelet异常,无法识别删除k8s集群访问dashboa…...

打造专属照片分享平台:快速上手Piwigo网页搭建
文章目录 通过cpolar分享本地电脑上有趣的照片:部署piwigo网页前言1.Piwigo2. 使用phpstudy网页运行3. 创建网站4. 开始安装Piwogo 总结 🍀小结🍀 🎉博客主页:小智_x0___0x_ 🎉欢迎关注:&#x…...

OpenAI全球招外包大军,手把手训练ChatGPT取代码农 ; 码农:我自己「杀」自己
目录 前言 OpenAI招了一千多名外包人员,训练AI学会像人类一样一步步思考。如果ChatGPT「学成归来」,码农恐怕真的危了? 码农真的危了! 当时OpenAI也说,ChatGPT最合适的定位,应该是编码辅助工具。 用Cha…...

船舶法兰盘法兰管件3D扫描尺寸测量|三维扫描检测|CAV测量-CASAIM
第一章 服务背景 船舶建造多采用分段建造法,即将零件、预装好的部件在胎架上组合焊接成分段或总段,然后由船台装配成整船的建造方法。而当船体合拢组装时,在船体上遍布着各种各样的管道,这些管道都需要互相完全适配以确保船体安装…...

每天一道leetcode:1218. 最长定差子序列(动态规划中等)
今日份题目: 给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。 子序列 是指在不改变其余元素顺序的情况下,通过删除一些元素或不删除任何…...
C#的 Settings.Settings配置文件的使用方法
1、定义 在Settings.settings文件中定义配置字段。把作用范围定义为:User则运行时可更改(用户范围的字段数据更改存储在用户信息中,不在该程序文件中),Applicatiion则运行时不可更改。可以使用数据网格视图(VS软件的Properties 下面的Setting…...
神经网络基础-神经网络补充概念-35-为什么正则化可以减少过拟合
概念 正则化可以减少过拟合的原因在于它通过限制模型的复杂性来约束参数的取值范围,从而提高了模型的泛化能力。过拟合是指模型在训练集上表现很好,但在未见过的数据上表现不佳,这通常是因为模型过于复杂,过多地拟合了训练数据中…...

Glide 的超时控制相关处理
作者:newki 前言 Glide 相信大家都不陌生,各种源码分析,使用介绍大家应该都是烂熟于心。但是设置 Glide 的超时问题大家遇到过没有。 我遇到了,并且掉坑里了,情况是这样的。 调用接口从网络拉取用户头像,…...

使用requests如何实现自动登录
不知道大家有没有注意到,好多网站我们登录过后,在之后的某段时间内访问该网页时,不会给出请登录的提示,时间到期后就会提示请登录!这样在使用爬虫访问网页时还要登录,打乱我们的节奏,那么如何使…...

【代码随想录-Leetcode第六题:209. 长度最小的子数组】
209. 长度最小的子数组 题目思路代码实现 题目 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回…...
部署LVS-DR群集
LVS的工作模式及工作过程 LVS 有三种负载均衡的模式,分别是VS/NAT(nat 模式)、VS/DR(路由模式)、VS/TUN(隧道模式)。 1、NAT模式(VS-NAT) 原理:首先负载均…...
建库、建表、修改表、复制表、字符类型、数值类型、枚举类型、日期时间类型、检索目录、数据导入命令、数据导入步骤、数据导出命令、非空、默认值、唯一索
Top NSD DBA DAY04 案例1:表管理案例2:数据类型案例3:数据批量处理案例4:表头基本约束 1 案例1:表管理 1.1 问题 建库练习建表练习修改表练习 1.2 方案 在MySQL50主机完成练习。 1.3 步骤 实现此案例需要按照如…...
iview默认样式覆盖
scoped 属性是 HTML5 中的新属性。 当style标签拥有scoped属性时,它的css样式只能用于当前的Vue组件,可以使组件的样式不相互污染。 如果一个项目的所有style标签都加上了scoped属性,相当于实现了样式的模块化。 1、全页面覆盖 不添加scoped…...
System.Text.Encoding不同字符编码之间进行转换
System.Text.Encoding 是 C# 中用于处理字符编码和字符串与字节之间转换的类。它提供了各种静态方法和属性,用于在不同字符编码之间进行转换,以及将字符串转换为字节数组或反之。 在处理多语言文本、文件、网络通信以及其他字符数据的场景中,…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...