freertos——任务通知知识总结与任务通知模拟及信号量实验、消息邮箱实验、事件标志组实验

news2024/11/15 5:02:43

1.任务通知概念

任务通知:用来通知任务的,任务控制块中的结构体成员变量 ulNotifiedValue就是这个通知值,不需要另外创建一个结构体可以直接接受别人发过来的通知
在这里插入图片描述

2.任务通知的优势及劣势

任务通知的优势:
效率更高 :使用任务通知向任务发送事件或数据比使用队列、事件标志组或信号量快得多
使用内存更小:使用其他方法时都要先创建对应的结构体,使用任务通知时无需额外创建结构体

任务通知的劣势:
无法发送数据给ISR:ISR没有任务结构体,所以无法给ISR发送数据。但是ISR可以使用任务通知的功能,发数据给任务。
无法广播给多个任务:任务通知只能是被指定的一个任务接收并处理
无法缓存多个数据:任务通知是通过更新任务通知值来发送数据的,任务结构体中只有一个任务通知值,只能保持一个数据。
发送受阻不支持阻塞:发送方无法进入阻塞状态等待

3.任务结构体中任务通知值和通知状态

typedef  struct  tskTaskControlBlock 
{
	… …
    	#if ( configUSE_TASK_NOTIFICATIONS  ==  1 )
        	volatile  uint32_t    ulNotifiedValue [ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
        	volatile  uint8_t      ucNotifyState [ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
    	endif
	… …
} tskTCB;
#define  configTASK_NOTIFICATION_ARRAY_ENTRIES	1  	/* 定义任务通知数组的大小, 默认: 1

一个是 uint32_t 类型,用来表示通知值
一个是 uint8_t 类型,用来表示通知状态

4 任务通知状态

#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* 任务未等待通知 /
#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 ) /
任务在等待通知 /
#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) /
任务在等待接收 */
未等待通知:初始化状态
等待通知:接收方已经准备好了(调用了接收任务通知函数),等待发送方给个通知
等待接收:发送方已经发送出去(调用了发送任务通知函数),等待接收方接收

5.任务通知API函数

1)发送通知相关API函数
在这里插入图片描述
注意;发送通知API函数可以用于任务和中断服务函数中
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue)
在这里插入图片描述
2)接收任务通知相关API函数
在这里插入图片描述
1)#define ulTaskNotifyTake( xClearCountOnExit , xTicksToWait )
ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ),
( xClearCountOnExit ),
\ ( xTicksToWait ) )
形参: uxIndexToWaitOn 任务的指定通知(任务通知相关数组成员)
xClearCountOnExit 指定在成功接收通知后,将通知值清零或减 1,
pdTRUE:把通知值清零;
pdFALSE:把通知值减一
xTicksToWait 阻塞等待任务通知值的最大时间

返回值:0 接收失败
其他 接收成功,返回任务通知的通知值

2)#define xTaskNotifyWait( ulBitsToClearOnEntry, \
ulBitsToClearOnExit, \
pulNotificationValue, \
xTicksToWait)
xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY,
\ ( ulBitsToClearOnEntry ),
\ ( ulBitsToClearOnExit ),
\ ( pulNotificationValue ),
\ ( xTicksToWait ) )

形参: uxIndexToWaitOn 任务的指定通知(任务通知相关数组成员)
ulBitesToClearOnEntry 等待前清零指定任务通知值的比特位(旧值对应bit清0)
ulBitsToClearOnExit 成功等待后清零指定的任务通知值比特位(新值对应bit清0)
pulNotificationValue 用来取出通知值(如果不需要取出,可设为NULL)
xTicksToWait 阻塞等待任务通知值的最大时间

返回值:0 接收失败
其他 接收成功,返回任务通知的通知值

总结:
1)当任务通知用作于信号量时,使用函数获取信号量:ulTaskNotifyTake()
2)当任务通知用作于事件标志组或队列时,使用此函数来获取: xTaskNotifyWait()

6.任务通知的几种方式

typedef enum
{
eNoAction = 0, /* 无操作 /
eSetBits /
更新指定bit /
eIncrement /
通知值加一 /
eSetValueWithOverwrite /
覆写的方式更新通知值 /
eSetValueWithoutOverwrite /
不覆写通知值 */
} eNotifyAction;

7.任务通知模拟信号量实验

在这里插入图片描述
代码:

#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/*1.FreeRTOS配置*/

/* 1.1 START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

/* 1.2 TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

/* 1.3 TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

/**
 * 2 FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
    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();
}

/**
 * 3 start_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           /* 进入临界区 */
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    /* 创建任务2 */
    xTaskCreate((TaskFunction_t )task2,
                (const char*    )"task2",
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
    taskEXIT_CRITICAL();            /* 退出临界区 */
}

/**
 * 3 task1发送任务通知值
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task1(void *pvParameters)
{
    uint8_t key = 0;
    
    while (1)
    {
       
            key = key_scan(0);

            switch (key)
            {
                case KEY0_PRES:                                         /* 发送任务通知 */
                {
                    xTaskNotifyGive(Task2Task_Handler);
                    printf("任务通知发送,模拟二值信号量释放!\r\n");
                    break;
                }
                default:
                {
                    break;
                }
        }

        vTaskDelay(10);
    }
}

/**
 * 3 task2 接收任务通知值
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task2(void *pvParameters)
{
    uint32_t rev = 0;
    while (1)
    {
        rev = ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
        if(rev != 0)
        {
            printf("接收任务通知成功,模拟获取二值信号量!\r\n");
        }
    }
}

8.任务通知模拟计数型信号量实验

void task2(void *pvParameters)
{
    uint32_t rev = 0;
    while (1)
    {
        rev = ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
        if(rev != 0)
        {
            printf("rev:%d\r\n",rev);
        }
        vTaskDelay(1000);
    }
}

9.任务通知模拟事件标志组实验

在这里插入图片描述

#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*1.FreeRTOS配置*/

/* 1.1 START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

/* 1.2 TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

/* 1.3 TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

//1.4 位0、位1宏定义
#define EVENTBIT_0 (1 << 0)
#define EVENTBIT_1 (1 << 1)



/**
 * 2 FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
    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();
}

/**
 * 3 start_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           /* 进入临界区 */
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    /* 创建任务2 */
    xTaskCreate((TaskFunction_t )task2,
                (const char*    )"task2",
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
    taskEXIT_CRITICAL();            /* 退出临界区 */
}

/**
 * 3 task1发送任务通知值
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task1(void *pvParameters)
{
    uint8_t key = 0;
    
    while (1)
    {
       
            key = key_scan(0);

            switch (key)
            {
                case KEY0_PRES:                                         /* 发送任务通知 */
                {
                    printf("将bit0位置置1\r\n");
                    xTaskNotify( Task2Task_Handler,EVENTBIT_0, eSetBits);
                    break;
                }
                 case KEY1_PRES:                                         /* 发送任务通知 */
                {
                     printf("将bit1位置置1\r\n");
                    xTaskNotify( Task2Task_Handler,EVENTBIT_1, eSetBits);
                   
                    break;
                }
                default:
                {
                    break;
                }
            
        }
        
        vTaskDelay(10);
    }
}

/**
 * 3 task2 接收任务通知值
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task2(void *pvParameters)
{
    uint32_t notify_val = 0,event_bit=0;
    while (1)
    {
       xTaskNotifyWait( 0, 0xFFFFFFFF,&notify_val,portMAX_DELAY);
       if(notify_val & EVENTBIT_0)
       {
          event_bit |= EVENTBIT_0;
       } 
       if(notify_val & EVENTBIT_1)
       {
          event_bit |= EVENTBIT_1;
       } 
         if(event_bit ==( EVENTBIT_0 | EVENTBIT_1))
       {
          printf("任务通知模拟事件标志组接收成功\r\n");
          event_bit = 0;
       } 

    }
}

10.任务通知模拟消息邮箱实验

在这里插入图片描述


#include "freertos_demo.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
 #include "./BSP/LED/led.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*1.FreeRTOS配置*/

/* 1.1 START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

/* 1.2 TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

/* 1.3 TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

/******************************************************************************************************/



/**
 * 2 FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
    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();
}

/**
 * 3 start_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           /* 进入临界区 */
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    /* 创建任务2 */
    xTaskCreate((TaskFunction_t )task2,
                (const char*    )"task2",
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
    taskEXIT_CRITICAL();            /* 退出临界区 */
}

