STM32F1--FreeRTOS系统学习(二):任务创建与删除(动态)

2023-05-16

以下内容皆是个人学习过程中的总结,记录一下整个过程,用于后期复习,如有不对之处,麻烦各位大佬指出~

(喜欢的朋友麻烦点个关注~~~  后期还会进行持续更新)

        在FreeRTOS 中应用既可以使用任务,也可以使用协程(Co-Routine),或者两者混合使用。 但是任务和协程使用不同的API函数,因此不能通过队列(或信号量)将数据从任务发送给协程, 反之亦然。协程是为那些资源很少的 MCU 准备的,其开销很小,但是 FreeRTOS 官方已经不打算再更新协程了,因此我们对于协程进行一个简单的了解就好了,主要还是学习任务

任务(Task)的特性:

        在使用 RTOS 的时候一个实时应用可以作为一个独立的任务。每个任务都有自己的运行环境,不依赖于系统中其他的任务或者 RTOS 调度器。任何一个时间点只能有一个任务运行,具 体运行哪个任务是由 RTOS 调度器来决定的,RTOS 调度器因此就会重复的开启、关闭每个任务。任务不需要了解 RTOS 调度器的具体行为,RTOS 调度器的职责是确保当一个任务开始执 行的时候其上下文环境(寄存器值,堆栈内容等)和任务上一次退出的时候相同。为了做到这一 点,每个任务都必须有个堆栈,当任务切换的时候将上下文环境保存在堆栈中,这样当任务再 次执行的时候就可以从堆栈中取出上下文环境,任务恢复运行。

任务特性:

1、简单。

2、没有使用限制。

3、支持抢占

4、支持优先级

5、每个任务都拥有堆栈导致了 RAM 使用量增大。

6、如果使用抢占的话的必须仔细的考虑重入的问题。.

协程(Co-routine)的特性:

        协程是为那些资源很少的 MCU 而做的,但是随着 MCU 的飞速发展,性能越来越强大,现 在协程几乎很少用到了!但是 FreeRTOS 目前还没有把协程移除的计划,但是 FreeRTOS 是绝对 不会再更新和维护协程了,因此协程大家了解一下就行了。在概念上协程和任务是相似的,但 是有如下根本上的不同:

1、堆栈使用所有的协程使用同一个堆栈(如果是任务的话每个任务都有自己的堆栈),这样就比使用任务消耗更少的 RAM。

2、调度器和优先级协程使用合作式的调度器,但是可以在使用抢占式的调度器中使用协程。

3、宏实现协程是通过宏定义来实现的。

4、使用限制为了降低对 RAM 的消耗做了很多的限制

在了解完任务的基本特性之后,我们现在开始正式学习

一、任务状态:

        首先我们要知道,在FreeRTOS 中任务永远处于下面几个状态中的某一个:

● 运行态 当一个任务正在运行时,那么就说这个任务处于运行态,处于运行态的任务就是当前正在 使用处理器的任务。如果使用的是单核处理器的话那么不管在任何时刻永远都只有一个任务处 于运行态。

● 就绪态 处于就绪态的任务是那些已经准备就绪(这些任务没有被阻塞或者挂起),可以运行的任务, 但是处于就绪态的任务还没有运行,因为有一个同优先级或者更高优先级的任务正在运行!

● 阻塞态 如果一个任务当前正在等待某个外部事件的话就说它处于阻塞态,比如说如果某个任务调 用了函数 vTaskDelay()的话就会进入阻塞态,直到延时周期完成。任务在等待队列、信号量、事 件组、通知或互斥信号量的时候也会进入阻塞态。任务进入阻塞态会有一个超时时间,当超过 这个超时时间任务就会退出阻塞态,即使所等待的事件还没有来临!

● 挂起态 像阻塞态一样,任务进入挂起态以后也不能被调度器调用进入运行态,但是进入挂起态的 任务没有超时时间。任务进入和退出挂起态通过调用函数 vTaskSuspend()和 xTaskResume()。

任务状态之间的转换如下图所示:

二、任务优先级:

        每 个 任 务 都 可 以 分 配 一 个 从 0~(configMAX_PRIORITIES-1) 的 优 先 级 , configMAX_PRIORITIES 在文件 FreeRTOSConfig.h 中有定义,前面我们讲解 FreeRTOS 系统配 置的时候已经讲过了。如果所使用的硬件平台支持类似计算前导零这样的指令(可以通过该指令 选 择 下 一 个 要 运 行 的 任 务 , Cortex-M 处 理 器 是 支 持 该 指 令 的 ) ,并且宏 configUSE_PORT_OPTIMISED_TASK_SELECTION 也 设 置 为 了 1 , 那 么 宏 configMAX_PRIORITIES 不能超过 32!也就是优先级不能超过 32 级。其他情况下宏 configMAX_PRIORITIES 可以为任意值,但是考虑到 RAM 的消耗,宏 configMAX_PRIORITIES 最好设置为一个满足应用的最小值。 优先级数字越低表示任务的优先级越低,0 的优先级最低,configMAX_PRIORITIES-1 的优 先级最高。空闲任务的优先级最低,为 0。 FreeRTOS 调度器确保处于就绪态或运行态的高优先级的任务获取处理器使用权,换句话说 就是处于就绪态的最高优先级的任务才会运行。当宏 configUSE_TIME_SLICING 定义为 1 的时 候多个任务可以共用一个优先级,数量不限。默认情况下宏 configUSE_TIME_SLICING 在文件 FreeRTOS.h 中已经定义为 1。此时处于就绪态的优先级相同的任务就会使用时间片轮转调度器 获取运行时间。综合所述,优先级可设置的范围为1~31,优先级数字越小优先级越低,优先级可设置为同样的,同样的优先级则按时间先后来进行

三、任务实现:

        在使用 FreeRTOS 的过程中,我们要使用函数 xTaskCreate()或 xTaskCreateStatic()来创建任 务,这两个函数的第一个参数 pxTaskCode,就是这个任务的任务函数。什么是任务函数?任务 函数就是完成本任务工作的函数。我这个任务要干嘛?要做什么?要完成什么样的功能都是在 这个任务函数中实现的。 比如我要做个任务,这个任务要点个流水灯,那么这个流水灯的程序 就是任务函数中实现的。FreeRTOS 官方给出的任务函数模板如下

void vATaskFunction(void *pvParameters) (1)
{
    for( ; ; ) (2)
    {
        --任务应用程序-- (3)
        vTaskDelay(); (4)
    }
     /*不能从任务函数中返回或者退出, 从任务函数中返回或退出的话就会调用
configASSERT(),前提是你定义了 configASSERT()。如果一定要从任务函数中退出的话那一定要调用函数 vTaskDelete(NULL)来删除此任务。*/

    vTaskDelete(NULL); (5)
}

 (1)、任务函数本质也是函数,所以肯定有任务名什么的,不过这里我们要注意:任务函数 的返回类型一定要为 void 类型,也就是无返回值,而且任务的参数也是 void 指针类型的!任务 函数名可以根据实际情况定义。

(2)、任务的具体执行过程是一个大循环,for(; ; )就代表一个循环,作用和 while(1)一样,笔者习惯用 while(1)。

(3)、循环里面就是真正的任务代码了,此任务具体要干的活就在这里实现!

(4)、FreeRTOS 的延时函数,此处不一定要用延时函数,其他只要能让 FreeRTOS 发生任务 切换的 API 函数都可以,比如请求信号量、队列等,甚至直接调用任务调度器。只不过最常用 的就是 FreeRTOS 的延时函数。

(5)、任务函数一般不允许跳出循环,如果一定要跳出循环的话在跳出循环以后一定要调用 函数 vTaskDelete(NULL)删除此任务! FreeRTOS 的任务函数和 UCOS 的任务函数模式基本相同的,不止 FreeRTOS,其他 RTOS 的任务函数基本也是这种方式的。

