当前位置: 首页 > 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 运行结果展示…...

第四阶段15-关于权限,处理解析JWT时的异常,跨域请求,关于Spring Security的认证流程

处理解析JWT时的异常 由于解析JWT是在过滤器中执行的&#xff0c;而过滤器是整个服务器端中最早接收到所有请求的组件&#xff0c;此时&#xff0c;控制器等其它组件尚未运行&#xff0c;则不可以使用此前的“全局异常处理器”来处理解析JWT时的异常&#xff08;全局异常处理器…...

毕业设计 基于51单片机的指纹红外密码电子锁

基于51单片机的指纹红外密码电子锁1、项目简介1.1 系统框架1.2 系统功能2、部分电路设计2.1 STC89C52单片机最小系统电路设计2.2 矩阵按键电路电路设计2.3 液晶显示模块电路设计3、部分代码展示3.1 LCD12864显示字符串3.2 串口初始化实物图1、项目简介 选题指导&#xff0c;项…...

【JavaWeb】数据链路层协议——以太网 + 应用层协议——DNS

以太网 以太网不是一个具体的网络&#xff0c;而是一个技术标准&#xff0c;主要应用于数据链路层和物理层。 以太网数据帧结构 以太网的数据帧结构由三部分构成&#xff1a; 帧头 载荷 帧尾 其中的MAC地址是六位&#xff0c;这样就比IPV4所表示的地址大很多&#xff0c;…...

docker 容器安装 python jre

Dockerfile FROM python:2.7.11-alpine RUN mkdir /usr/local/java WORKDIR /usr/local/java # 5.更改 Alpine 的软件源为阿里云&#xff0c;默认从官方源拉取比较慢 RUN echo http://mirrors.aliyun.com/alpine/v3.10/main/ > /etc/apk/repositories && \ echo…...

Linux下将C++程序打包成动态库静态库方法

之前在这篇文章里介绍过动态库和静态库的理论部分,这篇文章主要介绍下实际的操作步骤&#xff1a; 静态链接库生成 gcc -c main.cpp -o main.o ar -rc libmain.a main.o sudo cp libmain.a /usr/local/lib 调用即可解释一下上面的命令&#xff1a;前两步生成了libmain.a sudo…...

Centos7 服务器基线检查处理汇总

1、服务器超时设置 问题描叙 TMOUT的值大于key2且小于等于{key2}且小于等于key2且小于等于{key1}视为合规 查看命令&#xff1a;export检测结果 超时时间:0处理方式 备份/etc/profile文件 cp /etc/profile /etc/profile_bak编辑profile文件 vim /etc/profile修改/新增 TMO…...

PaddleOCR遇到 lanms-neo问题处理

在window环境中安装PaddleOCR依赖是真的蛋疼&#xff0c;关键官方论坛里也都没有具体的解决方案。吐槽。。。吐槽。。。 我在 “windows安装lanms-neo问题处理”文章中看到lanms-neo问题全过程解决。个人觉得文档说明不是很细致&#xff0c;导致我按步骤执行&#xff0c;还是安…...

coreldraw2023安装包下载及新功能介绍

对于广告标识业来说 coreldraw这个软件&#xff0c;对我们来说绝对不陌生&#xff0c;我从2008年开始接触到广告制作&#xff0c;到现在已经13多年了&#xff0c;从一开始的coreldraw 9红色的热气球开始。就被这个强大的软件所吸引&#xff0c;他有强大的排榜功能已经对位图的处…...

Nginx 负载均衡服务失败场景

nginx可以配置负载均衡&#xff0c;我们可以通过配置实现nginx负载均衡。这里部署了两个服务producter-one和producter-one2。 upstream proxyproducter-one {server producter-one:8080 weight1;server producter-one2:8080 weight1;}# 访问其他服务server {listen 9090…...

开学季哪个电容笔好?2023口碑最好电容笔推荐

虽说苹果原装的电容笔非常好用&#xff0c;性能也非常不错&#xff0c;但由于价格昂贵&#xff0c;普通的学生是没办法购买的&#xff0c;再加上重量比较大&#xff0c;使用时间长了&#xff0c;难免会让人感觉到疲劳。如果仅仅是为了学习记笔记&#xff0c;那就没必要再去购买…...

太原网站建设口碑推荐/嘉兴网络推广

1.更改java文件大小设置Window->preferences->General->Appearance->Colors and Fonts->Java->Java Editor Text Font->右边按钮Change 英文版默认的是Courier New 常规 102.更改jsp文件大小设置&#xff08;此设置也同事更改其他类型文件的字体大小&…...

南海网站推广/百度做广告怎么做

【摘要】在做国际化WEB项目的时候&#xff0c;遇到了一个根据用户浏览器所使用的自然语言切换默认语言版本的问题。于是&#xff0c;整理了这篇文章。 首先&#xff0c;W3Cschool关于Navigator的各个属性值说的很明确了&#xff0c;这里不再赘述。 然后&#xff0c;从各个浏览器…...

商务网站建设工程师/网络公司网站建设

产品接口&#xff1a;Product 产品实现类&#xff1a;ProductA&#xff0c;ProductB 当你需要根据条件A和B来分别创建产品时&#xff0c;就可以把if else放到一个类SimpleFacotory中的createProduct方法中&#xff0c;如下 SimpleFactory{public Product create(Type){if(A) …...

广州金融网站建设/阿里巴巴怎么优化关键词排名

一&#xff0e; 本地安装yum仓库 1.挂载镜像到/media下&#xff0c; mount /dev/sr0 /media/ 2.Centos 中要删除/etc/yum.repos.d/目录下的其他文件 cd /etc/yum.repos.d/ rm -r * 3.编辑yum仓库&#xff0c;必须以.reop为后缀 vim yum.repo [yum] nameyum …...

做网站模板的海报尺寸多少钱/青岛网站建设公司

当然前提是cmd.exe是以管理员身份执行的&#xff0c;不然会报“拒绝xx”的错..... 1、netstat -ano |findstr 3306 //查看3306端口是否存在 2、tasklist |findstr 3036&#xff08;PID号&#xff09;//查看pid为3036的是什么程序在用 3、taskkill /T /F /PID 3036 //强制&#…...

网站建设相关优化/悟空建站seo服务

它们彼此相反.doLayout用作extends标记的一部分. extends标记指定要扩展的模板,doLayout标记指定扩展模板中注入代码的位置.include标记只是指定应在指定的点注入另一个模板.因此,doLayout以类似的方式工作,除了doLayout标记没有指定注入哪个模板.这是通过extends标签完成的,这…...