STM32F407移植LVGL基于RT-Thread和无操作系统版本

news2024/10/6 4:11:31

文章目录

  • 一、无操作系统
    • 1.源码获取:
    • 2.输出设备配置(屏幕配置)
      • 几个关键函数
        • 屏幕初始化函数:
        • 显示刷新(画点)函数
    • 3.输入配置(触摸)
    • 4.提供时基
  • 二、RT-Thread
    • 1.新建工程
    • 2.添加软件包,屏幕相关文件以及添加编译路径
    • 3.输出设备配置(屏幕配置)
    • 4.输入设备配置(Touch设备配置)

LVGL移植

前言:本次LVGL移植分为有操作系统和无操作系统两种方式。操作系统使用的是RT-Thread

硬件使用野火STM32F407霸天虎开发板,屏幕使用nt35510显示IC,触摸使用gt917s芯片

一、无操作系统

开发环境使用wsl环境下的VScode+arm-none-eabi-gcc编译+openocd烧录+arm-none-eabi-gdb调试,具体可以参考https://blog.csdn.net/weixin_51954217/article/details/129350873?spm=1001.2014.3001.5501

1.源码获取:

LVGL核心图形库github地址:https://github.com/lvgl/lvgl

解压后目录如下:红框圈起来的文件是必须的文件,其他的可删可不删

image-20230414213536492

将文件夹复制到工程目录下

image-20230414213157495

我们主要修改lvgl/examples/porting文件夹下的lv_port_disp_templete.c/.h文件和lv_port_indev_templete.c/.h文件以及lvgl文件夹下的lv_conf_templete.h文件

这几个文件的作用如下:

  • lv_port_disp_templete.c/.h:输出设备接口文件,在这里使用的是LCD屏幕,将屏幕的初始化函数以及画点函数对接起来,使LVGL库能够画图。
  • lv_port_indev_templete.c/.h:输入设备接口文件,在这里使用的是touch电容触摸,将触摸反馈与LVGL的接口对接,使LVGL能够对触摸做出反应。

2.输出设备配置(屏幕配置)

  • lv_port_disp_templete.c/.h文件分别重命名为lv_port_disp.c/.h

  • 将这两个文件里的条件编译#if 0改为#if 1表示启用这两个文件

  • lv_port_disp_templete.h改名为lv_port_disp.h后记得包含的头文件也改成lv_port_disp.h。

  • 包含自己的显示屏头文件lcd.h

  • 修改显示屏的水平宽度和垂直宽度为实际屏幕的尺寸,我的水平方向450,垂直方向800

image-20230414215659464

几个关键函数

  • void lv_port_disp_init(void)//通过调用该函数初始化屏幕

  • static void disp_init(void)//将屏幕的初始化代码放在里面

  • static void disp_flush(lv_disp_t * disp_drv, const lv_area_t * area, lv_color_t * px_map)//我们需要补全显示刷新(画点)函数


屏幕初始化函数:

我的屏幕初始化函数为LCD_Init(),在lcd.h中,作用是初始化屏幕相关的IO口和屏幕驱动方式FSMC的初始化,以及屏幕初始化参数的写入等。

static void disp_init(void)
{
    /*You code here*/
    LCD_Init();
}

显示刷新(画点)函数

其中LCD_SetPointPixel函数用于将屏幕x , y点设置为十六位的color这个颜色