四、任务控制块:

        FreeRTOS 的每个任务都有一些属性需要存储,FreeRTOS 把这些属性集合到一起用一个结 构体来表示,这个结构体叫做任务控制块:TCB_t,在使用函数 xTaskCreate()创建任务的时候就 会自动的给每个任务分配一个任务控制块。在老版本的 FreeRTOS 中任务控制块叫做 tskTCB, 新版本重命名为 TCB_t,但是本质上还是 tskTCB,本教程后面提到任务控制块的话均用 TCB_t 表示,此结构体在文件 tasks.c 中有定义,如下:

typedef struct tskTaskControlBlock
{
    volatile StackType_t *pxTopOfStack; //任务堆栈栈顶
    #if ( portUSING_MPU_WRAPPERS == 1 )
        xMPU_SETTINGSxMPUSettings; //MPU 相关设置
    #endif

    ListItem_t xStateListItem; //状态列表项
    ListItem_t xEventListItem; //事件列表项
    UBaseType_t uxPriority; //任务优先级
    StackType_t *pxStack; //任务堆栈起始地址
    char pcTaskName[ configMAX_TASK_NAME_LEN ];//任务名字

    #if ( portSTACK_GROWTH > 0 )
        StackType_t *pxEndOfStack; //任务堆栈栈底
    #endif

    #if ( portCRITICAL_NESTING_IN_TCB == 1 )
        UBaseType_t uxCriticalNesting; //临界区嵌套深度
    #endif

    #if ( configUSE_TRACE_FACILITY == 1 ) //trace 或到 debug 的时候用到
        UBaseType_t uxTCBNumber;
        UBaseType_t uxTaskNumber;
    #endif

    #if ( configUSE_MUTEXES == 1 )
        UBaseType_t uxBasePriority; //任务基础优先级,优先级反转的时候用到
        UBaseType_t uxMutexesHeld; //任务获取到的互斥信号量个数
    #endif

    #if ( configUSE_APPLICATION_TASK_TAG == 1 )
        TaskHookFunction_t pxTaskTag;
    #endif

    #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) //与本地存储有关
        void 
*pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
    #endif

    #if( configGENERATE_RUN_TIME_STATS == 1 )
        uint32_t ulRunTimeCounter; //用来记录任务运行总时间
    #endif

    #if ( configUSE_NEWLIB_REENTRANT == 1 )
        struct _reent xNewLib_reent; //定义一个 newlib 结构体变量
    #endif

    #if( configUSE_TASK_NOTIFICATIONS == 1 )//任务通知相关变量
        volatile uint32_t ulNotifiedValue; //任务通知值
        volatile uint8_t ucNotifyState; //任务通知状态
    #endif

    #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
        //用来标记任务是动态创建的还是静态创建的,如果是静态创建的此变量就为 pdTURE,
        //如果是动态创建的就为 pdFALSE
        uint8_t ucStaticallyAllocated; 
    #endif

    #if( INCLUDE_xTaskAbortDelay == 1 )
        uint8_t ucDelayAborted;
    #endif

} tskTCB;

//新版本的 FreeRTOS 任务控制块重命名为 TCB_t,但是本质上还是 tskTCB,主要是为了兼容
//旧版本的应用。
typedef tskTCB TCB_t;

        可以看出来 FreeRTOS 的任务控制块中的成员变量相比 UCOSIII 要少很多,而且大多数与 裁剪有关,当不使用某些功能的时候与其相关的变量就不参与编译,任务控制块大小就会进一 步的减小。

