STM32 工程移植 LVGL:一步一步完成

news2024/10/6 18:31:15

STM32 工程移植 LVGL:一步一步完成

LVGL,作为一款强大且灵活的开源图形库,专为嵌入式系统GUI设计而生,极大地简化了开发者在创建美观用户界面时的工作。作为一名初学者,小编正逐步深入探索LVGL的奥秘,并决定记录下这段学习旅程,以便与同道中人共享心得。本文旨在于引导读者如何将LVGL图形库成功集成至STM32微控制器项目中,从零开始,步步为营,让嵌入式界面开发之旅变得更加平易近人。

小编选择了源自淘宝“魔女开发板”店铺的一款STM32F407开发板作为实践工具,其配套的丰富资源和客服技术支持为学习之路铺设了坚实的基础。特别值得关注的是,该店铺提供了一套详尽且实用的入门系列文章——【快速入门 LVGL】,首篇聚焦于如何在STM32工程中高效移植LVGL,该文详述了从环境搭建到实际应用的每一步,成为了我此次学习的重要指引。文章链接如下:
【快速入门 LVGL】-- 1、STM32 工程移植 LVGL

介绍

LVGL(Light and Variables Graphics Library)是一个免费的开源图形库,提供了创建具有易于使用的图形元素、优美的视觉效果和低内存占用的嵌入式GUI所需的一切。它用C语言编写,以实现最大的兼容性(与C ++兼容),模拟器可在没有嵌入式硬件的PC上启动嵌入式GUI设计。

1. 准备工作

首先,你需要以下几样东西:

  • STM32CubeMX:用于配置 STM32 的硬件特性。
  • STM32 HAL 库:STM32 的硬件抽象层库,用于简化硬件操作。
  • LVGL 库:你可以在 LVGL 的 GitHub 页面下载最新版本。

STM32工程的要求

1️⃣设置堆栈大小:Heap、Stack,设置为:0x1000

2️⃣准备好你使用开发平台所用屏幕的驱动函数BSP(一般屏幕商家会提供)

  • 画点函数,用于后面注册LVGL的显示功能
  • 触摸检测函数 (返回:0-未按下、1-按下)、坐标获取函数,用于注册LVGL的触屏功能

2. 下载 LVGL

浏览器搜索 lvgl git
在这里插入图片描述

虽然LVGL已发布了v9.0、v9.1等,但v8.3版,是目前最广泛使用的版本。
它拥有众多的网上教程资源,使开发者能够轻松地学习和使用LVGL。而且多款主流的可视化设计工具(如SimVis Designer和Qt Design Studio)都支持LVGL的v8.3版本。v9.0、v9.1等版本由于其相对较新,相关资源和可视化设计工具的支持可能相对较少。

因此这里建议下载v8.3版

可以选择用git clone到本地或者直接下载zip
在这里插入图片描述

下载完成
在这里插入图片描述

3. LVGL源文件裁剪

我们所下载的LVGL源文件并不是所有文件都要加入到我们的工程中,我们首先要进行裁剪

我们只需要下面这五个文件
在这里插入图片描述

1️⃣将这五个文件复制一份作为模板,方便后面的移植
在这里插入图片描述

2️⃣打开模板中的examples文件夹,将porting文件夹以外的全部文件删除
在这里插入图片描述
删除后👇
在这里插入图片描述

3️⃣修改 porting 里面的文件名称

由于LVGL源代码中的头文件,使用了相对路径,如在 “lvgl.h” 中

#include "src/misc/lv_log.h"
#include "src/misc/lv_timer.h"
#include "src/misc/lv_math.h"
#include "src/misc/lv_mem.h"
#include "src/misc/lv_async.h"
#include "src/misc/lv_anim_timeline.h"
#include "src/misc/lv_printf.h"

所以我们在构造工程是也要使用相同目录结构

打开 “porting” 文件夹,修改里面的文件名,将 “_template” 删除
在这里插入图片描述

修改后如下
在这里插入图片描述

4️⃣ 修改 lv_conf.h 文件名

回到 “LVGL” 文件夹中,lv_conf_template.h,是LVGL配置参数的重要文件,同样将它修改为: lv_conf.h
在这里插入图片描述

修改完成后如下
在这里插入图片描述

4. 将LVGL 添加到STM32工程

1️⃣将我们创建的 lvgl 文件夹,粘贴到STM32工程目录下