static void disp_flush(lv_disp_t * disp_drv, const lv_area_t * area, lv_color_t * px_map)
{
    if(disp_flush_enabled) {
        /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/

        int32_t x;
        int32_t y;
        for(y = area->y1; y <= area->y2; y++) {
            for(x = area->x1; x <= area->x2; x++) {
                /*Put a pixel to the display. For example:*/
                /*put_px(x, y, *px_map)*/
                /* 下面自己的代码 */
                uint16_t color=0;
                color |= px_map->red<<11;
                color |= px_map->green<<5;
                color |= px_map->blue;
                LCD_SetPointPixel(x, y, color);
                /* 上面是自己的代码 */
                px_map++;
            }
        }
    }

注意:LVGL有三种刷新方式,都是新建数组的方式缓存要显示的内容

方式1和方式2都是新建一个屏幕长度*10的数组存储数据,只不过方式2新建了两个。方式3位屏幕长度*屏幕宽度*2的数组,因为方式3太大了,会出现超内存的情况,需要将方式3注释掉,再在方式1 2 中选择一个,将另一个注释掉

image-20230414233121757

image-20230414232748046

至此,LVGL有关显示的函数就已经配置好了,只需要在主函数中调用lv_port_disp_init即可初始化屏幕。


3.输入配置(触摸)

输入设备有很多种,比如鼠标、触摸IC等等,可以把不用的方式的代码去掉,只保留用到的代码。

输入设备相关的函数在lv_port_indev_templete.c/.h文件中

  • 与输入设备文件相同,将#if 0 改为#if1

  • 将文件名中的_templete去掉,文件名改为lv_port_indev.c/.h

  • 包含自己的touch设备头文件touch.h

  • 因为只用到了touch设备,所以可以将mouse和encode相关代码删除

    /**
     * @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.h"
    #include "touch.h"
    
    /*********************
     *      DEFINES
     *********************/
    
    /**********************
     *      TYPEDEFS
     **********************/
    
    /**********************
     *  STATIC PROTOTYPES
     **********************/
    
    static void touchpad_init(void);    //Initialize your touchpad
    static void touchpad_read(lv_indev_t * indev, lv_indev_data_t * data);  //Read the touchpad
    static bool touchpad_is_pressed(void);  //Return true is the touchpad is pressed
    static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y);    //Get the x and y coordinates if the touchpad
    
    
    
    /**********************
     *  STATIC VARIABLES
     **********************/
    lv_indev_t * indev_touchpad;
    
    /**********************
     *      MACROS
     **********************/
    
    /**********************
     *   GLOBAL FUNCTIONS
     **********************/
    
    void lv_port_indev_init(void)
    {
        /*------------------
         * Touchpad
         * -----------------*/
    
        /*Initialize your touchpad if you have*/
        touchpad_init();
    
        /*Register a touchpad input device*/
        indev_touchpad = lv_indev_create();
        lv_indev_set_type(indev_touchpad, LV_INDEV_TYPE_POINTER);
        lv_indev_set_read_cb(indev_touchpad, touchpad_read);
    }
    
    /**********************
     *   STATIC FUNCTIONS
     **********************/
    
    /*------------------
     * Touchpad
     * -----------------*/
    
    /*Initialize your touchpad*/
    static void touchpad_init(void)
    {
        /*Your code comes here*/
        GTP_Init_Panel();
    }
    
    /*Will be called by the library to read the touchpad*/
    static void touchpad_read(lv_indev_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*/
        //实现touchpad_is_pressed函数
        if(GTP_Scan(0))
        {
            return true;
        }
        
        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*/
        
        (*x) = tp_dev.x[0];
        (*y) = tp_dev.y[0];
    }
    
    #else /*Enable this file at the top*/
    
    /*This dummy typedef exists purely to silence -Wpedantic.*/
    typedef int keep_pedantic_happy;
    #endif
    

关键函数

  • static void touchpad_init(void) 将自己的touch初始化函数放在里面
  • static bool touchpad_is_pressed(void) 补全该函数,使touch设备按下时返回true
  • static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y) 补全该函数使其能够返回touch坐标的函数

函数实现:

  • static void touchpad_init(void)
static void touchpad_init(void)
{
    /*Your code comes here*/
    GTP_Init_Panel();
}

将自己的touch.h中的touch初始化函数放在里面

  • static bool touchpad_is_pressed(void)
static bool touchpad_is_pressed(void)
{
    /*Your code comes here*/
    //实现touchpad_is_pressed函数
    if(GTP_Scan(0))
    {
        return true;
    }
    
    return false;
}

