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

嵌入式 LVGL移植到STM32F4

目录

LVGL简介

1、特点

2、LVGL的硬件要求 

3、相关网站 

4、LVGL源码下载 

5、LVGL移植要求 

5.1 移植过程-添加源码 

2、更改接口文件

 3、显示实现

4、添加外部中文字体的方法

5、编译下载后有几种情况 

6、调用显示 

6、GUI-Guider使用

6.1 安装软件

6.2 使用软件 

6.3 移植到STM32 


LVGL简介

  LittlevGL是一个免费的开源图形库,提供了创建嵌入式GUI所需的一切,具有易于使用的图形元素、漂亮的视觉效果和低内存占用。

1、特点

  1. 强大的构建模组:按钮、图表、列表、滑块、图像等
  2. 先进的图形:动画、反锯齿、半透明、平滑滚动
  3. 多样的输入设备:触摸板、鼠标、键盘、编码器等
  4. 多显示器支持:支持同时使用多个TFT或单色显示器
  5. 多语言支持:格式文字编码
  6. 硬件无关:可用于任UTF-8意微控制器或显示器
  7. 可裁剪:用于小内存(64 KB FLASH,16 KB RAM)操作
  8. 外部支持:操作系统、外部存储以及GPU
  9. 单帧缓存:即可实现先进的图形效果
  10. C语言编写:以最大化兼容(C++ 兼容)
  11. 模拟器:无需嵌入式硬件就可以在电脑上开始GUI设计
  12. 文档:在线及离线
  13. 免费开源:基于MIT协议

2、LVGL的硬件要求 

3、相关网站 

  1. LVGL官网:LVGL - Light and Versatile Embedded Graphics Library 
  2. LVGL代码库地址(Simulator、Source、Examples、Esp32、MicroPython):LVGL · GitHub 
  3. LVGL源码下载地址:GitHub - lvgl/lvgl: Embedded graphics library to create beautiful UIs for any MCU, MPU and display type. It's boosted by a professional yet affordable drag and drop UI editor, called SquareLine Studio. 

4、LVGL源码下载 

在源码链接中下载一份源码,LVGL已经更新迭代了很多个版本,这里我们选择8.0.1版本来移植。

 注意:不同版本之间有很大的不同,尽量使用与本文相同的版本,否则不予解释。

下载后得到的目录如下:

 

源码各文件作用

  1. github:github的配置文件,忽略即可。
  2. docs:说明文档。
  3. examples:示例代码。
  4. scripts:配置脚本,Linux平台会用到,Windows忽略即可。
  5. src:源代码。
  6. tests:测试代码。

5、LVGL移植要求 

STM32工程,该工程应具备功能:

LCD显示(必备)

  1. TOUCH触摸(可选)
  2. DMA刷屏(可选)
  3. 内存管理(可选)
  4. 操作系统(可选)

5.1 移植过程-添加源码 

在工程目录下创建LVGL文件夹,

接着, 将LVGL的源码目录(lvgl-8.0.1\src)复制到本工程中的LVGL目录中

 接下来,将LVGL的驱动接口文件目录(lvgl-8.0.1\examples\porting)复制到本工程中的LVGL文件夹中。其中共六个文件,disp为显示接口驱动文件(LCD),fs为文件系统接口驱动文件(FATFS),indev为输入设备接口驱动文件(TOUCH)

接着, 将LVGL源码中(lvgl-8.0.1)的lv_conf_template.h更名为lv_conf.h,随后将其与lvgl.h一同拷贝到本地工程中的LVGL目录下;

 

接着, 打开工程,在工程的目录结构中添加二个文件夹LVGL_SRC和LVGL_PORT,并把源码添加到其中。(可根据需要进行裁剪)。

 

 

添加port文件

 

 不知道就全部都添加。本示例只使用disp这个显示的模板。

 接着,添加源码头文件路径;

 如果工程中没有内存管理,则需要修改启动文件中的堆栈。根据官方推荐我们可以把堆栈修改为4K,假如使用的功能比较多,还需要再适当增大;

 LVGL的源码需要C99的支持,否则编译无法通过;

 next,编译工程

 

 双击错误定位到错误位置发现,该代码包含的头文件路径层级错误,根据目录层级修改。(原来是../../lv_conf,更改为../ lv_conf)

 打开lv_conf文件中的条件编译。lv_conf的条件编译没有打开,去到此文件下打开该文件修改保存即可;

 编译。如果出现以下错误:

 只剩3个错误了,原因是没有添加主题源文件(..\LVGL\src\extra\themes\default)。把下图中的文件添加到工程。