在这里插入图片描述
2️⃣打开Keil5,在工程里,添加4个文件夹

文件夹名称文件类型
LVGL_myGui用户自己的界面代码文件、官方demo等
LVGL_confLVGL 的两个h文件
LVGL_portingLVGL 的接口文件, 如显示、触摸屏、键盘等
LVGL_srcLVGL 的所有底层c文件

操作如下👇

在这里插入图片描述

3️⃣为每一个文件夹组,添加需要的文件

文件夹 (Group)添加文件
LVGL_myGUI不用添加。
LVGL_conflv_conf.h, lvgl.h
LVGL_portinglv_port_disp.c, lv_port_disp.h, lv_port_indev.c, lv_port_indev.h
LVGL_src所有 .c 文件位于 lvhl/src 及其所有子文件夹下

🚨注意src文件夹下,会有多重的子文件夹,需要把每一个子文件夹的C文件全部添加进来
在这里插入图片描述
4️⃣打勾C99
在这里插入图片描述

5️⃣添加头文件路径

配置项具体内容
路径1LVGL 文件夹路径
路径2LVGL\src 文件夹路径
路径3LVGL\examples\porting 文件夹路径

添加方法如下
在这里插入图片描述

5. 注册输出设备

1️⃣打开 lv_conf.h,对第15行预编译#if 0进行修改👇,将0改为1,以启用此文件
在这里插入图片描述
同样的方法启用LVGL_porting下的 lv_port_disp.h,打开 lv_port_disp.h,进行如下修改

行号原内容修改后内容
7#if 0#if 1
22lvgl/lvgl.hlvgl.h

在这里插入图片描述
同样启用 lv_port_disp.c

行号原内容修改后内容
7#if 0#if 1
12"lv_port_disp_template.h""lv_port_disp.h"

在这里插入图片描述
2️⃣添加 LCD 驱动的头文件
同样在 lv_port_disp.c

  1. 插入LCD驱动文件

    • 位置: 第14行之后
    • 操作: 插入您的LCD驱动头文件
  2. 设置显示屏宽度和高度

    • 位置: 第20行 & 第25行(或根据实际代码结构调整)
    • 操作: 根据您的显示屏参数,替换现有的宽度和高度定义

在这里插入图片描述
插入LCD驱动头文件 ,确保您的项目可以访问LCD的绘图功能,特别是画点函数。

🚨留意LVGL的横屏默认设置 LVGL库默认以横向模式布局,这意味着宽度对应水平像素,高度对应垂直像素。

3️⃣选择创建缓存的方式
lv_port_disp.c文件中,您需要配置LVGL的显示缓冲区。面对提供的三种创建缓冲区的选项,您需要选择其中一种方式。通常推荐选择第一种方案,特别是对于大多数基本应用场景。

定位到相关代码段:首先,在文件中找到第86行至101行附近的内容。这部分代码涉及到显示缓冲区的配置。

选择第一种方法:这通常是创建单个缓冲区的方法,适用于多数场景。确认第86行附近的代码(第一种缓冲区创建方式)是未被注释的,形如:

    /* Example for 1) */
    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_1[MY_DISP_HOR_RES * 10];                            /*A buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10);   /*Initialize the display buffer*/

这段代码初始化了一个缓冲区,名为buf_1,并分配了足够的内存空间来存储屏幕一行或多行的像素数据。

注释掉其他方法:为了明确选择第一种方式,需要将描述第二和第三种缓冲区创建方式的代码行(大约在第90行到101行之间)进行注释处理。注释后如下
在这里插入图片描述
4️⃣关联 画点函数
同样在lv_port_disp.c文件里

假设您的LCD驱动中画点函数的原型为

void My_LCD_DrawPixel(int x, int y, uint16_t color);

我们需要将其与LVGL的显示刷新回调函数168行的disp_flush()关联起来

替换画点函数disp_flush函数内部,LVGL通过调用一个画点函数来实际在屏幕上绘制每个像素。你需要将此部分代码替换为我们自己的的LCD驱动中的画点函数调用。

修改后如下
在这里插入图片描述

6. 注册触摸屏

1️⃣启用 “lv_port_indev.h
在lv_port_indev.h中修改下面两行

行号原始代码修改后代码
8#if 0#if 1
20"lvgl / lvgl.h""lvgl.h"

在这里插入图片描述