实现一个touch扫描函数,当电容屏被触摸时返回真值

  • static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
    /*Your code comes here*/
    
    (*x) = tp_dev.x[0];
    (*y) = tp_dev.y[0];
}

将touch设备获取的坐标返回给x,y


4.提供时基

与操作系统类似,LVGL也需要时基,相当于LVGL的心跳,API为LV_ATTRIBUTE_TICK_INC void lv_tick_inc(uint32_t tick_period)

需要将其放在定时器中断函数里,多少毫秒产生一次中断就在参数里填写几。这里将其放在SysTick系统滴答定时器的中断函数里,就不需要为其开一个单独的定时器了

image-20230414221914381

二、RT-Thread

开发环境使用RT-Thread Studio

参考RT-Thread官方LVGL移植步骤https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/packages-manual/lvgl-docs/indev-touch-port

1.新建工程

首先基于芯片新建一个RT-Thread标准版工程

image-20230414223015280

2.添加软件包,屏幕相关文件以及添加编译路径

添加LVGL软件包与触摸芯片软件包

image-20230414223203823

ctrl+s保存后等待软件包应用到工程中,应用完成后可以在packages目录下看到新导入的lvgl与触摸ic软件包

image-20230414224218847

可以看到LVGL软件包中没有lv_port_disp_templete.c/.hlv_port_indev_templete.c/.h文件,需要从文件目录中复制过来

image-20230414224336031

右键LVGL目录->打开资源所在目录,将examples->porting文件夹下的lv_port_disp_templete.c/.hlv_port_indev_templete.c/.h文件复制到applications目录下

image-20230414224543662

将自己的屏幕相关代码拷贝到工程的applications目录下,我在applications目录下新建了app_driver文件夹,在该文件夹下又新建了inc与src文件夹分贝存放头文件与源文件。将刚才复制的lv_port_disp_templete.c/.hlv_port_indev_templete.c/.h文件也分别改名后放到inc与src目录下。

注意:因为我们直接复制的文件到工程中,所以编译器中没有保存我们复制的文件的路径,编译的时候会存在找不到文件的情况,需要将路径添加到工程路径中

方法:image-20230414225219441

image-20230414225246353

image-20230414225324296

添加完成后应用即可

3.输出设备配置(屏幕配置)

  • lv_port_disp_templete.c/.h文件分别重命名为lv_port_disp.c/.h

  • 将这两个文件里的条件编译#if 0改为#if 1表示启用这两个文件

  • lv_port_disp_templete.h改名为lv_port_disp.h后记得包含的头文件也改成lv_port_disp.h。

  • 包含自己的显示屏头文件lcd.h

  • 修改显示屏的水平宽度和垂直宽度为实际屏幕的尺寸,我的水平方向450,垂直方向800

步骤与无操作系统的一样,步骤吧参考无操作系统的,因为屏幕没有接入rtthread的设备框架,后期有时间会接入设备框架。

4.输入设备配置(Touch设备配置)

touch设备接入参考rtthread官方文档进行的修改,因为gt917s这个软件包对接了rtthread的touch设备框架,所以在这里我们需要使用rtthread的touch设备框架的api

lvgl中原先需要我们实现的touchpad_init(); static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)都用不到被我注释掉了。参考官方教程后我移植的程序如下,实测是可以运行的。注意LVGL版本是8.2.0。

注意:需要在rtthread设置中打开i2c1并使能touch设备的中断(如下图所示),在board.h中取消掉i2c1的注释,并且指定i2c的接口为touch芯片所用到的i2c接口

image-20230414231759292

image-20230414231938102

/**
 * @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.h"
#include "lvgl.h"
#include "touch.h"
#include "rtdbg.h"
#include "gt917s.h"
#include "rtdevice.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 VARIABLES
 **********************/
lv_indev_t * indev_touchpad;


/**********************
 *      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
 * -----------------*/