/**
 * 3 task1发送任务通知值
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task1(void *pvParameters)
{
    uint8_t key = 0;
    
    while (1)
    {
       
        key = key_scan(0);
        if((key != 0) && (Task2Task_Handler != NULL))
        {
            printf("任务通知模拟消息邮箱发送,发送的键值:%d\r\n",key);
            xTaskNotify(Task2Task_Handler,key,eSetValueWithOverwrite);
        }
        vTaskDelay(10);
    }
}

/**
 * 3 task2 接收任务通知值
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task2(void *pvParameters)
{
    uint32_t notify_val = 0;
    while (1)
    {
        xTaskNotifyWait(0,0xFFFFFFFF,&notify_val,portMAX_DELAY);
        switch(notify_val)
        {
            case KEY0_PRES:
                printf("接收到的通知为:%d\r\n",notify_val);
                LED0_TOGGLE();
                break;
             case KEY1_PRES:
                printf("接收到的通知为:%d\r\n",notify_val);
                LED1_TOGGLE();
                break;
             default : 
                break;
        }
    }
}

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

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

相关文章

基于Python+Django,开发一款房屋租赁系统

学习文档 学习过程中&#xff0c;遇到问题可以咨询作者 功能介绍 平台采用B/S结构&#xff0c;后端采用主流的PythonDjango进行开发&#xff0c;前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 前台功能包括&#xff1a;首页、房屋详情页、用户中心模块。…

卫星互联网与MEC融合方案研究

卫星互联网与MEC融合方案研究 作者&#xff1a;温特、王立中、司鹏、颜明明、马恬、郭伊蒙 中国卫通集团股份有限公司 本文首发&#xff1a;第十九届卫星通信学术年会 摘 要&#xff1a;在卫星互联网中引入移动边缘计算(MEC)技术可有效提高用户体验质量&#xff0c;降低运营成…

关掉RHEL 8安装软件包订阅注册

关掉RHEL订阅注册&#xff1a;&#xff08;关掉之后&#xff0c;在YUM的时候就不会有提示注册的信息了&#xff09; cd /etc/yum/pluginconf.d/ ls vim subscription-manager.conf可以看到enabled1&#xff0c;这个数值表明此时是允许订阅注册的。 此时安装软件包时&#xff…

kubectl的插件安装工具krew

最近得知一个kubectl插件安装工具&#xff0c;叫做krew。 官网地址是&#xff1a;Krew – kubectl plugin manager 安装krew 按照官网的做法&#xff0c;一直安装失败&#xff0c;于是拆解步骤&#xff0c;一步一步下载离线安装。 1、下载krew.yaml 地址&#xff1a;https:…

thinkphp6实现简单定时任务

thinkphp6实现定时任务 创建定时任务文件定义指令编写Test.php代码运行测试 创建定时任务文件 Test类名根据自己的需要修改 php think make:command Test testcommand文件夹在app目录下没有需要自己创建 运行上面的命令后会在command下 多一个Test.php文件 定义指令 在conf…

Stable Diffusion 系列教程 - 6 Dreambooth及训练

Stable-Diffusion、Imagen等文生图大模型已经具备了强大的生成能力&#xff0c;假设我们的Prompt为 [Cyberpunk Style]&#xff0c;SD或许能很快画出赛博朋克风格的一幅画。但你作为一个不知名的人&#xff0c;不能奢求SD在训练的时候把你自己想要的风格也加进去吧&#xff1f;…

爬虫实战3-js逆向入门:以黑猫投诉平台为例

目录 引言 逆向过程 步骤一&#xff1a;找到参数对应js代码位置 步骤二&#xff1a;分析参数值的生成逻辑 步骤三&#xff1a;确定函数u的具体内容 步骤四&#xff1a;使用python实现请求参数的生成 投诉信息爬取 引言 下面是一张主流网页加密方法的思维导图&#xff0…

Rustdesk打开Win10 下客户端下面服务不会自启,显示服务未运行

环境: Rustdesk1.19 问题描述: Rustdesk打开Win10 下客户端下面服务不会自启,显示服务未运行 解决方案: 1.查看源代码 pub async fn start_all() {crate::hbbs_http::sync::start();let mut nat_tested = false;check_zombie()

税法相关的基础知识

文章目录 税法原则1.税法基本原则2.税法适用原则 来和大家聊聊税法相关的基础知识 税法原则 1.税法基本原则 2.税法适用原则

1329:【例8.2】细胞 广度优先搜索

1329&#xff1a;【例8.2】细胞 时间限制: 1000 ms 内存限制: 65536 KB 【题目描述】 一矩形阵列由数字0 到9组成,数字1到9 代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。如: 4 10 0234500067 1034560500 2045600671 00000000…

超声波模块的驱动(STM32、51单片机等)

一、前言 本文旨在分享单片机对超声波模块的驱动&#xff0c;测量距离和显示 二、超声波的驱动 1、超声波模块 2、模块性能 &#xff08;1&#xff09;TCT40-16T/R1 压电陶瓷超声传感器&#xff08;通用型&#xff09; 3、接口定义 Vcc、 Trig&#xff08;控制端&#xff09…

一款开源的MES系统

随着工业4.0的快速发展&#xff0c;制造执行系统&#xff08;MES&#xff09;成为了智能制造的核心。今天&#xff0c;将为大家推荐一款开源的MES系统——iMES工厂管家。 什么是iMES工厂管家 iMES工厂管家是一款专为中小型制造企业打造的开源MES系统。它具备高度的可定制性和灵…

【无线通信专题】NFC通信模式及可能的应用方式

在文章【无线通信专题】NFC基本原理中我们讲到了NFC工作模式。其中NFC工作模式主要有三种,读写模式、卡模拟模式、点对点模式。 NFC通信模式丰富,NFC Forum定义了三种NFC设备:通用NFCForum设备、读写器设备和标签设备。这些NFC设备可以在三种通信模式下运行,并对应用案例进…

docker、docker-compose 离线安装、shell脚本一键安装、卸载

注&#xff1a;二进制包&#xff0c;与脚本在同级目录 docker 离线安装&#xff1a; 包下载&#xff1a;https://download.docker.com/linux/static/stable/x86_64/ docker_install.sh&#xff1a; #!/bin/bash# 指定 Docker 版本和文件名 DOCKER_VERSION"24.0.7" D…

FreeRTOS移植详解

一、前言 本文旨在讲解FreeRTOS在STM32单片机上的移植步骤&#xff0c;对于FreeRTOS在其他单片机上的移植已具有一定的参考意义。相信读者在看完这篇文章后&#xff0c;一定会有所收获&#xff01; 文末附有相关资料连接&#xff0c;有需要的读者可以自行下载。 二、FreeRTOS源…

【自动驾驶中的SLAM技术】第2讲:基础数学知识回顾

第二讲&#xff1a;基础数学回顾 文章目录 第二讲&#xff1a;基础数学回顾1 几何学1.1 坐标系1.2 坐标变换① 空间向量② 基变换③ 坐标变换④ 总结 1.3 四元数与旋转向量 2 运动学2.1 李群视角2.2 四元数视角2.3 四元数的李代数与旋转向量间的转换2.4 SO(3)t 上的运动学2.5 线…

视频剪辑技巧:添加srt字幕,提升视频品质的方法

在视频制作和剪辑过程中&#xff0c;字幕的添加是一项常见的技巧。通过添加srt字幕&#xff0c;可以提升视频的品质和观感&#xff0c;让观众更好地理解视频内容。下面一起来看云炫AI智剪如何批量添加srt字幕的方法&#xff0c;如何通过这些技巧提升视频品质。 原视频画面与添…

【Docker基础二】Docker安装Mysql8

下载镜像 安装mysql&#xff08;版本&#xff1a;8.0.35&#xff09; # 拉取镜像 docker pull mysql:8.0.35 # 查看镜像是否已经下载 docker images 创建挂载目录 # 宿主机上创建挂载目录 (可以不创建&#xff0c;docker run -v配置了挂载目录&#xff0c;docker会自动…

二分查找(一)

算法原理 原理&#xff1a;当一个序列有“二段性”的时候&#xff0c;就可以使用二分查找算法。 适用范围&#xff1a;根据规律找一个点&#xff0c;能将这个数组分成两部分&#xff0c;根据规律能有选择性的舍去一部分&#xff0c;进而在另一个部分继续查找。 除了最普通的…

使用ChatGPT生成项目需求文档模板

前言 我们在工作中需要编写的技术文档有多种形式&#xff0c;包括Word、Excel、PDF及一些在线形式。我们可以借助ChatGPT生成文本&#xff0c;然而&#xff0c;它不能直接生成Word、Excel、PDF等格式的文档。因此&#xff0c;我们需要利用其他工具来帮助我们生成一些模板&…