如果出现以下错误:

 不这是因为没有添加控件的源文件,默认所有控件是使能状态的(lv_conf.h),我们把这些源文件(src\extra\widgets目录下)都添加到我们的工程中(如果在添加src文件时已经全部添加则不会出现这些错误)。

 

 最终编译没有错误了。

 移植成功了,但是还显示不了,我们还需要去实现显示的相关接口。

2、更改接口文件

默认lv_port_disp_templ.c和lv_port_disp_templ.h的条件编译是关闭的,我们需要把他打开并修改包含目录层级。

 更改lv_port_disp_templ.c 文件中lv_port_disp_init驱动函数。此函数提供了三种写缓存方式,保留其中一种即可,本示例采用方式二;

方式一:单缓存显示(10行),主控内存较小时选用此方式。

方式二:双缓存显示(两个10行),此方式支持DMA交替传输,缓存区越大,显示效果越好(有条件两个满屏缓存)。

方式三:双满屏缓存显示,相当于有条件的方式二

注释方式一和方式三,更改第二种方式如下:

 

 方式二更改如下:

 

 

更改屏幕大小:

 

 

添加DMA实现代码,并在disp_init函数中调用DMA的初始化函数(如果不使用DMA,disp_flush函数中只需要保留LCD_Color_Fill、lv_disp_flush_ready这两个函数即可)。注意添加需要的头文件。如#include "lcd.h"

  1. 添加一个全局变量static lv_disp_drv_t *disp_drv_p;

 把以下代码添加到lv_port_disp_templ.c,

static void DisPlay_SPI_DMA_Init()
{DMA_InitTypeDef  DMA_InitStructure	= {0};NVIC_InitTypeDef NVIC_InitStruct	= {0};RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); //DMA1时钟使能DMA_DeInit(DMA1_Stream7);while(DMA_GetCmdStatus(DMA1_Stream7) != DISABLE) {}  //等待DMA可配置/* 配置 DMA Stream */DMA_InitStructure.DMA_Channel 				= DMA_Channel_0;  				//通道选择DMA_InitStructure.DMA_PeripheralBaseAddr 	= (unsigned int)&SPI3->DR; 		//DMA外设地址DMA_InitStructure.DMA_Memory0BaseAddr 		= (unsigned int)buf_2_1;		//DMA 存储器0地址DMA_InitStructure.DMA_DIR 					= DMA_DIR_MemoryToPeripheral;	//存储器到外设模式DMA_InitStructure.DMA_BufferSize 			= sizeof(buf_2_2);				//数据传输量DMA_InitStructure.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;	//外设非增量模式DMA_InitStructure.DMA_MemoryInc 			= DMA_MemoryInc_Enable;			//存储器增量模式DMA_InitStructure.DMA_PeripheralDataSize 	= DMA_PeripheralDataSize_Byte;	//外设数据长度:8位DMA_InitStructure.DMA_MemoryDataSize 		= DMA_MemoryDataSize_Byte;		//存储器数据长度:8位DMA_InitStructure.DMA_Mode 					= DMA_Mode_Normal;				//使用普通模式DMA_InitStructure.DMA_Priority 				= DMA_Priority_High;			//中等优先级DMA_InitStructure.DMA_FIFOMode 				= DMA_FIFOMode_Disable;			//不使用fifoDMA_InitStructure.DMA_FIFOThreshold 		= DMA_FIFOThreshold_Full;		//fifo全容量DMA_InitStructure.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;		//存储器突发单次传输DMA_InitStructure.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;	//外设突发单次传输DMA_Init(DMA1_Stream7, &DMA_InitStructure);									//初始化DMA StreamSPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE); // SPI3使能DMA发送NVIC_InitStruct.NVIC_IRQChannel = DMA1_Stream7_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStruct);DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, ENABLE);DMA_Cmd(DMA1_Stream7, DISABLE);
}/*********************************************************************************************************
* 函 数 名 : DisPlay_SPI_DMA_Enable
* 功能说明 : 配置DMA并启动一次传输
* 形    参 : buf:需要搬运的数据的指针;size:搬运的数据量
* 返 回 值 : 无
* 备    注 : 无
*********************************************************************************************************/ 
void DisPlay_SPI_DMA_Enable(void *buf, unsigned int size)
{DMA1_Stream7->CR &= ~(0x01);while((DMA1_Stream7->CR&0X1)){}DMA1_Stream7->M0AR = (unsigned int)buf;DMA1_Stream7->NDTR = size;DMA1_Stream7->CR |= (0x01);	
}
/*********************************************************************************************************
* 函 数 名 : DMA1_Stream7_IRQHandler
* 功能说明 : DMA1_Stream7发送完成中断
* 形    参 : 无
* 返 回 值 : 无
* 备    注 : 无
*********************************************************************************************************/ 
void DMA1_Stream7_IRQHandler(void)
{if(DMA_GetITStatus(DMA1_Stream7, DMA_IT_TCIF7) != RESET)//if(DMA1->HISR & (1<<27)){DMA_ClearITPendingBit(DMA1_Stream7, DMA_IT_TCIF7);//DMA1->HIFCR |= (1<<27);LCD_CS = 1;SPI3->DR;	lv_disp_flush_ready(disp_drv_p);	/* tell lvgl that flushing is done */}
}

