嵌入式实时操作系统笔记3:FreeRTOS移植(STM32F407)_编写简单的FreeRTOS任务例程

上文讲到UC/OS III系统的移植,那篇文章是失败了的,网络上的资料真是层次不清,多有遗漏步骤,导致单片机连操作系统的初始化都卡在那,这次换个赛道,学FreeRTOS吧......

今日任务如标题所示:FreeRTOS移植(STM32F407)_编写简单的FreeRTOS任务例程

文章提供测试代码讲解、完整工程下载、测试效果图

这次总算是成功了!也是成功触碰到操作系统的领域了

目录

FreeRTOS移植准备:

准备STM32F407VET6空项目:

下载FreeRTOS V202212.00源码:

提取FreeRTOS V202212.00源码:

工程添加FreeRTOS源码:

添加文件到FreeRTOS/port:

添加文件到FreeRTOS/src:

添加FreeRTOSConfig.h:

所有工程源码添加情况如下所示:

 魔棒添加各个头文件路径:

 FreeRTOS/includes:

工程修改一些文件:

修改 FreeRTOSConfig.h :

修改stm32f4xx_it.h:

修改系统时钟初始化函数:

修改systick中断服务函数:

主函数:

问题解决:

编译报错:FCARM - Output Name not specified, please check 'Options for Target - Utilities'

编译报错:钩子函数未定义:

最终实现0报错:

编写简单的FreeRTOS任务例程:

宏定义各个任务:

主函数创建开始任务:

编写START_TASK 开始任务函数:

编写其余任务函数:

测试效果图:

测试遇到的问题:

1、只有task3一个最后初始化的任务能执行:

2、串口经常断开与PC的连接,且LED亮度闪烁不定:

测试工程说明:

测试工程下载:

测试工程文件注释勘误:

网上查阅资料贴出:


FreeRTOS移植准备:

准备STM32F407VET6空项目:

这里我使用了自己封装的裸机开发空项目文件,它的介绍如下,下载网址也同步贴出:

https://download.csdn.net/download/qq_64257614/89338792?spm=1001.2014.3001.5503

下载FreeRTOS V202212.00源码:

官方网址贴出:

FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions

官网提供的github链接太卡了,建议去代码托管网站下载:

FreeRTOS Real Time Kernel (RTOS) - Browse /FreeRTOS at SourceForge.net

我这里就直接下载目前的最新版本了:

 点这个zip文件下载就行了:

提取FreeRTOS V202212.00源码:

目录   FreeRTOSv202212.00\FreeRTOS\Source  下的就是源码:

在STM32空项目文件夹目录新建文件夹FreeRTOS:并移动文件:

然后在FreeRTOSv202212.00\FreeRTOS\Source\portable 目录将这俩文件夹移动到PORT

最后直接将 目录 FreeRTOSv202212.00\FreeRTOS\Source 下的include文件夹移动到在STM32空项目文件夹目录新建文件夹FreeRTOS

最后复制FreeRTOSv202212.00\FreeRTOS\Demo\CORTEX_M4F_STM32F407ZG-SK 中的 FreeRTOSConfig.h 到文件夹至此移动结束:

工程添加FreeRTOS源码:

先新建俩个分组:

FreeRTOS/src
FreeRTOS/port

添加文件到FreeRTOS/port

点击---FreeRTOS/src----AddFiles

添加以下目录中所有文件 :\FreeRTOS\PORT\RVDS\ARM_CM4F

如果查找不到文件,别忘记将文件类型改为 ALL Files

添加完后应如是:

方才添加时发现,有俩个ARM_M4相关的文件夹供选择,那它们有何区别呢:

  1. ARM_CM4F:这通常表示针对ARM Cortex-M4F内核的源代码。STM32F407VET6是一个基于ARM Cortex-M4F的处理器,它包含了浮点单元(FPU),因此如果你打算使用到浮点运算,那么选择ARM_CM4F的文件可能更为合适。
  2. ARM_CM4_MPU:这通常与ARM Cortex-M4处理器中的内存保护单元(MPU)相关。MPU用于提供硬件级别的内存访问控制,以防止一个任务或进程访问到另一个任务或进程的内存区域。如果你的项目需要这种级别的内存保护,那么你可能需要选择ARM_CM4_MPU的文件。
  3. 至此我们知道了STM32F407VET6 需要添加的是ARM_CM4F 文件夹中的内容!