五、任务堆栈:

         FreeRTOS 之所以能正确的恢复一个任务的运行就是因为有任务堆栈在保驾护航,任务调度器在进行任务切换的时候会将当前任务的现场(CPU 寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行。创建任务的时候需要给任务指定堆栈,如果使用的函数 xTaskCreate()创建任务(动态方法) 的话那么任务堆栈就会由函数 xTaskCreate()自动创建,如果使用函数 xTaskCreateStatic()创建任务(静态方法)的话就需要程序员自行定义任务堆栈

六、任务创建和删除API函数:

FreeRTOS 最基本的功能就是任务管理,而任务管理最基本的操作就是创建和删除任务, FreeRTOS 的任务创建和删除 API 函数如下表所示:

6.1、函数 xTaxkCreate()(动态)

        此函数用来创建一个任务,任务需要 RAM 来保存与任务有关的状态信息(任务控制块),任 务也需要一定的 RAM 来作为任务堆栈。如果使用函数 xTaskCreate()来创建任务的话那么这些 所需的 RAM 就会自动的从 FreeRTOS 的堆中分配,因此必须提供内存管理文件,默认我们使用 heap_4.c 这个内存管理文件,而且宏 configSUPPORT_DYNAMIC_ALLOCATION 必须为 1。如 果使用函数 xTaskCreateStatic()创建的话这些 RAM 就需要用户来提供了。新创建的任务默认就 是就绪态的,如果当前没有比它更高优先级的任务运行那么此任务就会立即进入运行态开始运 行,不管在任务调度器启动前还是启动后,都可以创建任务。此函数也是我们以后经常用到的, 本教程所有例程均用此函数来创建任务,函数原型如下:

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                        const char * const pcName,
                        const uint16_t usStackDepth,
                        void * const pvParameters,
                        UBaseType_t uxPriority,
                        TaskHandle_t * const pxCreatedTask )

参数:

pxTaskCode: 任务函数。

pcName: 任务名字,一般用于追踪和调试,任务名字长度不能超过。 configMAX_TASK_NAME_LEN。

usStackDepth: 任务堆栈大小,注意实际申请到的堆栈是 usStackDepth 的 4 倍。其中空闲任 务的任务堆栈大小为 configMINIMAL_STACK_SIZE。

pvParameters: 传递给任务函数的参数。 uxPriotiry: 任务优先级,范围 0~ configMAX_PRIORITIES-1。

pxCreatedTask: 任务句柄,任务创建成功以后会返回此任务的任务句柄,这个句柄其实就是 任务的任务堆栈。此参数就用来保存这个任务句柄。其他 API 函数可能会使 用到这个句柄。

返回值:

pdPASS: 任务创建成功。

errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 任务创建失败,因为堆内存不足!

6.2、函数 vTaskDelete()(删除)

        删除一个用函数 xTaskCreate()或者 xTaskCreateStatic()创建的任务,被删除了的任务不再存 在,也就是说再也不会进入运行态。任务被删除以后就不能再使用此任务的句柄!如果此任务 是使用动态方法创建的,也就是使用函数 xTaskCreate()创建的,那么在此任务被删除以后此任 务之前申请的堆栈和控制块内存会在空闲任务中被释放掉,因此当调用函数 vTaskDelete()删除 任务以后必须给空闲任务一定的运行时间。 只有那些由内核分配给任务的内存才会在任务被删除以后自动的释放掉,用户分配给任务 的内存需要用户自行释放掉,比如某个任务中用户调用函数 pvPortMalloc()分配了 500 字节的内 存,那么在此任务被删除以后用户也必须调用函数 vPortFree()将这 500 字节的内存释放掉,否 则会导致内存泄露。此函数原型如下:

vTaskDelete( TaskHandle_t xTaskToDelete )

参数:

xTaskToDelete: 要删除的任务的任务句柄。

返回值:

七、任务创建和删除实验(动态):

        本实验设计三个任务:start_task、task1_task 和 task2_task ,这三个任务的任务功能如下: start_task:用来创建其他两个任务。

task1_task :当此任务运行 5 次以后就会调用函数 vTaskDelete()删除任务 task2_task,此任务也会控制 LED0 的闪烁

task2_task :此任务普通的应用任务,此任务也会控制 LED1 的闪烁

首先我们先打开上一节的跑马灯实验,然后把多余的代码删除掉,删除后的main.c界面如下图显示:

删除完毕之后,我们先对start_task任务的优先级、堆栈、句柄、函数进行表示,如下图所示:

紧接着,我们开始调用函数xTaxkCreate()创建 start_task 任务,函数中的各个参数就是上图里所定义的,其他任务的创建也用这种方法。创建完成之后调用函数vTaskStartScheduler()开启 FreeRTOS 的任务调度器,FreeRTOS 开始运行,如下图所示:

start_task()任务创建完成之后,接着我们要编写start_task()任务要实现的功能,参照我们之前设定的实验目标,start_task()任务是用于创建另外两个任务的,因此我们在start_task()的任务函数中进行另外两个任务的创建,并在创建完成之后调用函数vTaskDelete()删除掉start_task()任务自身。如下图所示:

PS:自行参照上面的方法分别对task1_task(),task2_task()任务参数进行表示

最后按照我们之前设定的实验目标,开始编写task1_task(),task2_task()任务所要实现的功能,如下图所示:

PS:变量stata是起一个标志位的作用,用于防止变量num在计数到达255之后会自动清零,清零之后会重新计数,在计数再次到达5之后又一次执行删除任务,从而报错的问题

 最终实现的效果如图所示:

task1_task()任务在运行到第五次的时候,调用函数将task2_task()任务删除,紧接着task1_task()继续运行,task2_task()则不再运行

 至此,我们的实验宣告成功,希望各位能从中有所收获,最后附上完整的main.c代码

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "FreeRTOS.h"
#include "task.h"

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

#define TASK1_TASK_PRIO   3           //任务优先级
#define TASK1_STK_SIZE    128         //任务堆栈大小
TaskHandle_t Task1Task_Handler; 	  //任务句柄
void task1_task(void *pvParameters);  //任务函数

#define TASK2_TASK_PRIO   2           //任务优先级
#define TASK2_STK_SIZE    128         //任务堆栈大小
TaskHandle_t Task2Task_Handler; 	  //任务句柄
void task2_task(void *pvParameters);  //任务函数

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4 	 	 
	delay_init();	    				//延时函数初始化
	uart_init(115200);					//初始化串口
	LED_Init();		  					//初始化LED
	
	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);  //任务句柄       
  vTaskStartScheduler();          //开始任务调度
}
//start_task任务函数
void start_task(void *pvParameters)  
{
	while(1)
	{
	  	taskENTER_CRITICAL(); //进入临界区
			xTaskCreate( (TaskFunction_t)  task1_task,  		//任务函数
						 (const char *  )  "task1_task",        //任务名称
                         (uint16_t      )  TASK1_STK_SIZE,      //任务堆栈大小
                         (void *        )  NULL,				//传递给任务函数的参数
                         (UBaseType_t   )  TASK1_TASK_PRIO,     //任务优先级
                         (TaskHandle_t *)  &Task1Task_Handler); //任务句柄
									 
			xTaskCreate( (TaskFunction_t)  task2_task,  		//任务函数
					     (const char *  )  "task2_task",  	    //任务名称
                         (uint16_t      )  TASK2_STK_SIZE,      //任务堆栈大小
                         (void *        )  NULL,				//传递给任务函数的参数
                         (UBaseType_t   )  TASK2_TASK_PRIO,     //任务优先级
                         (TaskHandle_t *)  &Task2Task_Handler); //任务句柄	
									 
			vTaskDelete(StartTask_Handler); //删除start_task()任务
			taskEXIT_CRITICAL(); //退出临界区								 
	}
}

//task1_task任务函数
void task1_task(void *pvParameters)
{
		int i=0;
		int num=0;
		int stata=1;
    while(1)
    {
			  i++;num++;
        LED0=~LED0;
				
				printf("\r\n正在运行task1_task:%d\r\n",num);
				if(stata==1)
				{
					if(i==5)
					{
						vTaskDelete(Task2Task_Handler);
						stata=0;
						printf("\r\n删除task2_task任务!!\r\n");
					}
				}
			 vTaskDelay(500);
    }
}