在disp_init函数中调用DMA的初始化函数。

 修改disp_flush函数

/* Flush the content of the internal buffer the specific area on the display* You can use DMA or any hardware acceleration to do this operation in the background but* 'lv_disp_flush_ready()' has to be called when finished. */
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{/*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, *color_p)*/
//            color_p++;
//        }
//    }unsigned int size = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) * 2;disp_drv_p = disp_drv;LCD_Address_Set(area->x1, area->y1, area->x2, area->y2+1);	LCD_CS = 0;DisPlay_SPI_DMA_Enable(color_p, size);/*不使用DMA的显示方法*/
//	LCD_Color_Fill(area->x1, area->y1, area->x2-area->x1, area->y2-area->y1+1, (unsigned short *)color_p);/* IMPORTANT!!!* Inform the graphics library that you are ready with the flushing*/
//    lv_disp_flush_ready(disp_drv);
}

最后编译;

还有一个错误;

 

 最终编译无误。

lv_port_disp_templ.c 文件最终更改后如下;

#if 1
#include "lv_port_disp_template.h"
#include "lcd.h"#define MY_DISP_HOR_RES 240  //屏的大小
#define MY_DISP_VER_RES 240
static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10];                        /*A buffer for 10 rows*/
static lv_color_t buf_2_2[MY_DISP_VER_RES * 10];                        /*An other buffer for 10 rows*/static lv_disp_drv_t *disp_drv_p;static void disp_init(void);static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);/*********************************************************************************************************
* 函 数 名 : DisPlay_SPI_DMA_Init
* 功能说明 : SPI3 DMA1初始化
* 形    参 : 无
* 返 回 值 : 无
* 备    注 : DMA1_Stream7搬运显示数据到SPI3的DR寄存器
*********************************************************************************************************/ 
static void DisPlay_SPI_DMA_Init()
{DMA_InitTypeDef  DMA_InitStructure	= {0};NVIC_InitTypeDef NVIC_InitStruct	= {0};RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); //DMA1时钟使能DMA_DeInit(DMA1_Stream7);while(DMA_GetCmdStatus(DMA1_Stream7) != DISABLE) {}  //等待DMA可配置/* 配置 DMA Stream */DMA_InitStructure.DMA_Channel 				= DMA_Channel_0;  				//通道选择DMA_InitStructure.DMA_PeripheralBaseAddr 	= (unsigned int)&SPI3->DR; 		//DMA外设地址DMA_InitStructure.DMA_Memory0BaseAddr 		= (unsigned int)buf_2_1;		//DMA 存储器0地址DMA_InitStructure.DMA_DIR 					= DMA_DIR_MemoryToPeripheral;	//存储器到外设模式DMA_InitStructure.DMA_BufferSize 			= sizeof(buf_2_2);				//数据传输量DMA_InitStructure.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;	//外设非增量模式DMA_InitStructure.DMA_MemoryInc 			= DMA_MemoryInc_Enable;			//存储器增量模式DMA_InitStructure.DMA_PeripheralDataSize 	= DMA_PeripheralDataSize_Byte;	//外设数据长度:8位DMA_InitStructure.DMA_MemoryDataSize 		= DMA_MemoryDataSize_Byte;		//存储器数据长度:8位DMA_InitStructure.DMA_Mode 					= DMA_Mode_Normal;				//使用普通模式DMA_InitStructure.DMA_Priority 				= DMA_Priority_High;			//中等优先级DMA_InitStructure.DMA_FIFOMode 				= DMA_FIFOMode_Disable;			//不使用fifoDMA_InitStructure.DMA_FIFOThreshold 		= DMA_FIFOThreshold_Full;		//fifo全容量DMA_InitStructure.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;		//存储器突发单次传输DMA_InitStructure.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;	//外设突发单次传输DMA_Init(DMA1_Stream7, &DMA_InitStructure);									//初始化DMA StreamSPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE); // SPI3使能DMA发送NVIC_InitStruct.NVIC_IRQChannel = DMA1_Stream7_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStruct);DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, ENABLE);DMA_Cmd(DMA1_Stream7, DISABLE);
}
/*********************************************************************************************************
* 函 数 名 : DisPlay_SPI_DMA_Enable
* 功能说明 : 配置DMA并启动一次传输
* 形    参 : buf:需要搬运的数据的指针;size:搬运的数据量
* 返 回 值 : 无
* 备    注 : 无
*********************************************************************************************************/ 
void DisPlay_SPI_DMA_Enable(void *buf, unsigned int size)
{DMA1_Stream7->CR &= ~(0x01);while((DMA1_Stream7->CR&0X1)){}DMA1_Stream7->M0AR = (unsigned int)buf;DMA1_Stream7->NDTR = size;DMA1_Stream7->CR |= (0x01);	
}
/*********************************************************************************************************
* 函 数 名 : DMA1_Stream7_IRQHandler
* 功能说明 : DMA1_Stream7发送完成中断
* 形    参 : 无
* 返 回 值 : 无
* 备    注 : 无
*********************************************************************************************************/ 
void DMA1_Stream7_IRQHandler(void)
{if(DMA_GetITStatus(DMA1_Stream7, DMA_IT_TCIF7) != RESET)//if(DMA1->HISR & (1<<27)){DMA_ClearITPendingBit(DMA1_Stream7, DMA_IT_TCIF7);//DMA1->HIFCR |= (1<<27);LCD_CS = 1;SPI3->DR;	lv_disp_flush_ready(disp_drv_p);	/* tell lvgl that flushing is done */}
}void lv_port_disp_init(void)
{disp_init();static lv_disp_draw_buf_t draw_buf_dsc_2;lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 10);   /*Initialize the display buffer*/static lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/disp_drv.hor_res = MY_DISP_HOR_RES;disp_drv.ver_res = MY_DISP_VER_RES;disp_drv.flush_cb = disp_flush;disp_drv.draw_buf = &draw_buf_dsc_2;lv_disp_drv_register(&disp_drv);
}static void disp_init(void)
{/*You code here*/DisPlay_SPI_DMA_Init();
}static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{unsigned int size = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) * 2;disp_drv_p = disp_drv;LCD_Address_Set(area->x1, area->y1, area->x2, area->y2+1);	LCD_CS = 0;DisPlay_SPI_DMA_Enable(color_p, size);
}#else 
typedef int keep_pedantic_happy;
#endif