2️⃣启动 “lv_port_indev.c
打开"lv_port_indev.c", 修改以下内容

行号原内容修改后内容
7#if 0#if 1
12"lv_port_indev_template.h""lv_port_indev.h"
13"../../lvgl.h""lvgl.h"

在这里插入图片描述

3️⃣添加 触屏 的驱动头文件
同样在"lv_port_indev.c"文件下第14行,插入:#include “触摸屏的头文件”
在这里插入图片描述

4️⃣注释掉不需要的输入任务注册’

在文件 “lv_port_indev.c” 中,你还需要对输入设备初始化函数 lv_port_indev_init() 进行调整,以便仅启用触摸屏输入而禁用其他类型的输入设备注册。以下是具体的操作:

  1. 定位函数:首先,找到文件中的 lv_port_indev_init() 函数,它通常位于文件的中后部,大约在第70行左右。

  2. 识别并注释:在此函数内部,您会看到为不同输入设备(如触摸屏、鼠标、键盘、编码器和物理按键)注册处理任务的代码段。为了仅保留触摸屏输入,你需要:

    • 保留:触摸屏输入相关的注册代码,这部分是我们希望保持活跃的部分。

    • 注释掉:鼠标、键盘、编码器、物理按键等其它输入设备的注册代码。

示例修改:
在这里插入图片描述
5️⃣添加触摸检测函数

在"lv_port_indev.c"文件中,为了添加触屏检测功能,你需要对原有的触摸检测函数touchpad_is_pressed()进行如下👇修改,以使用特定的触屏检测函数。:

// 假设原先的 touchpad_is_pressed 函数位于约209行
bool touchpad_is_pressed(void) {
    // 第212行:插入魔女开发板提供的触屏检测函数
    // 注意:这里使用XPT2046_IsPressed()是魔女开发板提供的外部函数
    // 返回值已经是 0 代表未按下,1 代表已按下,符合LVGL要求
    return XPT2046_IsPressed();

    // 第213行:原有的 return false 应该被注释掉或直接删除
    // 注释如下:
    // // return false;
}

// 其余代码...

如果你使用的是其他开发板或库(比如原子哥的STM32库),并且该库提供了不同的触屏检测接口,您只需将XPT2046_IsPressed()替换为对应的触屏检测函数名称,并确保该函数返回值逻辑与LVGL所需的逻辑相匹配(即0表示未按下,非0值表示按下)

例如,如果使用原子哥的库且触屏检测函数名为TP_IsPress(),并且它的返回值是1表示按下,0表示未按下,则代码应调整为:

bool touchpad_is_pressed(void) {
    // 使用原子哥STM32库的触屏检测函数
    return TP_IsPress();
}

🚨确保所做的修改符合您实际使用的硬件接口和函数逻辑。

6️⃣添加坐标获取函数
在"lv_port_indev.c"文件中,为了集成触屏坐标获取功能,你还需要修改坐标获取函数touchpad_get_xy(),确保LVGL能够正确读取到触摸点的坐标。

void touchpad_get_xy(lv_coord_t *x, lv_coord_t *y) {
    // 第221行:修改为调用魔女开发板提供的获取X坐标的函数
    (*x) = XPT2046_GetX(); // XPT2046_GetX()为魔女开发板中实现了X坐标获取的方法

    // 第222行:修改为调用获取Y坐标的函数
    (*y) = XPT2046_GetY(); // 同样地,XPT2046_GetY()用于获取Y坐标

    // 根据不同库或硬件,您可能需要调整这里的函数调用,确保它们返回的是当前触摸点的实际坐标值。
}

这段代码修改后,LVGL框架将能够通过调用touchpad_get_xy()来获取触屏上每次触摸事件的坐标信息。请注意,XPT2046_GetX()XPT2046_GetY()函数需要替换为是你硬件平台上正确的实现,用于读取触摸屏控制器坐标值。

7. 添加LVGL的文件引用

现在,我们已成功调整了LVGL显示和触摸功能相关的代码,接下来的步骤是将LVGL的功能实际整合到项目中,即在工程中“激活”LVGL,使其发挥作用。

1️⃣头文件包含
在主程序或相应的配置文件中,确保包含了必要的LVGL头文件。这通常涉及lvgl.h及其他之前配置的特定头文件,比如lv_port_disp.hlv_port_indev.h

#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"