然后再添加添加以下目录中的文件 :\FreeRTOS\FreeRTOS\PORT\MemMang

这里我们就添加heap4.c即可,(这个是选择一个添加的,具体介绍下面会提到)

添加heap4.c
  • heap_1.c这是一个非常简单的内存管理实现,它使用一个静态分配的数组作为堆。适用于那些内存需求相对固定且不需要复杂的内存管理的应用。
  • heap_2.c这个实现提供了比heap_1更复杂的内存管理,包括内存碎片合并等特性。但它仍然基于一个静态分配的数组。
  • heap_3.cheap_4.c这些实现提供了更复杂的内存管理算法,但它们可能并不总是适合嵌入式系统,因为它们可能需要更多的RAM或处理时间。
  • heap_5.c(可能称为heap_5x.c):这是一个基于最佳适应(best-fit)算法的堆实现,它提供了较好的内存碎片管理,但可能需要更复杂的实现和更多的处理时间。
  • heap_x.c这是一个用户定义的内存管理实现,允许你根据自己的需求编写自定义的内存管理代码。

添加文件到FreeRTOS/src

点击---FreeRTOS/src----AddFiles

添加以下目录中所有文件 :\FreeRTOS\SRC

如果查找不到文件,别忘记将文件类型改为 ALL Files

添加文件到 FreeRTOS/src

添加FreeRTOSConfig.h:

由之前移动提取源码的操作可知,这个.h文件目录在截图所示文件夹内:

FreeRTOSConfig.h目录

这个头文件随便添加在哪都行,我是放置在了startup 组内了:

所有工程源码添加情况如下所示:

 魔棒添加各个头文件路径:

 FreeRTOS/includes:

这我额外新增一个组FreeRTOS/includes并将FreeRTOS\include文件夹中的内容都放进了:

工程修改一些文件:

修改 FreeRTOSConfig.h :

宏定义配置功能介绍,这部分可以先跳过或者快速浏览,以后用到在仔细看:

/*设置为1,表示启用抢占式调度。这意味着当一个更高优先级的任务准备好运行时,它会立即抢占当前运行的任务的CPU。*/
#define configUSE_PREEMPTION			1
/*设置为1,表示启用空闲钩子函数。空闲钩子函数是一个可以在系统处于空闲状态时调用的函数。*/
#define configUSE_IDLE_HOOK				1
/*设置为1,表示启用滴答定时器钩子函数。这个函数在每个滴答定时器中断时都会被调用。*/
#define configUSE_TICK_HOOK				1
/*定义CPU的时钟频率。这里使用了SystemCoreClock宏,它可能是在其他地方定义的。*/
#define configCPU_CLOCK_HZ				( SystemCoreClock )
/*定义了FreeRTOS滴答定时器的频率。这里设置为1000Hz,意味着每秒有1000个滴答。*/
#define configTICK_RATE_HZ				( ( TickType_t ) 1000 )
/*定义了FreeRTOS中可以使用的最大任务优先级数量。这里设置为5。*/
#define configMAX_PRIORITIES			( 5 )
/*定义了每个任务的最小栈大小(以字节为单位)。这里设置为130字节。*/
#define configMINIMAL_STACK_SIZE		( ( unsigned short ) 130 )
/*定义了FreeRTOS可用的总堆大小(以字节为单位)。这里设置为75KB。*/	
#define configTOTAL_HEAP_SIZE			( ( size_t ) ( 75 * 1024 ) )
/*定义了任务名称的最大长度。这里设置为10个字符。*/
#define configMAX_TASK_NAME_LEN			( 10 )
/*设置为1,表示启用跟踪功能。这允许你收集有关任务执行、队列操作和其他RTOS活动的信息。*/
#define configUSE_TRACE_FACILITY		1
/*设置为0,表示使用32位滴答计数器。如果设置为1,则使用16位滴答计数器。*/
#define configUSE_16_BIT_TICKS			0
/*设置为1,表示在空闲任务中应该进行任务切换(如果有其他任务准备好运行)。*/
#define configIDLE_SHOULD_YIELD			1
/*设置为1,表示启用互斥量(mutex)功能。*/
#define configUSE_MUTEXES				1
/*定义了队列注册表的项数。这允许你跟踪队列的使用情况,并帮助调试。*/
#define configQUEUE_REGISTRY_SIZE		8
/*定义了栈溢出检查的类型。这里设置为2,可能是某种特定类型的检查(具体的检查方式可能因FreeRTOS版本而异)。*/
#define configCHECK_FOR_STACK_OVERFLOW	2
/*设置为1,表示启用递归互斥量。递归互斥量允许同一个任务多次获取同一个互斥量。*/
#define configUSE_RECURSIVE_MUTEXES		1
/*设置为1,表示启用内存分配失败钩子函数。当FreeRTOS的堆内存耗尽时,这个函数会被调用。*/
#define configUSE_MALLOC_FAILED_HOOK	1
/*设置为0,表示不启用应用程序任务标签功能。*/
#define configUSE_APPLICATION_TASK_TAG	0
/*设置为1,表示启用计数信号量。*/
#define configUSE_COUNTING_SEMAPHORES	1
/*设置为0,表示不生成运行时统计信息。如果设置为1,FreeRTOS会收集关于任务运行时间的信息。*/
#define configGENERATE_RUN_TIME_STATS	0


/* Software timer definitions. */
/*设置为1,表示启用FreeRTOS的软件定时器功能。软件定时器允许你在没有硬件定时器可用或想要更复杂的定时行为时使用软件实现定时器。*/
#define configUSE_TIMERS				1
/*定义了软件定时器任务的优先级。在这里,它被设置为2,意味着软件定时器任务的优先级为2。*/
#define configTIMER_TASK_PRIORITY		( 2 )
/*定义了软件定时器队列的长度。当定时器到期时,它们会被添加到这个队列中以供软件定时器任务处理。队列长度为10表示最多可以有10个定时器等待处理。*/
#define configTIMER_QUEUE_LENGTH		10
/*定义了软件定时器任务的栈深度。这里它被设置为configMINIMAL_STACK_SIZE * 2,意味着软件定时器任务的栈大小是最小栈大小的两倍。*/
#define configTIMER_TASK_STACK_DEPTH	( configMINIMAL_STACK_SIZE * 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
/*设置为1,表示包含vTaskPrioritySet函数。这个函数用于动态地改变任务的优先级。*/
#define INCLUDE_vTaskPrioritySet		1
/*设置为1,表示包含uxTaskPriorityGet函数。这个函数用于获取任务的当前优先级。*/
#define INCLUDE_uxTaskPriorityGet		1
/*设置为1,表示包含vTaskDelete函数。这个函数用于删除一个任务,释放其占用的资源。*/
#define INCLUDE_vTaskDelete				1
/*设置为1,表示包含vTaskCleanUpResources函数。这个函数用于清理FreeRTOS内核在不再需要时占用的资源。通常,在应用程序的最后一个任务结束时调用。*/
#define INCLUDE_vTaskCleanUpResources	1
/*设置为1,表示包含vTaskSuspend函数。这个函数用于挂起一个任务,使其不再运行,直到它被恢复。*/
#define INCLUDE_vTaskSuspend			1
/*设置为1,表示包含vTaskDelayUntil函数。这个函数用于使当前任务延迟到指定的绝对时间。*/
#define INCLUDE_vTaskDelayUntil			1
/*设置为1,表示包含vTaskDelay函数。这个函数用于使当前任务延迟指定的时间片数(滴答数)。*/
#define INCLUDE_vTaskDelay				1

 在FreeRTOSConfig.h添加以下头文件:

#include "stm32f4xx.h"//

修改条件编译:

改为:

#if defined (__ICCARM__) || defined (__CC_ARM)  ||  defined (__GNUC__) 
	#include <stdint.h>
	extern uint32_t SystemCoreClock;
#endif

屏蔽FreeRTOSConfig.h掉底部的#define xPortSysTickHandler SysTick_Handler

修改stm32f4xx_it.h:

注释掉几个中断服务函数 PendSV_Handler(),SVC_Handler(),SysTick_Handler()

因为已经在FreeRTOS的相关文件中需要用到,并提供定义了:

修改系统时钟初始化函数:

这部分Systick系统时钟的初始化目的是要将系统时钟的频率  与FreeRTOS的宏定义configTICK_RATE_HZ 进行联系,之后是可以通过修改 configTICK_RATE_HZ来反过来直接修改Systick系统时钟的频率的

			   
//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟,基础例程里面SYSTICK时钟频率为AHB/8
//这里为了兼容FreeRTOS,所以将SYSTICK的时钟频率改为AHB的频率!
//SYSCLK:系统时钟频率
void delay_init(u8 SYSCLK)
{
	u32 reload;
 	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); 
	fac_us=SYSCLK;							//不论是否使用OS,fac_us都需要使用
	reload=SYSCLK;							//每秒钟的计数次数 单位为M	   
	reload*=1000000/configTICK_RATE_HZ;		//根据configTICK_RATE_HZ设定溢出时间
											//reload为24位寄存器,最大值:16777216,在168M下,约合0.0998s左右	
	fac_ms=1000/configTICK_RATE_HZ;			//代表OS可以延时的最少单位	   
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;//开启SYSTICK中断
	SysTick->LOAD=reload; 					//每1/configTICK_RATE_HZ断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启SYSTICK     
}								    

修改systick中断服务函数:

这个函数我添加在了#include "delay.h":

// 声明SysTick中断处理函数  
void SysTick_Handler(void)
{
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
	{
		xPortSysTickHandler();
	}
}

主函数:

先添加头文件,然后删去while(1)循环之类的:

/*****************FREE RTOS头文件***************/
#include "FreeRTOS.h"
#include "task.h"

问题解决:

编译报错:FCARM - Output Name not specified, please check 'Options for Target - Utilities'

这是因为某个导入文件的格式选错了:这是个说明文件,不小心暴力导入了,直接鼠标右键Remove即可

编译报错:钩子函数未定义:

FreeRTOSConfig.h中关闭这些钩子函数,他们都是宏定义决定,这里将  configUSE_IDLE_HOOK

configUSE_TICK_HOOK

configUSE_MALLOC_FAILED_HOOK

configUSE_FOR_STACK_OVERFLOW

或者叫configCHECK_FOR_STACK_OVERFLOW

定义为0

最终实现0报错:

编写简单的FreeRTOS任务例程:

各个TASK的任务如下描述:

//TASK_1 串口报告自己执行的次数 (0.5s) 并打开LED

//TASK_2 串口报告自己执行的次数 (1.2s) 并关闭LED

//TASK_3 会每隔 5S 打印

宏定义各个任务:

任务优先级 \任务堆栈大小   \任务句柄 \任务函数
/*******开始任务的宏定义*********/
#define START_TASK_PRIO		1         //任务优先级
#define START_STK_SIZE 		128       //任务堆栈大小	
TaskHandle_t StartTask_Handler;     //任务句柄
void start_task(void *pvParameters);//任务函数

/*******TASK1任务的宏定义*********/
#define TASK1_TASK_PRIO		2         //任务优先级
#define TASK1_STK_SIZE 		50        //任务堆栈大小	
TaskHandle_t Task1_Handler;         //任务句柄
void task1_task(void *pvParameters);//任务函数