根据需求修改lv_conf.h的宏定义;

  1. LV_COLOR_DEPTH:屏幕的色彩深度,支持1bit、8bit、16bit、32bit。
  2. LV_COLOR_16_SWAP:字节交换,DMA刷屏的时候需要置1。
  3. LV_MEM_SIZE:GUI可支配的内存空间,根据使用的功能调节。
  4. LV_FONT_MONTSERRAT_*:字体大小,太小会很模糊。

 

 

 如果需要更改默认字体大小,则把相应的宏设置为1.

 

 3、显示实现

配置一个定时器为LVGL提供1ms的时钟心跳,该定时器的中断服务函数中调用lv_tick_inc(1);即可

 主程序中调用lv_task_handler();函数处理事件

 

编写显示程序

#include "lvgl.h"
#include "lv_port_disp_template.h"
void Lvgl_Lable_Demo(void)
{_obj_t *scr = lv_scr_act();
lv_obj_t * label1 = lv_label_create(scr);lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP);    lv_label_set_recolor(label1, true);                      lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label, align the lines to the center ""and wrap long text automatically.");	lv_obj_set_width(label1, 150);  lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0);	lv_obj_align(label1, LV_ALIGN_CENTER, 0, -40);	lv_obj_t * label2 = lv_label_create(scr);lv_label_set_long_mode(label2, LV_LABEL_LONG_SCROLL_CIRCULAR);     lv_obj_set_width(label2, 150);	lv_label_set_text(label2, "It is a circularly scrolling text. ");	lv_obj_align(label2, LV_ALIGN_CENTER, 0, 40);	
}int main()
{
…..
Lcd_Init();lv_init();						// 初始化lvgllv_port_disp_init();  			// 显示初始化Lvgl_Lable_Demo();….while(1){lv_task_handler();Delay_Ms(1);}
}