2️⃣ 初始化LVGL
在项目启动初期,调用LVGL的初始化函数,设置显示驱动和输入设备。这些在主循环开始前完成:

lv_init(); // 初始化LVGL库
lv_port_disp_init(); // 初始化显示驱动
lv_port_indev_init(); // 初始化输入设备

3️⃣初始化LCD、触摸屏
同样在main函数内、 while 循环之前,调用LCD初始化函数、触摸屏初始化函数

LCD_Init();                                         // 初始化 LCD
LCD_SetDir(1);                                      // 设置LCD的显示方向:横屏
XPT2046_Init(xLCD.width, xLCD.height,  xLCD.dir);   // 初始化触摸屏

4️⃣ 创建及管理UI元素
开始创建图形界面元素,如按钮、标签、滑块等。这通常涉及到使用LVGL的API来定义和控制界面组件:

static lv_obj_t *label = lv_label_create(lv_scr_act(), NULL); // 创建一个标签
lv_label_set_text(label, "Hello, LVGL!"); // 设置标签文本

5️⃣主循环集成LVGL任务处理
在您的主循环或任务调度中,定期调用LVGL的任务处理函数,以确保UI的实时响应和更新:

while(1) {
    // 处理其他任务...
    
    // 更新LVGL任务
    lv_task_handler(); // 或使用特定的调度函数,如lv_tick_inc()
    
    // 确保系统休眠或延时,避免CPU过载
    HAL_Delay(1 - 1);// 1ms延时
}

8. LVGL 心跳、任务刷新

LVGL图形库为了保证用户界面的流畅更新和响应,引入了心跳机制(Heartbeat)和任务刷新的概念。这些机制确保了LVGL能够及时处理图形渲染、输入事件和动画更新等任务。以下是关于如何在项目中正确实现LVGL心跳与任务刷新的基本指南:

心跳机制(Heartbeat)

LVGL的心跳机制主要通过周期性的调用来维持,它负责触发内部的任务调度,从而更新UI元素和处理后台任务。心跳频率影响着UI的流畅度和响应速度,一般推荐的频率为每秒大约60次(即大约每16毫秒一次)。

实现方法:

使用系统定时器:在嵌入式系统中,可以通过配置硬件定时器中断来定期触发心跳。定时器中断服务例程(ISR)中调用lv_tick_inc()函数来模拟心跳。

🚨但要注意在很多实时操作系统(RTOS)环境中,SysTick定时器通常被操作系统本身用于基本的时间管理,比如任务调度和时间片分配。因此,直接用SysTick来驱动LVGL心跳可能会与RTOS的核心功能冲突,或者限制系统的灵活性和可扩展性。

为了实现高精度的定时控制,建议利用TIM机制生成1毫秒的周期性中断,并将此中断配置为高级别优先级。通过在中断服务程序中触发LVGL心跳时钟,确保用户界面的实时更新。实现这一功能时,可灵活选择TIM外设及编程手段,涵盖直接操作寄存器、采用STM32标准库或是手动集成HAL库等不同策略。本文照仿【快速入门 LVGL】-- 1、STM32 工程移植 LVGL 将以CubeMX工具为例,配置TIM6以实现每1毫秒的精确中断调度。

1️⃣打开CubeMX并选择您的STM32型号

  • 启动STM32 CubeMX软件,选择或创建您的项目,指定目标STM32微控制器型号。

2️⃣配置TIM6

  1. 启用TIM6: 在“Pinout & Configuration”页面左侧的外设列表中找到TIM6,点击展开。

  2. 基本定时器配置:

    • 设置Prescaler(预分频器)以得到1ms的周期。例如,如果您的STM32运行在84MHz(这是很多STM32的默认频率),您需要设置预分频器为PSC = 84-1(因为 84000000 / 84- 1 = 100kHz,即每1us触发一次更新事件)。
    • 设置Counter Mode(计数模式)Up,意味着计数器从0递增到自动重载值(Autoreload)。
    • 设置Autoreload(自动重载)值为1000-1,配合上述预分频设置达到1ms中断周期。

    在这里插入图片描述

3️⃣设置中断优先级

转到Configuration -> NVIC Settings,在中断列表中找到TIM6,点击它并设置优先级为高。您可以根据系统中的其他中断需求调整具体的优先级数值。

确保Interrupt(更新中断)被勾选,这样每当计数器达到自动重载值时就会产生中断。
在这里插入图片描述