rt_touch_t touch_dev;
static int lv_hw_touch_init(void)
{
    struct rt_touch_config cfg;

    cfg.dev_name = "i2c1";/* 使用的I2C设备名 */
//#ifdef BSP_USING_TOUCH_GT917S
    rt_hw_gt917s_init("touch", &cfg); /* 软件包提供的初始化函数 */
//#endif /* BSP_USING_TOUCH_FT6X36 */

    touch_dev = rt_device_find("touch");
    if (rt_device_open(touch_dev, RT_DEVICE_FLAG_RDONLY) != RT_EOK)
    {
        LOG_E("Can't open touch device:%s", "touch");
        return -RT_ERROR;
    }

    return RT_EOK;
}

INIT_COMPONENT_EXPORT(lv_hw_touch_init);
/*Initialize your touchpad*/
//static void touchpad_init(void)
//{
    /*Your code comes here*/
//    GTP_Init_Panel();
//    rt_hw_gt917s_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;
    struct rt_touch_data *read_data;
    /* 可以将内存分配这个步骤改为全局变量,以提高读取效率 */
    read_data = (struct rt_touch_data *)rt_calloc(1, sizeof(struct rt_touch_data));

    rt_device_read(touch_dev, 0, read_data, 1);

    /* 如果没有触摸事件,直接返回 */
    if (read_data->event == RT_TOUCH_EVENT_NONE)
        return;

    /* 这里需要注意的是:触摸驱动的原点可能和LCD的原点不一致,所以需要我们进行一些处理 */
//#ifdef BSP_USING_TOUCH_FT6X36
    data->point.x = read_data->y_coordinate;
    data->point.y = 800 - read_data->x_coordinate;
//#endif /* BSP_USING_TOUCH_FT6X36 */

    if (read_data->event == RT_TOUCH_EVENT_DOWN)
        data->state = LV_INDEV_STATE_PR;
    if (read_data->event == RT_TOUCH_EVENT_MOVE)
        data->state = LV_INDEV_STATE_PR;
    if (read_data->event == RT_TOUCH_EVENT_UP)
        data->state = LV_INDEV_STATE_REL;
}

/*Return true is the touchpad is pressed*/
//static bool touchpad_is_pressed(void)
//{
    /*Your code comes here*/
//    if(GTP_Scan(0))
//    {
//        return true;
//    }
//    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*/

//    (*x) = tp_dev.x[0];
//    (*y) = tp_dev.y[0];
//}

//static void input_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
//{
//    struct rt_touch_data *read_data;
//    /* 可以将内存分配这个步骤改为全局变量,以提高读取效率 */
//    read_data = (struct rt_touch_data *)rt_calloc(1, sizeof(struct rt_touch_data));
//
//    rt_device_read(touch_dev, 0, read_data, 1);
//
//    /* 如果没有触摸事件,直接返回 */
//    if (read_data->event == RT_TOUCH_EVENT_NONE)
//        return;
//
//    /* 这里需要注意的是:触摸驱动的原点可能和LCD的原点不一致,所以需要我们进行一些处理 */
#ifdef BSP_USING_TOUCH_FT6X36
//    data->point.x = read_data->y_coordinate;
//    data->point.y = 800 - read_data->x_coordinate;
#endif /* BSP_USING_TOUCH_FT6X36 */
//
//    if (read_data->event == RT_TOUCH_EVENT_DOWN)
//        data->state = LV_INDEV_STATE_PR;
//    if (read_data->event == RT_TOUCH_EVENT_MOVE)
//        data->state = LV_INDEV_STATE_PR;
//    if (read_data->event == RT_TOUCH_EVENT_UP)
//        data->state = LV_INDEV_STATE_REL;
//}


#else /*Enable this file at the top*/

/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif

注意在gt917s.c中有int8_t和int16_t两种类型会报错,需要改为rt_uint8_t 和 rt_uint16_t

#include "lvgl/lvgl.h"需要改为#include “lvgl.h”

image-20230414232315177