4、添加外部中文字体的方法

打开字库生成工具,选择字体,选择TTF字体,加入常用字体,清除重复。目前抗齿距只能使用4,版本选择6.0以上,XBF字体,外部BIN。点击保存可以存出C文件,点击开始转换即可转换出BIN文件。

 然后点击加入常用汉字à保存à开始转换;

 得到以下两个文件;

 myFont.bin烧写到自己的SPI FLASH相应的地址。烧写过程你懂的。

myFont.c添加到自己的LVGL工程中并添加自定义的字体

lvgl.h处添加用户字体声明;

 将myFont.c中lv_font_t myFont结构体类型加上const修饰,其他需要修改的代码如。

 

5、编译下载后有几种情况 

(1)乱码:抗齿距不是4,多试几种;FLASH读写异常,先测试是否能正常读写。

(2)只有英文:显示中文的C文件编码不是UTF-8,使用软件修改为UTF-8编码后编译报错,在C/C++选项卡中的Misc Controls选项中添加--locale=english

 

6、调用显示 

void Lvgl_Lable_Demo(void)
{lv_obj_t *scr = lv_scr_act();
lv_obj_t * label1 = lv_label_create(scr);lv_label_set_long_mode(label1, LV_LABEL_LONG_WRAP);    lv_label_set_recolor(label1, true);                      lv_label_set_text(label1, "#0000ff Re-color# #ff00ff words# #ff0000 of a# label, align the lines to the center ""and wrap long text automatically");	lv_obj_set_width(label1, 150);  lv_obj_set_style_text_align(label1, LV_TEXT_ALIGN_CENTER, 0);	lv_obj_align(label1, LV_ALIGN_CENTER, 0, -40);	lv_obj_t * label2 = lv_label_create(scr);lv_label_set_long_mode(label2, LV_LABEL_LONG_SCROLL_CIRCULAR);     lv_obj_set_width(label2, 150);	lv_label_set_text(label2, "It is a circularly scrolling text.中国");	lv_obj_align(label2, LV_ALIGN_CENTER, 0, 40);	
}

6、GUI-Guider使用

GUI Guider是恩智浦为LVGL开发了一个上位机GUI设计工具,可以通过拖放控件的方式设计LVGL GUI页面,加速GUI的设计。

设计完成的GUI页面可以在PC上仿真运行,确认设计完毕之后可以生成C代码,再整合到MCU项目中。

GUI Guider(Version: 1.3.0-GA)的主要特征:

  1. 支持Windows 10和Ubuntu 20.04。
  2. 支持中文、英文。
  3. 兼容LVGL V7和LVGL V8版本。
  4. 支持拖放的所见即所得(WYSIWYG)用户界面设计。
  5. 多种字体支持及第三方字体导入。
  6. 可定制的中文字符范围。
  7. 小部件对齐方式:左、中、右。
  8. 自动产生LVGL C语言源代码。
  9. 支持默认样式和自定义样式。
  10. 演示应用程序集成。
  11. 实时日志显示。
  12. 集成上位机仿真器。

GUI-Guider会依赖JDK,因此需要安装jdk.

6.1 安装软件

GUI-Guider会依赖JDK,因此需要安装jdk.

6.2 使用软件 

1、打开GUI-Guider-1.3.0-GA软件;

 2、创建工程;

3、创建完成进入设计界面;

 

 左侧是组件区,中间是设计区,右边是控件地属性设置区。按照自己需要设计GUI页面,

 上图事件功能是按下按钮是把按钮的背景改为黑色。