4️⃣生成代码

点击Project Manager,然后Generate Code,选择您偏好的IDE和工程类型,让CubeMX生成代码。

5️⃣编写中断服务例程

在生成的代码中,找到stm32f4xx_hal_tim.c文件,里面会有一个空的HAL_TIM_PeriodElapsedCallback函数,这是一个弱定义的函数,需要我们重写。

我们将这个函数实现,放到main.c的最后

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM6)                     // 判断是哪个TIM产生的中断
    {
    	 // 在这里调用LVGL的心跳函数
        lv_tick_inc(1);                             // 给LVGL提供1ms的心跳时期

    }
}

6️⃣主函数中使能TIM6

确保在main.c或相应的主函数中,有代码初始化并使能TIM6

HAL_TIM_Base_Init(&htim6);
HAL_TIM_Base_Start_IT(&htim6); // 使用中断模式启动TIM6

🎊🎉🎉🎉🎉🎉🎉🎉🎉🎉🎊

恭喜你至此,关于时间精度的需求已成功解决,LVGL图形库的移植工作也圆满结束。激动人心的时刻来临,点击编译按键后,结果显示令人满意——0个错误!这意味着我们的移植不仅完成了,而且实现了无缝对接与优化。

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

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

相关文章

52.HarmonyOS鸿蒙系统 App(ArkTS)配置文件添加多个权限方法

52.HarmonyOS鸿蒙系统 App(ArkTS)配置文件添加多个权限方法 module.json5

关于修改hosts,浏览器并没有刷新生效的问题.

1.windows系统用cmd命令: ipconfig /flushdns 进行刷新.并查看本地解析是否已经刷新. 2.检查是否开了,代理,代理还是有影响的,关闭,不然不会生效 3.针对谷歌浏览器解决方案: 访问: chrome://net-internals/?#sockets 点击close idle sockets和flush socket pools,,,清…

如何将安卓手机投屏到Windows 10电脑上

诸神缄默不语-个人CSDN博文目录 我之所以要干这个事是为了用手机直播的时候在电脑上看弹幕…… 文章目录 1. 方法一:直接用Win10内置的投影到此电脑2. 方法二:用AirDroid Cast投屏到电脑上 1. 方法一:直接用Win10内置的投影到此电脑 在设置…

Flutter笔记:Widgets Easier组件库(8)使用图片

Flutter笔记 Widgets Easier组件库(8):使用图片 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress o…

小程序wx.getlocation接口如何开通?

小程序地理位置接口有什么功能? 随着小程序生态的发展,越来越多的小程序开发者会通过官方提供的自带接口来给用户提供便捷的服务。但是当涉及到地理位置接口时,却经常遇到申请驳回的问题,反复修改也无法通过,给的理由…

Microsoft.NET 框架程序设计 —— 共享程序集

文件版本是一个很难解决的问题。实际上,如果仅仅在一个文件中将其某一位从0改变到1、或者从1改变到0,我们便不能绝对保证使用原来文件的代码和它使用新版文件时的行为一样。这是因为许多应用程序都会有意或者无意地引入bug。如果一个文件的后续版本修复了一个bug,应用程序便…

PotatoPie 4.0 实验教程(34) —— FPGA实现摄像头图像二值化腐蚀效果

链接直达 https://item.taobao.com/item.htm?ftt&id776516984361 图像二值化腐蚀处理有什么作用? 图像二值化腐蚀处理在图像处理中起到了以下作用: 物体分割与提取:在图像二值化之后,通过腐蚀操作可以消除噪声、连接相邻的…

搭建Kafka源码环境并测试

文章目录 一、前言二、环境准备三、环境搭建3.1 JDK 环境搭建3.2 Scala 环境搭建3.2.1 配置 Scala 环境变量3.2.2 验证 3.3 Gradle 环境搭建3.3.1 配置 Gradle 环境变量3.3.2 验证 3.4 Zookeeper 环境搭建3.4.1 配置 Zookeeper 环境变量3.4.2 验证 3.5 Kafka 源码搭建3.5.1 导入…

44. UE5 RPG 初始化敌人的属性

在正常的游戏中,我们应该考虑如何去初始化角色属性,并且要给角色分好类型。比如,在我们游戏中,我们如何去初始化小兵的属性,并且还要实现小兵随着等级的增长而增加属性。而且就是小兵也有类型的区分,比如我…

