当前位置: 首页 > news >正文

lvgl 双物理显示器的驱动实现

目录

  • 一、背景
    • 1. 要实现的功能
    • 2. lvgl 版本
  • 二、简单粗暴的方式
    • 理论上可以这样实现
    • 缺陷:
  • 三、lvgl 自身机制支持
    • 3.1 实现思路
    • 3.2 初始化缓冲区和注册显示驱动
      • 3.2.1 复制lv_port_disp → lv_port_disp_2
      • 3.2.2 修改 lv_port_disp_2 文件
      • 3.2.3 在应用层调用显示器2初始化程序
    • 3.3 如何切换显示器
      • 3.3.1 切换显示器的 API
      • 3.3.2 如何找到显示器指针
      • 3.3.3 接收显示器指针
        • 定义保存显示器1 指针的变量
        • 接收显示器1 指针
        • 提供 API 供上层访问
      • 3.3.4 另外一种返回显示器指针的实现方式
        • 返回显示器1指针
        • 返回显示器2 指针
      • 3.3.5 应用层切换显示器实现
        • 选择显示器1
        • 选择显示器2
  • 四、参考链接

一、背景

1. 要实现的功能

一个mcu 物理连接两块彩屏,使用一个lvgl内核实现对双显示器的显示驱动。

2. lvgl 版本

V8.3.x

二、简单粗暴的方式

理论上可以这样实现

  • 软件应用层将两款显示器虚拟成一整块显示器。显示器的宽度就是最宽那个显示器的宽度,显示的长度是显示器1 + 显示器2 的长度。
  • 在刷屏打点函数中(disp_flush),根据坐标进行判断,属于显示器1 范围的数据,写到物理显示器1;属于显示器2范围的数据,写到物理显示器2。

缺陷:

  • 可能存在边界数据处理异常问题;
  • 对lvgl 来说,屏幕宽度和高度是虚拟的。如果想实现参考屏幕本身对齐的功能,比较难实现。
  • 在软件编码实现UI时,需要将显示坐标转换成虚拟坐标。不够直观。例如要实现分别在两块显示器的(0,0) 坐标开始位置写数据。写显示器1时,可以写(0,0) 坐标;写显示2时,需要写(0,LCD_SCR1_Y_MAX);

三、lvgl 自身机制支持

3.1 实现思路

  • 为每一个显示器分配并初始化一个缓冲区;
  • 为每一个显示器注册显示驱动;
  • 每次更新显示内容前,先选中当前的显示器

3.2 初始化缓冲区和注册显示驱动

3.2.1 复制lv_port_disp → lv_port_disp_2

显示缓冲区初始化和显示器注册的处理部分都在 lv_port_disp.c 文件中;复制一份 lv_port_disp.clv_port_disp.h)文件,改名为 lv_port_disp_2.c ( lv_port_disp_2.h )负责显示器2的初始化。

3.2.2 修改 lv_port_disp_2 文件

  • 更正显示器2的x,y 坐标范围
  • 将每一个可能因此重定义的变量或函数重命名。例如
    • lv_port_disp_init → lv_port_disp_init_2

3.2.3 在应用层调用显示器2初始化程序

在调用 lv_port_disp_init() 后面,调用 lv_port_disp_init_2()

3.3 如何切换显示器

3.3.1 切换显示器的 API

完成上面步骤之后,就已经完成了显示器缓冲区分配,显示驱动注册。

通过阅读官方帮助文档,我们知道 lv_disp_set_default(disp) 用来切换当前的默认显示器。

void lv_disp_set_default(lv_disp_t * disp)
{disp_def = disp;
}

参数 disp 就是要设置的显示器指针。

3.3.2 如何找到显示器指针

大致看了一遍相关的源码文件,没看到直接返回显示器1显示器2的相关接口函数。重新研究了一遍注册显示器的过程,发现 lv_disp_drv_register 注册显示驱动函数,会返回当前注册的显示器指针。这个函数在lv_port_disp.c 文件中调用。

由于默认只有一个显示器,所以默认也没接收这个函数的返回值,记录为当前显示器指针。

lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver)

3.3.3 接收显示器指针

以显示器1 为例说明。以下代码都是在 lv_port_disp.c 文件中实现。