运行模拟器预览一下效果

 

 没问题之后就可以生成代码(记得先保存工程),在Guider中也可以在代码窗口查看生成的代码.

 生成的代码在Guider工程目录的generated和custom文件夹下

 

6.3 移植到STM32 

把generated和custom文件夹工程整个复制到我们的keil工程目录中:

 

添加generated和custom文件夹相关源文件;

 

 

 

 

 

添加头文件路径

 编写测试代码

 更改错误:一般都是头文件路径不对,哪里不对改哪里。比如

相关文章:

嵌入式 LVGL移植到STM32F4

目录 LVGL简介 1、特点 2、LVGL的硬件要求 3、相关网站 4、LVGL源码下载 5、LVGL移植要求 5.1 移植过程-添加源码 2、更改接口文件 3、显示实现 4、添加外部中文字体的方法 5、编译下载后有几种情况 6、调用显示 6、GUI-Guider使用 6.1 安装软件 6.2 使用…...

VSCode——SSH免密登录

文章目录本地PC端&#xff08;一般为Windows&#xff09;1. 检查自己是否已经生成公钥2. 配置VScode的SSH config远程服务器端1. 服务器新建授权文件2. 赋权限3. 重启远程服务器的ssh服务最全步骤&#xff1a;【设置ssh免密不起作用&#xff1f;彻底搞懂密钥】vscode在remote S…...

python未来应用前景怎么样

Python近段时间一直涨势迅猛&#xff0c;在各大编程排行榜中崭露头角&#xff0c;得益于它多功能性和简单易上手的特性&#xff0c;让它可以在很多不同的工作中发挥重大作用。 正因如此&#xff0c;目前几乎所有大中型互联网企业都在使用 Python 完成各种各样的工作&#xff0…...

webpack基本使用和开发环境配置

目录 1 webpack 基本使用 01 webpack 简介 02 webpack 初体验 2 webpack开发环境配置 03 打包样式资源 04 打包html资源 05 打包图片资源 06 打包其他资源&#xff08;以打包icon为例&#xff09; 07 devServer 08.开发环境配置 1 webpack 基本使用 由于笔记文档没有…...

3.2 http协议