//task2_task任务函数
void task2_task(void *pvParameters)
{
	while(1)
	{
			LED1=1;
			vTaskDelay(500);
			LED1=0;
			vTaskDelay(800);
			printf("\r\n正在运行tatk2_task\r\n");
	}
}
 
 


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F1--FreeRTOS系统学习(二):任务创建与删除(动态) 的相关文章

  • 51红外循迹智能车——红外循迹模块设计

    目录 赛道环境 红外传感器的特征 TCRT5000传感器 LM339单限电压比较器 LM339简介 编辑 单限电压比较器仿真 红外循迹模块的设计 红外循迹模块原理图 红外循迹模块原理图讲解 赛道环境 上图为赛道示意图 xff0c 两端为黑色
  • 开发板烧写程序方法

    开发板烧写程序方法 如果开发板上没有预装bootloader程序 xff0c 那么可以通过JTAG进行烧写 常用的JTAG工具有并口JTAG xff0c 它的特点是便宜但是速度比较慢 USB转JTAG RS232串口二合一的工具OpenJT
  • 51单片机——汇编指令合集

    目录 指令格式 编译语句实例 单片机的寻址方式 立即数 xff08 Immediate Constants xff09 寻址方式 直接 xff08 Direct Addressing xff09 寻址方式 寄存器 xff08 Registe
  • 电子专业英语(持续更新)

    前言 23考研刚刚结束 xff0c 但在我复试的两个学校的专业英语翻译我都不会 发现自己在专业英语方面很差 xff0c 故写此文章记录我专业英语的学习历程 2023 4 17日学习 Analog n l signal 模拟信号 Contin
  • HttpServletRequest详解

    HttpServletRequest 详解 HttpServletRequest对象代表客户端的请求 xff0c 当客户端通过HTTP协议访问服务器时 xff0c HTTP请求头中的所有信息都封装在这个对象中 xff0c 通过这个对象提供的
  • 串口通信协议---UART

    串口通信的分类 UART属于串行 异步 全双工通信 串行通信与并行通信 根据传输数据的位宽 xff0c 串口通信可分为串行通信与并行通信 xff0c 串行通信是指设备之间通过少量数据信号线 一般是 8 根以下 xff0c 地线以及控制信号线
  • Django request请求和response响应介绍

    目录 一 request请求 1 request GET 2 request POST 3 request META 4 request headers 5 request method 6 request path 二 response对
  • 2022电赛C题——跟随小车 总结

    目录 一 前言 二 电赛回顾 三 比赛原因总结 1 准备不充分 2 队友配合不好 3 总体进程安排有问题 四 小车题经验和教训 五 电赛总结与收获 一 前言 今年参加了省电子设计大赛 xff0c 做的是控制类的小车题目 xff0c 今天下午
  • 设计一个代码,可以把int类型数据从小端序转成大端序

    设计一个代码 xff0c 可以把int类型数据从小端序转成大端序 1 位移 include lt stdio h gt 把int类型数据从小端序转成大端序 void main int n 61 0x12345678 char p 61 ch
  • 使用select函数搭建TCP客户端和服务器

    select的TCP服务器 include lt stdio h gt include lt sys types h gt include lt sys socket h gt include lt arpa inet h gt inclu
  • Linux--UDP编程

    目录 一 实现的过程 二 代码 xff1a 1 ser c 2 cli c 三 运行结果 四 服务器端断开重运行 xff0c 客户端还能发送吗 xff1f xff08 可以 xff09 五 可以同时运行两个客户端吗 xff1f xff08
  • 51单片机串行通信奇偶校验的设置方法

    51单片机串行通信奇偶校验的设置方法 悬赏分 xff1a 10 解决时间 xff1a 2009 12 5 10 21 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 6
  • pycharm连接VMware

    一 上传目录的配置 1 打开虚拟机 xff0c 进入终端查看host ip addr 输出此命令 记住下面会用到 2 打开pycharm新建一个py文件 3 点击ok后会出现如下图 设置好后先点击1 xff0c 测试是否连接成功 xff0c
  • 请确保您已登录客户机操作系统。在客户机中装载CD驱动器启动终端,使用tar解压缩安装程序,然后执行vmware-insall.pl安装VMware Tools。

    解决Ubuntu安装VM Tools请确保您已登录客户机操作系统 在客户机中装载CD驱动器启动终端 xff0c 使用tar解压缩安装程序 xff0c 然后执行vmware insall pl安装VMware Tools whafal的博客
  • 使用SSH远程连接工具(MOBAXTERM)连接虚拟机时输入中文乱码问题

    使用SSH远程连接工具连接虚拟机时输入中文乱码问题 一 xff1a 出现的中文输入问题 二 xff1a 造成的可能原因和出现原因的环境 出现原因的环境 xff1a 本机环境win10 xff0c 虚拟机环境centos7 出现这样情况的可能
  • vscode的alt+b失效解决

    1 先安装插件 xff0c 如下 2 一共有两种方式打开浏览器 xff0c 一个是alt 43 b xff0c 还有一个是alt 43 shift 43 b 但是对于刚安装上open in browser插件 xff0c alt 43 b是
  • 解决ERROR 2003 (HY000): Can’t connect to MySQL server on ‘localhost’ (10061)

    如何解决ERROR 2003 HY000 Can t connect to MySQL server on localhost 10061 1 登录到安装Mysql的主机 xff0c 打开cmd命令行工具 xff0c 执行命令mysql u
  • vscode中converting to execution character set: Illegal byte sequence

    我的这个问题是由于之前跟博主安装的时候在tasks json文件中添加了 34 fexec charset 61 GBK 34 删除后便可以正常运行了 当时即使我没添加这个代码控制台也没出现乱码的情况 xff0c 但还是加上了 xff0c
  • 工作日志day04

    再次安装虚拟机时常见的不确定点 软件选择 安装位置 点击完成 设置用户名的时候可能与数字 xff0c 以及强度有关 注销以管理员身份登录填写root用户名和自己设的密码 网络设置之后可以ping通 sudo yum y install tr
  • linux

    目录 基本命令 文件和用户管理 用户 创建用户 删除用户 修改用户属性 用户组 创建组 组的类型 提权 用户的权限 基本权限UGO 权限的三类对象 权限的三种类型 设置权限 编写程序 增加执行权限 更改属主 xff0c 属组 基本权限ACL