除此之外肯定还有许多没有涉及到的小错误,需要自己根据报错修改。最后展示一下效果

在这里插入图片描述

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

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

相关文章

3.5 二维随机变量函数的分布

学习目标&#xff1a; 要学习二维随机变量的分布&#xff0c;我可能会遵循以下步骤&#xff1a; 了解基本概念&#xff1a;我会开始学习二维随机变量、联合概率密度函数、边缘概率密度函数、条件概率密度函数、期望值和方差等基本概念&#xff0c;以确保我对这些概念有一个牢固…

elasticsearch 跨索引联合多条件查询

文章目录Elasticsearch需求使用版本联合索引多条件查询示例相关API相关资料Elasticsearch Elasticsearch 是一个免费且开放的分布式搜索和分析引擎。适用于包括文本、数字、地理空间、结构化和非结构化数据等在内的所有类型的数据。Elasticsearch 在 Apache Lucene 的基础上开…

十分钟玩转3D绘图:WxGL完全手册

文章目录1 简介2 安装3 快速体验3.1 熟悉的风格3.2 Colorbar3.3 光照效果3.4 让模型动起来3.5 定制着色器3.6 三维曲面重建3.7 生成动画或视频文件4 在其他GUI库中使用WxGL4.1 与wxPython集成4.2 与PyQt集成5 API Reference5.1 常量5.2 函数wxgl.font_listwxgl.color_listwxgl.…

Java--反射

目录 反射 什么是反射&#xff1f; Class类 动态加载 小结 访问字段 获取字段值 设置字段值 练习 小结 调用方法 调用方法 调用静态方法 调用非public方法 多态 练习 小结 调用构造方法 小结 获取继承关系 获取父类的Class 获取interface 继承关系 小…

遗传算法优化深度信念网络DBN的分类预测,GA-DBN分类预测

目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) 遗传算法的原理 遗传算法优化深度信念网络DBN的分类识别 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,本文用DBN提取特征,遗传…

如何在DevOps中进行API生命周期管理?

引言 随着DevOps理念在中国企业当中的普及和发展&#xff0c;中国企业DevOps落地成熟度不断提升&#xff0c;根据中国信通院的数据已有近6成企业向全生命周期管理迈进。而在研发全生命周期管理之中&#xff0c;API管理的地位愈发显得重要。随着API数量的大幅增长&#xff0c;也…

Java多线程编程—wait/notify机制

文章目录1. 不使用wait/notify机制通信的缺点2. 什么是wait/notify机制3. wait/notify机制原理4. wait/notify方法的基本用法5. 线程状态的切换6. interrupt()遇到方法wait()7. notify/notifyAll方法8. wait(long)介绍9. 生产者/消费者模式10. 管道机制11. 利用wait/notify实现…

【操作系统】半小时写一个微型操作系统-写一个启动扇区并且导入到软盘镜像中

一.什么是启动扇区 我们使用软盘来启动操作系统时&#xff0c;系统首先就是从软盘的第一个扇区中开始读取数据&#xff0c;也就是第0面&#xff0c;0磁道的第0个扇区&#xff0c;软盘的每个扇区为512个字节的大小&#xff0c;如果最后两个字节为0xaa55&#xff08;当BIOS看到这…

Java多线程基础面试总结(一)

进程、线程和协程 进程、线程和协程 进程 进程是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff0c;因此进程是动态的。系统运行一个程序即是一个进程从创建、运行到消亡的过程。 在Java中&#xff0c;当我们启动main函数其实就是启动了一个JVM进程&…

【Linux】全新服务器Centos7环境搭建和安装