/*******TASK2任务的宏定义*********/
#define TASK2_TASK_PRIO		3         //任务优先级
#define TASK2_STK_SIZE 		50        //任务堆栈大小	
TaskHandle_t Task2_Handler;         //任务句柄
void task2_task(void *pvParameters);//任务函数

/*******TASK3任务的宏定义*********/
#define TASK3_TASK_PRIO		3         //任务优先级
#define TASK3_STK_SIZE 		50        //任务堆栈大小	
TaskHandle_t Task3_Handler;         //任务句柄
void task3_task(void *pvParameters);//任务函数

主函数创建开始任务:

int main(void)
{	
  system_init_all();       //开机初始化系统所有模块
  //开启 FreeRTOS 操作系统,创建开始任务!
	//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    UsartPrintf(USART1," FreeRTOS : Hello World!\r\n");	//开机打印测试字符串 
		vTaskStartScheduler();          //开启任务调度	
}

编写START_TASK 开始任务函数:

 START_TASK 开始任务函数 在创建完其余任务后必须删除 START_TASK 任务

不然他也会出现在时间片轮询,造成不必要的占用!

//开始任务任务函数
void start_task(void *pvParameters)
{

	//创建TASK1任务

    xTaskCreate((TaskFunction_t )task1_task,     	
                (const char*    )"task1_task",   	
                (uint16_t       )TASK1_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )TASK1_TASK_PRIO,	
                (TaskHandle_t*  )&Task1_Handler);   

	
	//创建TASK2任务
    xTaskCreate((TaskFunction_t )task2_task,     	
                (const char*    )"task2_task",   	
                (uint16_t       )TASK2_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )TASK2_TASK_PRIO,	
                (TaskHandle_t*  )&Task2_Handler);  
								
	//创建TASK3任务
    xTaskCreate((TaskFunction_t )task3_task,     	
                (const char*    )"task3_task",   	
                (uint16_t       )TASK3_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )TASK3_TASK_PRIO,	
                (TaskHandle_t*  )&Task3_Handler);  
								
	//删除开始任务							
		vTaskDelete(StartTask_Handler); 
}

编写其余任务函数:

在开始任务的基础上,其他任务只需要在此基础上添加三个地方:
①声明;      ②函数编写;     ③开始任务函数调用


//TASK_1 串口报告自己执行的次数 (0.5s)
void task1_task(void *pvParameters)
{
	int TASK1_num=0;  //记录任务TASK_1执行次数 
	
	
	while(1)
	{
		TASK1_num++;	//任务TASK_1执行次数加1
		PBout(2)=1;
	  UsartPrintf(USART1,"TASK_1 has Carred out %d times! \r\n",TASK1_num);	//打印测试字符串(并报告TASK_1执行次数)
		vTaskDelay(500);//使当前任务延迟指定的时间(2s):  (让当前任务放弃CPU一段时间,CPU让给其余任务)
	}
}
 
//TASK_2 串口报告自己执行的次数 (1.2s)
void task2_task(void *pvParameters)
{
	int TASK2_num=0;  //记录任务TASK_2执行次数
		
	while(1)
	{
		TASK2_num++;
		PBout(2)=0;
	    UsartPrintf(USART1,"TASK_2 has Carred out %d times! \r\n",TASK2_num);	//打印测试字符串(并报告TASK_2执行次数)
		vTaskDelay(1200);//使当前任务延迟指定的时间(1s):  (让当前任务放弃CPU一段时间,CPU让给其余任务)
	}
}
 
//TASK_3 会每隔 5S 打印
void task3_task(void *pvParameters)
{
	int TASK3_num=0;  //记录任务TASK_3执行次数								 
	while(1)
	{
		  TASK3_num++;
	    UsartPrintf(USART1,"TASK_3 has Carred out %d times! \r\n",TASK3_num);	//打印测试字符串(并报告TASK_3执行次数)							 
		  vTaskDelay(5000); //使当前任务延迟指定的时间(17s):  (让当前任务放弃CPU一段时间,CPU让给其余任务)	
	}
}