一.HTTP协议1.概述是计算机网络的核心概念,是一种网络协议网络协议种类非常多,其中IP,TCP,UDP...其中还有一个应用非常广泛的协议.HTTPHTTP协议是日常开发中用的最多的协议HTTP处在TCP/IP五层协议栈的应用层HTTP在传输层是基于TCP的,(http/1 HTTP/2是基于TCP,最新版本的HTTP/3是…...

页面访问升级出错怎么解决

相信大家在访问网站的时候时常会遇到页面访问界面升级&#xff0c;暂时不可能进行访问操作&#xff0c;可能遇到这种情况很多小伙伴们都不知道怎么版&#xff0c;其实互联网网页在正常使用过程中是不会出现这种问题的。那么如果遇到页面访问界面升级怎么办?页面访问界面升级通…...

leetcode 181. 超过经理收入的员工

SQL架构 表&#xff1a;Employee ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | | salary | int | | managerId | int | ---------------------- Id是该表的主键。 该表的…...

任务类风险漏洞挖掘思路

任务类风险定义&#xff1a; 大部分游戏都离不开任务&#xff0c;游戏往往也会借助任务&#xff0c;来引导玩家上手&#xff0c;了解游戏背景&#xff0c;增加游戏玩法&#xff0c;提升游戏趣味性。任务就像线索&#xff0c;将游戏的各个章节&#xff0c;各种玩法&#xff0c;…...

2023年Dubbo常见面试题

2023年Dubbo常见面试题 Dubbo 中 zookeeper 做注册中心&#xff0c;如果注册中心集群都挂掉&#xff0c;发布者和订阅者之间还能通信么&#xff1f; 可以通信的&#xff0c;启动 dubbo 时&#xff0c;消费者会从 zk 拉取注册的生产者的地址接口等数据&#xff0c;缓存在本地。…...

星光2开发板使用ECR6600U无线wifi网卡的方法

visionfive2 开发板性能还是不错的&#xff0c;有些人买的时候会带一个无线wifi网卡&#xff0c;但是官方提供的操作系统没有驱动。 所以需要自己编驱动&#xff08;他大爷的&#xff09;。 还好有人已经踩过坑了。 星光2之USB无线网卡使用教程【新增RTL8832AU WiFi6双频无线…...

【ArcGIS Pro二次开发】(11):面要素的一键拓扑

在工作中&#xff0c;经常需要对要素进行拓扑检查。 在ArcGIS Pro中正常的工作流程是在数据库中【新建要素数据集——新建拓扑——将要素加入拓扑——添加规则——验证】&#xff0c;工作流程不算短&#xff0c;操作起来比较繁琐。 下面以一个例子演示如何在ArcGIS Pro SDK二次…...

【实现点击下载按钮功能 Objective-C语言】

一、实现点击下载按钮功能, 1.接下来,我们再实现另外一个功能,是什么,点击下载按钮吧: 点击下载按钮,是不是要有效果啊, 就是给大家实现这个功能, 首先,我们要实现单击这个效果,是不是要给按钮注册单击事件吧, 请问,这个按钮在哪里啊,是在控制器里面吗,不是,…...

界面控件DevExpress WinForm——轻松构建类Visual Studio UI(三)

DevExpress WinForm拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜任…...

项目实战-瑞吉外卖day01(B站)

瑞吉外卖-Day01课程内容软件开发整体介绍瑞吉外卖项目介绍开发环境搭建后台登录功能开发后台退出功能开发1. 软件开发整体介绍作为一名软件开发工程师,我们需要了解在软件开发过程中的开发流程&#xff0c; 以及软件开发过程中涉及到的岗位角色&#xff0c;角色的分工、职责&am…...

Linux 学习整理(使用 iftop 查看网络带宽使用情况 《端口显示》)

一、命令简介 iftop 是实时流量监控工具&#xff0c;可以用来监控网卡的实时流量&#xff08;可以指定网段&#xff09;、反向解析IP、显示端口信息等。 二、命令安装 yum install -y iftop 三、命令相关参数及说明 3.1、相关参数说明 -i&#xff1a;设定监测的网卡&#…...

Vue3创建项目(四)axios封装及接口配置

项目结构: 目录 &#x1f349;&#x1f349;&#x1f349;index.ts &#x1f349;&#x1f349;&#x1f349; api.ts 看完需要预计花费10分钟。 请求拦截器与响应拦截器 阅读下面代码需先了解以下内容&#xff1a; 请求拦截器&#xff1a; 请求拦截器的作用是在请求发送前进…...

【算法笔记】递归与回溯

递归与回溯 To Iterate is Human, to Recurse, Divine. —L. Peter Deutsch 人理解迭代&#xff0c;神理解递归。 —L. Peter Deutsch 1.什么是递归呢 递归形象描述&#xff1a; 你打开面前这扇门&#xff0c;看到屋里面还有一扇门。 你走过去&#xff0c;发现手中的钥匙还可以…...

蓝桥杯备赛——Echarts学习

文章目录前言学习 ECharts 的方法快速上手基础知识option 配置选项可选配置title 标题组件tooltip 提示框组件axisPointer 坐标轴指示器legend 图例组件toolbox 工具栏坐标轴xAxis和yAxisseries &#xff08;[ ]用数组表示,数组里是一个个数据对象&#xff09;饼状图散点图交互…...

动态规划--最长公共子串

最长公共子串公共子串问题费曼算法动态规划算法思路代码实现公共子串问题 在计算机科学中&#xff0c;最长公共子串问题是寻找两个或多个已知字符串最长的子串。此问题与最长公共子序列问题的区别在于子序列不必是连续的&#xff0c;而子串却必须是。链接: 百度百科 费曼算法…...

【运筹优化】剩余空间法求解带顺序约束的二维矩形装箱问题 + Java代码实现

文章目录一、带顺序约束的二维矩形装箱问题二、剩余空间法三、完整代码实现3.1 Instance 实例类3.2 Item 物品类3.3 PlaceItem 已放置物品类3.4 Solution 结果类3.5 RSPackingWithWeight 剩余空间算法类3.6 Run 运行类3.7 测试案例3.8 ReadDataUtil 数据读取类3.9 运行结果展示…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

JVM垃圾回收机制全解析

Java虚拟机&#xff08;JVM&#xff09;中的垃圾收集器&#xff08;Garbage Collector&#xff0c;简称GC&#xff09;是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象&#xff0c;从而释放内存空间&#xff0c;避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...