使用qemu调试NVME driver

参考nvme驱动相关的博客,可以使用qemu buildroot进行nvme驱动的流程debug。 一、QEMU编译 首先需要编译qemu,可以参考QEMU编译。wget下载最新版本的QEMU,编译之前,最好检查下依赖包是否安装,避免安装过程出现各种错…

c++容器与算法概述

容器与算法 每个标准库容器都提供了begin() end() 函数&#xff0c;分别返回容器的头部位置和尾部位置。 I/O 流 对于自定义的类型&#xff1a; struct Entry {std::string name;int number;};如果需要使用标准输出需要重载<< 运算符&#xff0c;特别注意&#xff1a…

环形链表的经典问题

环形链表 环形链表的介绍链表中是否带环返回链表开始入环的第一个节点 本文主要介绍如何判断一个链表是否是环形链表&#xff0c;以及如何得到环形链表中的第一个节点。 环形链表的介绍 环形链表是一种链表数据结构&#xff0c;环形链表是某个节点的next指针指向前面的节点或指…

微软如何打造数字零售力航母系列科普05 - Azure中计算机视觉的视觉指南

Azure中计算机视觉的视觉指南 什么是计算机视觉&#xff1f;如何使用Microsoft Azure将计算机视觉功能集成到应用程序和工作流中&#xff1f; 作者&#xff1a;Nitya Narasimhan 编辑&#xff1a;数字化营销工兵 •11分钟阅读 什么是计算机视觉&#xff1f;如何使用Microso…

在树莓派安装 rpi-imager

步骤 安装 sudo apt install rpi-imager 我没有更新镜像源&#xff0c; 但是能安装完&#xff0c; 只是花的时间旧点。 烧写镜像 因为我是没有桌面的树莓派系统&#xff0c; 所以我这里执行的指令是不需要显示图形化界面的 man rpi-imager ## man指令查看说明 查看帮助手…

综合性练习(后端代码练习4)——图书管理系统

目录 一、准备工作 二、约定前后端交互接口 1、需求分析 2、接口定义 &#xff08;1&#xff09;登录接口 &#xff08;2&#xff09;图书列表接口 三、服务器代码 &#xff08;1&#xff09;创建一个UserController类&#xff0c;实现登录验证接口 &#xff…

服务运营 | 精选:用药难?用药贵?运筹学与统计学视角下的药物研发与管理

作者设计了一个多阶段博弈论模型来针对罕见病的不同补贴方案&#xff0c;分析政府、联盟、制药商和患者之间的相互作用。 制药商补贴为 α C \alpha C αC&#xff0c;其中 C C C是研发成本&#xff0c; α ∈ [ 0 , 1 ) \alpha \in [0,1) α∈[0,1)是政府总成本的比例。患者补…

vue3 依赖-组件tablepage-vue3 项目公共配置封装

github求⭐ 可通过github 地址和npm 地址查看全部内容 vue3 依赖-组件tablepage-vue3说明文档&#xff0c;列表页快速开发&#xff0c;使用思路及范例-汇总 vue3 依赖-组件tablepage-vue3说明文档&#xff0c;列表页快速开发&#xff0c;使用思路及范例&#xff08;Ⅰ&#…

模型智能体开发之metagpt-多智能体实践

参考&#xff1a; metagpt环境配置参考模型智能体开发之metagpt-单智能体实践 需求分析 之前有过单智能体的测试case&#xff0c;但是现实生活场景是很复杂的&#xff0c;所以单智能体远远不能满足我们的诉求&#xff0c;所以仍然还需要了解多智能体的实现。通过多个role对动…

Android11适配

一、分区存储 1.背景 Android 11 进一步增强了平台功能&#xff0c;为外部存储设备上的应用和用户数据提供了更好的保护。作为这项工作的一部分&#xff0c;平台引入了进一步的改进&#xff0c;以简化向分区存储的转换。 为了让用户更好地控制自己的文件&#xff0c;保护用户…

【华为】华为防火墙双机热备

【华为】华为防火墙双机热备 实验需求实验拓扑配置FW5-M前骤单臂路由和VRRP划分防火墙基本区域部署HRP&#xff08;华为心跳协议&#xff09; FW6-B前骤单臂路由和VRRP划分防火墙基本区域部署HRP&#xff08;华为心跳协议&#xff09; LSW2PC NATSNAT &#xff1a;Easy IPDNAT&…