测试效果图:

在串口测试可以看出三个任务各自的延时关系,以及不阻塞延时就是将延时的时间空闲留给其余任务执行:

框图关系可以看出以下几点:

1、三个任务被创建后立马执行一次

2、任务三 Task3 执行一次到下次的间隔有 5S,任务1 Task1 执行了9次(约4.5s),任务2 Task2 执行了4次(约4.8s)

3、任务二 Task2执行一次到下次的间隔有 1.2S,任务1 Task1 执行了2次(约1s)

然后还有LED会被 Task1 Task2 周期性亮灭

测试遇到的问题:

1、只有task3一个最后初始化的任务能执行:

(测试时尝试删去过task3,发现最后初始化的任务task2仍然是这个效果,也能执行,但仅仅是最后初始化的任务能执行)

解决:我是屏蔽删去了定时器的初始化,就能让三个任务都能执行了,后面应该会学到任务屏蔽块函数,能够屏蔽这些中断,防止任务被打断得连初始化进入都进不来

2、串口经常断开与PC的连接,且LED亮度闪烁不定:

这明显是供电不足导致的,我额外插个USB稳定的电源解决了

测试工程说明:

这里说明一下,因为我在初学时到处查阅资料无法理解Systick系统时钟的初始化与中断服务函数是如何与FreeRTOS的宏定义configTICK_RATE_HZ进行联系的,因此移植了正点原子的delay.h文件(初始化系统时钟的,可选OS系统),原工程的board.h被移除了 

/*
                              NULL指向我 { FreeRTOS } 项目封装说明:
                                                                    
    1、所有头文件都引用在headfire.h中,新建.h都只需 #include "headfire.h" 即可,也方便查阅修改
       (1) headfire.h新增 位带操作,实现51类似的GPIO控制功能
       
    2、Timer_common_init();可以初始化任意 TIMx 为通用定时器(带溢出中断),但必须在调用前添加开启相应定时器时钟的语句    
        
    3、函数 system_init_all(void); 初始化STM32所有外设模块 移动到了 headfire.h
    
    4、 自主配置修改了 SystemTick 的配置 内核定时器SystemTick  
       (1) 工程文件 #include "delay.h" 内配置了 SystemTick 内核定时器
       (2) SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); 函数初始化了SystemTick 内核定时器 的时钟源是168M
       (3) 增加了 SystemTick 定时中断功能
       (4) 声明SysTick中断处理函数  void SysTick_Handler(void) 必须要有,否则中断无法跳出,程序会卡在 初始化 1ms (这个时间是根据说明项5得出的) 后
       
       
    5、 SysTick新增中断,频率 为1000Hz, 即1ms  
       (1) 如想更改 内核定时器 溢出频率 更改   #define configTICK_RATE_HZ (1000) 括号内的值即可:  (在FreeRTOSConfig.h中)        
                uint32_t reload = SystemCoreClock / 1000 - 1; // 1ms中断频率 (1000Hz)
                         reload = configTICK_RATE_HZ
                Tips: 1、SystemCoreClock =168 000 000
                       2、SysTick_LOAD = (SystemCoreClock / TickRate) - 1
                       3、SysTick_LOAD = reload;
       (2) 内核定时器 未配置 溢出中断的NVIC优先级 (如果需要配置,我觉得应该要比其余中断低 甚至于最低组4)
       (3)
          
          
    6、 #include <board.h> 新增位带操作的宏定义 ,可以实现51类似的GPIO控制功能
        
    7、 UsartPrintf (USART_TypeDef *USARTx, char *fmt,...)函数 能够做到使用任意串口打印,并且用法与Printf相同(需要多传第一个参数 USARTx)
        (1) 该函数定义在 : #include "Uart.h"
        (2) 如需别处复制使用 需包含头文件 #include "stdarg.h"
    
*/

测试工程下载:

https://download.csdn.net/download/qq_64257614/89342421

测试工程文件注释勘误:

测试工程在学习的过程中经过多次修改,有部分注释与代码实际有出入不慎对应,这里勘误一下:

这里的延时是500ms,但注释写的是2S,注释错误

这里的延时是1200ms,但注释写的是1S,注释错误

这里的延时是5s,但注释写的是17S,注释错误

网上查阅资料贴出:

2、STM32F407移植FreeRTOS步骤_systemcoreclock 未定义-CSDN博客

FreeRTOS运行一次后卡死_freertos任务执行一次-CSDN博客

01 FreeRTOS任务实例_freertos例程-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年【熔化焊接与热切割】考试内容及熔化焊接与热切割考试报名

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 熔化焊接与热切割考试内容考前必练&#xff01;安全生产模拟考试一点通每个月更新熔化焊接与热切割考试报名题目及答案&#xff01;多做几遍&#xff0c;其实通过熔化焊接与热切割复审模拟考试很简单。 1、【单选题】…

Android 配置 Kapt 编译器插件

以 Android Studio 2023.3.1 最新版本为准。 步骤1:打开版本信息配置文件 找到libs.versions.toml文件。 这是打开后的样子&#xff1a; 步骤2&#xff1a;配置版本信息 你需要在[plugins]下面添加一条kapt的配置信息&#xff1a; 要添加的配置信息如下&#xff1a; jetbr…

Boxy SVG for Mac:打造精致矢量图形的得力助手

在矢量图形设计领域&#xff0c;Boxy SVG for Mac以其出色的性能和丰富的功能&#xff0c;成为了设计师们的得力助手。 Boxy SVG for Mac(矢量图编辑器) v4.32.0免激活版下载 Boxy SVG具备强大的编辑能力&#xff0c;支持节点编辑、路径绘制、颜色填充等多种操作&#xff0c;让…

小浪助手下载学浪视频的简单步骤

你是否想轻松下载学浪高清视频&#xff1f;快来尝试小浪助手&#xff0c;这是你不可错过的下载神器&#xff01;简单几步操作&#xff0c;即可轻松下载你所需的学浪视频&#xff0c;节省时间&#xff0c;提高效率&#xff01; 首先我已经打包好了小浪助手&#xff0c;有需要的…

毫米波雷达模块在智能家居安全系统中的关键技术分析

随着智能技术的不断发展&#xff0c;智能家居已经成为了现代生活的一部分。而智能家居安全系统作为智能家居的重要组成部分&#xff0c;其功能不仅仅是对家庭进行监控和报警&#xff0c;更是通过各种感知技术对家庭安全进行全方位的保障。在智能家居安全系统中&#xff0c;毫米…

二叉树的遍历(前序遍历,中序遍历,后序,层序遍历)和一些简单操作(由浅入深绝对能看懂)

欢迎大佬们的关顾能给个赞就更好啦QWQ 目录 二叉树的逻辑结构与物理结构 一.二叉树的遍历 &#xff08;1&#xff09;二叉树的前序遍历 &#xff08;2&#xff09;二叉树的中序遍历 &#xff08;3&#xff09;二叉树的后序遍历 &#xff08;4&#xff09;二叉树的层序遍历…

Python 渗透测试:电子邮件 || Redis || FTP || SSH || MySQL 集成爆破工具.

集成爆破工具. 集合爆破里面包含了&#xff1a;电子邮件爆破工具&#xff0c;Redis爆破工具&#xff0c;FTP爆破工具&#xff0c;SSH爆破工具&#xff0c;MySQL爆破工具。 目录&#xff1a; 集合爆破工具. 电子邮件 爆破工具&#xff1a; Redis 爆破工具&#xff1a; FTP …

sqlserver 创建表,列及表,列描述

-- 创建表 CREATE TABLE Employees (EmployeeID INT PRIMARY KEY,EmployeeName NVARCHAR(100),EmployeeEmail NVARCHAR(100) );-- 为表添加描述 EXEC sp_addextendedproperty name NMS_Description, value N员工信息表, level0type NSchema, level0name dbo, level1type N…