随机推荐

  • 机器学习.

    目录 一 机器学习概述 1 1人工智能概述 1 2什么是机器学习 1 2 1定义 1 2 2解释 1 2 3数据集的构成 1 3机器学习算法分类 1 3 1总结 1 3 2机器学习算法分类 1 4机器学习开发流程 1 5学习框架和资料介绍
  • NMEA-0813协议报文解析(QT/C++)

    文章目录 一 协议说明 二 具体实现 1 GNRMC 2 GNGGA 总结 一 协议说明 34 GN 34 联合模式协议头 xff1b 34 GP 34 GPS模式协议头 xff1b 34 GL 34 GLONASS模式协议头 xff1b
  • 寄存器位设置

    作为嵌入式工程师 xff0c 一定要掌握寄存器的控制 xff0c 想要了解基本的寄存器控制 xff0c 最简单的方法就是使用单片机练手 xff0c 51 xff0c stm0 xff0c stm8 xff0c MSP430等 xff0c 与
  • STM32 —— STM32 的串口通信

    STM32 STM32 的串口通信 STM32的串口通信接口有两种 xff0c 分别是 xff1a UART 通用异步收发器 USART 通用同步异步收发器 而对于大容量 STM32F10x 系列芯片 xff0c 分别有 3 个 USART
  • STM32 —— 串口数据接收

    STM32 串口接收数据 我们已经在前面的博客中讲过了串口通信中发送数据和中断的一些基本原理 xff0c 这里主要介绍串口接收数据的相关内容 定长字符串的接收 当接收单字节时 xff0c 我们就可以使用最简单的接收方式即可 xff0c 这种
  • 远距离WiFi模块,无人机传输技术,无线通信视频传输技术

    随着科技的发展 xff0c 无人机应用范围的不断扩展且愈加广泛 无人机的起飞 xff0c 航行 xff0c 悬停 xff0c 返回的任何一个阶段 xff0c 都需要进行无线遥控 xff0c 这就需要很高的灵敏度了 同时在无人机飞行的过程中
  • OpenMV:14巡线小车

    文章目录 追小球的小车巡线小车 这个例子展示了在OpenMV Cam上使用get regression xff08 xff09 方法获得ROI的线性回归 使用这种方法 xff0c 可以轻松让机器人跟踪所有指向相同大致方向的线 本例程可以用于
  • OpenMV:16神经网络

    文章目录 导论利用神经网络进行特征识别 已停用 神经网络检测函数检测函数 96 tf classify 96 返回值加载神经网络函数 96 tf load 返回值 96 例程1 图像中央人检测例程2 整幅图像人脸检测 导论 OpenMV内置
  • OpenMV:19OpenMV4 Plus训练神经网络进行口罩识别

    文章目录 1 采集2 连接3 训练复制API KEY上传照片模型创建生成神经网络训练神经网络测试神经网络备份保存 4 下载代码分析 注意 xff1a 只有 OpenMV4 Plus可以自己训练神经网络 xff0c 其他版本的性能不够 本节讲
  • OpenMV:21控制多个舵机(需要模块PCA9685)

    文章目录 连接代码控制单个舵机的旋转pc8596 pyservo pymain py利用两个舵机拓展板控制16个舵机 今天我们来学习下 OpenMV的舵机拓展板来控制多个舵机同时使用 如果我们想控制三个以上的舵机 xff0c 就需要用到舵机
  • OpenMV:22电机扩展板控制直流电机

    文章目录 电机拓展板产品介绍代码 今天为大家讲解下 OpenMV配套的电机扩展板 我们需要自己焊接插针 在使用电机扩展板时 xff0c 我们的电机扩展板需要外接一个6V 12V的电源 xff0c 来为电机供电 xff1b 电机扩展板同时会使
  • OpenMV:23串口发送数据

    文章目录 产品Hello World简单的数据发送 本节讲解 如何使用OpenMV通过串口来发送数据 OpenMV 是可以直接通过串口发送字符串的 为什么要用串口呢 xff1f 因为要时候需要把信息传给其他MCU xff08 单片机 xff
  • HTTP AUTH验证

    何为http auth http auth是一种基础的用户验证 xff0c 原理是将用户名 密码base64加密后放在http的请求头部Authorization 发给服务器 浏览器的做法 当你访问一个需要http auth验证的资源时 x
  • OpenMV与Arduino通信—串口

    文章目录 96 Arduino 96 的串口函数接收函数 96 Serial read 96 检测串口 96 Serial available 96 串口通信例程 96 OpenMV 96 代码 96 Arduino 96 代码 所有要进行
  • OpenCV:08图像金字塔

    目录 图像金字塔图像金字塔介绍高斯金字塔 xff08 Gaussian pyramid xff09 向下采样向上采样 拉普拉斯金字塔 图像直方图图像直方图的基本概念直方图术语使用 96 OpenCV 96 统计直方图使用 96 OpenCV
  • OpenCV:09车辆统计项目

    车辆统计项目 涉及到的内容大体流程知识补充背景减除 具体流程视频加载去除背景形态学识别车辆对车辆进行统计显示车辆统计信息 效果图 xff1a 涉及到的内容 窗口的展示图像 视频的加载基本图像的绘制 车辆识别 基本图像运算与处理形态学轮廓查找
  • OpenCV:10特征检测

    特征检测的基本概念 特征检测是计算机视觉和图像处理中的一个概念 它是指使用计算机提取图像信息 xff0c 决定每个图像的点是否属于一个图像特征 特征检测的结果是把图像上的点分为不同的子集 xff0c 这些子集往往属于孤立的点 连续的曲线或者
  • Android-自定义圆形ProgressBar加载

    帮朋友做个圆形加载进度条 xff0c 后来发现做的挺简单的 xff0c 大佬一个比一个厉害 介绍一下 xff1a 1 自定义View属性 2 View 的测量 3 计算绘制 View 所需参数 4 圆弧的绘制及渐变的实现 5 文字的绘制 效
  • VINS-MONO的安装与运行

    1 安装ros 网上大量教程 2 安装ceres 1 14 0版本 源码安装 xff0c 有依赖 xff09 安装mkdir build cd build cmake make sudo make install xff08 亲测2 0版本
  • STM32F1--FreeRTOS系统学习(二):任务创建与删除(动态)

    以下内容皆是个人学习过程中的总结 xff0c 记录一下整个过程 xff0c 用于后期复习 xff0c 如有不对之处 xff0c 麻烦各位大佬指出 xff08 喜欢的朋友麻烦点个关注 后期还会进行持续更新 xff09 在FreeRTOS 中应