1、简介 最近服务器重装后,环境啥的则需要从头全部搞一遍,于是开始搞起环境的配置和安装 2、环境配置安装 前期准备 给目录文件加文件传输权限(发现无法上传文件,于是增加权限 $ chmod 766 /home/lj/ 配置DNS服务 #配置DNS服务,如果没有8.8.8.8需要添加 cat /etc/re…

WRF模式与Python融合技术在多领域中的应用及精美绘图教程

当今从事气象及其周边相关领域的人员&#xff0c;常会涉及气象数值模式及其数据处理&#xff0c;无论是作为业务预报的手段、还是作为科研工具&#xff0c;掌握气象数值模式与高效前后处理语言是一件非常重要的技能。WRF作为中尺度气象数值模式的佼佼者&#xff0c;模式功能齐全…

QML控件--Dialog

文章目录一、控件基本信息二、控件使用三、属性成员四、成员函数五、信号一、控件基本信息 Import Statement&#xff1a;import QtQuick.Controls 2.14 Since&#xff1a;Qt 5.8 Inherits&#xff1a;Popup 二、控件使用 Dialog&#xff1a; 是一个弹出窗口&#xff0c;继承…

项目打包发布流程

---》》》项目打包发布 1.编译并构建项目 2.部署 npm i npm run build scp2&#xff1a;需要写代码 ---》》》 后续有空更新&#xff1a;赋几个链接&#xff1a; Jenkins官网 nullhttps://www.jenkins.io/zh/一文详解Jenkins的安装与配置Jenkins是一个基于Java开发的开源…

【SpringMVC】10—其他概念

⭐⭐⭐⭐⭐⭐ Github主页&#x1f449;https://github.com/A-BigTree 笔记链接&#x1f449;https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以&#xff0c;麻烦各位看官顺手点个star~&#x1f60a; 如果文章对你有所帮助&#xff0c;可以点赞&#x1f44d;…

2023年Web3的五大趋势

Web3 这个词有时被称为 "去中心化的互联网"&#xff0c;涵盖了一些重要的互联网发展趋势。Web3 的愿景是创造一个不受大公司控制的互联网&#xff0c;如Alibaba、baidu、Google和Facebook&#xff0c;这些公司制定了互联网的大部分规则&#xff0c;掌控着我们今天可以…

HyperWorks2021软件安装教程

下载软件 https://www.xsoftnet.com/share/a0004MWyQAg9r.html产品介绍&#xff1a; HyperWorks一款功能强大的开放式架构仿真软件。拥有先进的技术以及高性能、高效和创新的产品&#xff0c;为用户提供了设计、仿真和制造等服务。支持电磁分析设计、材料建模制造、多物理场分…

学校的地下网站(学校的地下网站1080P高清)

这个问题本身就提得有问题&#xff0c;为什么这么说&#xff0c;这是因为YouTube本身就不是一个视频网站或者说YouTube不是一个传统的视频网站&#xff01;&#xff01;&#xff01; YouTube能够一家独大&#xff0c;可不仅仅是因为有了Google 这个亲爹&#xff0c;还有一点&am…

Flutter Web 开发实践与优化

一,Flutter Web架构 目前,除了可以支持Android、iOS移动跨平台开发之外,Flutter还支持macOS、Windows、Linux和Web等多个跨平台的开发。可以说,作为一款先进的跨平台开发框架,Flutter已经真正意义上实现了“一次编写,处处运行”的美好愿景。 众所周知,Dart 语言存在之…

【建议收藏】数据库 SQL 入门——事务(内附演示)

文章目录&#x1f4da;引言&#x1f4d6;事务&#x1f4d1;事务的概念&#x1f4d1;事务操作&#x1f516;查看与设置事务提交方式&#x1f516;提交事务与回滚事务&#x1f4d1;事务的特性&#x1f4d1;并发事务问题&#x1f4d1;事务隔离级别&#x1f4cd;总结&#x1f4da;引…

8.基于拉丁超立方法的风光场景生成与削减

matlab代码&#xff1a;基于拉丁超立方法的风光场景生成与削减 摘要&#xff1a;与蒙特卡洛法不同&#xff0c;拉丁超立方采样改进了采样策略能够做到较小采样规模中获得较高的采样精度&#xff0c;属于分层抽样技术&#xff0c;设定风光出力遵从正态分布normrnd&#xff0c;从…