数字图像处理冈塞雷斯第四版课后习题答案【英文原版】

第二章 第三章 . 第四章 傅里叶变换是一个线性过程&#xff0c;而计算梯度的平方根和平方根则是非线性运算。傅里叶变换可以用来计算微分的差值(如问题4.50)&#xff0c;但必须在空间域中直接计算平方和平方根值。 (a)实际上&#xff0c;由于高通操作&#xff0c;环有一个暗中心…

基于MetaGPT构建LLM多智能体

前言 你好&#xff0c;我是GISer Liu&#xff0c;在上一篇文章中&#xff0c;我们用了两万多字详细拆解了单个Agent的组成&#xff0c;并通过Github Trending订阅智能体理解MetaGPT框架的订阅模块如何解决应用问题&#xff0c;但是对于复杂&#xff0c;并行的任务&#xff0c;单…

010-Linux磁盘介绍

文章目录 1、名词 2、类型 3、尺寸 4、接口/协议/总线 5、命名 6、分区方式 MBR分区 GPT分区 1、名词 磁盘是计算机主要的存储介质&#xff0c;可以存储大量的二进制数据&#xff0c;并且断电后也能保持数据不丢失。早期计算机使用的磁盘是软磁盘&#xff08;Floppy D…

VBA技术资料MF157:创建每个标题的目录

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

【计算机毕业设计】基于SSM+Vue的校园美食交流系统【源码+lw+部署文档】

目录 前 言 第1章 概述 1.1 研究背景 1.2 研究目的 1.3 研究内容 第二章 开发技术介绍 2.1 Java技术 2.2 Mysql数据库 2.3 B/S结构 2.4 SSM框架 第三章 系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.2 系统性能分析 3.3 系…

(避坑)SpringSecurity关于使用.antMatchers放行接口不生效问题

问题 在使用SpringSecurity的时候发现放行指定接口一直没有生效&#xff0c;使用"/**"就可以生效的问题 关于securityConfig的配置代码 Beanprotected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.csrf().disable() // 关闭csrf防护…

用 vue3 + phaser 实现经典小游戏:飞机大战

本文字数&#xff1a;7539字 预计阅读时间&#xff1a;30分钟 01 前言 说起小游戏&#xff0c;最经典的莫过于飞机大战了&#xff0c;相信很多同学都玩过。今天我们也来试试开发个有趣的小游戏吧&#xff01;我们将从零开始&#xff0c;看看怎样一步步实现一个H5版的飞机大战&a…

vue3 依赖-组件tablepage-vue3版本1.1.2~1.1.5更新内容

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

【计网】广播域和冲突域

一、相关概念 1.各层次设备 2.冲突域 2.1定义 冲突域通俗来讲就是在同一个网络中&#xff0c;两台设备同时传输的话会产生冲突。位于OSI的第一层&#xff1a;物理层 例如在集线器场景下&#xff0c;集线器属于物理层设备&#xff0c;它不具备交换机的功能&#xff0c;当收到节…

问题解决记录1:nvidia-container-cli: initialization error: load library failed

本地docker运行 $ docker run --rm --gpus all nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia-smi 遇到这种报错 Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error dur…

8.Redis之hash类型

1.hash类型的基本介绍 哈希表[之前学过的所有数据结构中,最最重要的] 1.日常开发中,出场频率非常高. 2.面试中,非常重要的考点, Redis 自身已经是键值对结构了Redis 自身的键值对就是通过 哈希 的方式来组织的 把 key 这一层组织完成之后, 到了 value 这一层~~ value 的其中…

掌握ASPICE标准:汽车软件测试工程师的专业发展路径

掌握ASPICE标准&#xff1a;汽车软件测试工程师的专业发展路径 文&#xff1a;领测老贺 随着新能源汽车在中国的蓬勃发展&#xff0c;智能驾驶技术的兴起&#xff0c;汽车测试工程师的角色变得愈发关键。这一变革带来了前所未有的挑战和机遇&#xff0c;要求测试工程师不仅要具…