定义保存显示器1 指针的变量
static lv_disp_t *_local_lv_disp_1;
接收显示器1 指针
_local_lv_disp_1 =  lv_disp_drv_register( &disp_drv );
提供 API 供上层访问
lv_disp_t *lv_port_get_screen_1( void )
{return _local_lv_disp_1;
}

3.3.4 另外一种返回显示器指针的实现方式

查看lv_disp_drv_register 函数,发现函数的第一行实现如下:

lv_disp_t * disp = _lv_ll_ins_head(&LV_GC_ROOT(_lv_disp_ll));

插入一个 接节点到列表LV_GC_ROOT(_lv_disp_ll) 的头部,并返回新插入的节点的指针。列表 LV_GC_ROOT(_lv_disp_ll) 就是物理显示器列表。

那么,我们遍历整个 LV_GC_ROOT(_lv_disp_ll) 列表,就能依次返回物理显示器的指针。由于应用层先注册显示器1,所以显示器1的指针位于队列尾。

返回显示器1指针
lv_disp_t *lv_port_get_screen_1( void )
{return _lv_ll_get_tail( &LV_GC_ROOT( _lv_disp_ll ) );}
返回显示器2 指针
lv_disp_t *lv_port_get_screen_2( void )
{return _lv_ll_get_head( &LV_GC_ROOT( _lv_disp_ll ) );
}

3.3.5 应用层切换显示器实现

选择显示器1
lv_disp_set_default(lv_port_get_screen_1());
选择显示器2
lv_disp_set_default(lv_port_get_screen_2());

四、参考链接

  • LVGL Displays :https://docs.lvgl.io/8.3/overview/display.html

相关文章:

lvgl 双物理显示器的驱动实现

目录 一、背景 1. 要实现的功能2. lvgl 版本 二、简单粗暴的方式 理论上可以这样实现缺陷: 三、lvgl 自身机制支持 3.1 实现思路3.2 初始化缓冲区和注册显示驱动 3.2.1 复制lv_port_disp → lv_port_disp_23.2.2 修改 lv_port_disp_2 文件3.2.3 在应用层调用显示器…...

论文阅读——X-Decoder

Generalized Decoding for Pixel, Image, and Language Towards a Generalized Multi-Modal Foundation Model 1、概述 X-Decoder没有为视觉和VL任务开发统一的接口,而是建立了一个通用的解码范式,该范式可以通过采用共同的(例如语义&#…...

【Kubernetes】控制器Statefulset

Statefulset控制器 一、概念二、Statefulset资源清单文件编写技巧2.1、查看定义Statefulset资源需要的字段2.2、查看statefulset.spec字段如何定义2.3、查看statefulset的spec.template字段如何定义 三、Statefulset使用案例:部署web站点3.1、编写一个Statefulset资…...

智能优化算法应用:基于鱼鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于鱼鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于鱼鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鱼鹰算法4.实验参数设定5.算法结果6.参考文献7.MA…...

探索 Vue3 (五) 骨架屏

骨架屏是页面的一个空白版本,通常会在页面完全渲染之前,通过一些灰色的区块大致勾勒出轮廓,待数据加载完成后,再替换成真实的内容。 目前主流 UI库 都有骨架屏,如 Element-UI、Antd 可以看到使用起来非常简单&#x…...

java取出list中的某几个属性组成一个新的集合的几种方式

我用了三种方式,1:forEach循环;2:for循环;3:stream方法 package org.springblade.test;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors;public class Test {org.junit.jupiter.api…...

开源自托管导航页配置服务Dashy本地搭建结合内网穿透远程访问

开源自托管导航页配置服务Dashy本地搭建结合内网穿透远程访问 简介1. 安装Dashy2. 安装cpolar3.配置公网访问地址4. 固定域名访问 简介 Dashy 是一个开源的自托管的导航页配置服务,具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你可以将自己常用的一…...

Cloudstack多个管理服务器节点

https://docs.cloudstack.apache.org/en/4.18.0.0/adminguide/reliability.html 参考翻译: 代理上支持多个管理服务器 在具有多个管理服务器的Cloudstack环境中,可以根据算法配置代理,将其连接到哪个管理服务器。这对于内部负载均衡器或高可…...

31. Ajax

简介 AJAX 是 Asynchronous JavaScript And XML 的简称。直译为,异步的JS和XML。AJAX的实际意义是,不发生页面跳转、异步载入内容并改写页面内容的技术。AJAX也可以简单的理解为通过JS向服务器发送请求。 AJAX这门技术很早就被发明,但是直到…...

ArrayList源码学习笔记(3)

时隔两年&#xff0c;重新读ArrayList源码&#xff0c;轻松了很多&#xff0c;以问题的方式记录一下收获 装饰器模式 注释中提到ArrayList本身不是线程安全的&#xff0c;注释如下&#xff1a; * <p><strong>Note that this implementation is not synchronized.&…...

flutter怎么对ReorderableListView中的用于排序的控制手柄进行显示或隐藏

我在使用ReorderableListView创建可排序列表的时候&#xff0c;需要在编辑的时候才显示右侧的控制排序的手柄。研究了半天&#xff0c;配合搜索引擎&#xff0c;才找到正确的方案。 答案很简单&#xff0c;就是在它的属性当中有一个叫做&#xff1a;buildDefaultDragHandles的…...

python 1200例——【9】斐波那契数列

文章目录 定义求解方法1. 递归方法2. 循环方法3. 动态规划方法4. 矩阵方法总结:定义 斐波那契数列(Fibonacci sequence)是一个在自然世界中经常出现的数学序列。它是由0和1开始,然后的每个数字都是前两个数字的和。因此,斐波那契数列的前几个数字是:0, 1, 1, 2, 3, 5, 8…...

JavaScript读写T5557卡源码

本示例使用发卡器&#xff1a; https://item.taobao.com/item.htm?spma1z10.5-c-s.w4002-21818769070.13.48ce6f89XlQ9Vf&id675212889085 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-t…...

【数据结构】LRU缓存的简单模拟实现(leetcode力扣146LRU缓存)

文章目录 一、定义二、LRU模拟实现二、代码实现 一、定义 LRU是Least Recently Used的缩写&#xff0c;意思是最近最少使用&#xff0c;它是一种Cache替换算法。 Cache的容量有限&#xff0c;因此当Cache的容量用完后&#xff0c;而又有新的内容需要添加进来时&#xff0c; 就…...

基于电商场景的高并发RocketMQ实战-Commitlog基于内存的高并发写入优化、基于JVM offheap的内存读写分离机制

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 【11来了】文章导读地址&#xff1a;点击查看文章导读&#xff01; &#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f3…...

工具系列:TensorFlow决策森林_(3)使用dtreeviz可视化

文章目录 介绍设置安装 TF-DF 和 dtreeviz导入库 可视化分类树加载、清洗和准备数据分割训练/测试集并训练模型训练一个随机森林分类器显示决策树检查叶节点统计信息决策树如何对实例进行分类特征空间划分 可视化回归树加载、清洗和准备数据分割训练/测试集并训练模型训练一个随…...

【算法学习】斐波那契数列模型-动态规划

前言 我在算法学习过程中&#xff0c;针对斐波那契数列模型的动态规划的例题进行了一个整理&#xff0c;并且根据标准且可靠一点的动态规划解题思路进行求解类似的动归问题&#xff0c;来达到学习和今后复习的必要。 所谓的斐波那契数列模型&#xff0c;即当前状态的值等于前两…...

ES的安装和RestClient的操作

目录 初识elasticsearch 什么是elasticsearch elasticsearch的发展 Lucene的优缺点 elasticsearch的优势 倒排索引 es与mysql的概念对比 文档 索引 概念对比 架构 安装es 安装kibana 安装ik分词器 分词器 安装ik分词器 ik分词器的拓展和停用词典 操作索引库…...

访问者模式(Visitor)

访问者模式(Visitor Pattern)是一种将算法与对象结构分离的行为型设计模式。这种模式主要用于对一个由许多不同类型的对象构成的复杂对象结构(如组合结构)进行操作,而不需要对这些对象的类进行修改。 访问者模式涉及以下几个角色: 访问者(Visitor):为每一个具体元素类…...

ATTCK红队评估一

一、环境搭建 主机 ip地址 win7外网服务器&#xff08;两张网卡&#xff09; 外网&#xff1a;192.168.92.135 内网&#xff1a;192.168.52.143 server2003域成员主机 内网&#xff1a;192.168.52.141 server2008域空主机 内网&#xff1a;192.168.52.138 kali攻击机 …...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

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

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...