【freertos】FreeRTOS消息队列的介绍与使用

FreeRTOS消息队列的介绍与使用

  • 一、概述
  • 二、消息队列的运作机制
  • 三、API函数
    • 1、消息队列创建函数
    • 2、消息队列静态创建函数
    • 3、用于向队列尾部发送一个队列消息
    • 4、在中断服务程序中用于向队列尾部发送一个消息
    • 5、向队列队首发送一个消息
    • 6、在中断服务程序中向消息队列队首发送一个消息
    • 7、从一个队列中接收消息,并把接收的消息从队列中删除
    • 8、在中断中从一个队列中接收消息,并从队列中删除该消息
    • 9、pdMS_TO_TICKS函数使用
  • 四、消息队列使用注意事项
  • 五、示例代码
    • 1、任务间数据传输
    • 2、任务与中断间的数据传输
  • 六、pxHigherPriorityTaskWoken
    • 方式1:
    • 方式2:

一、概述

\quad 队列又称消息队列,是一种常用于任务间通信的数据结构,队列可以在任务与任务间、 中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列里面读取消息,当队列中的消息是空时,读取消息的任务将被阻塞,用户还可以指定阻塞的任务时间 xTicksToWait,在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。
\quad 当队列中有新消息时,被阻塞的任务会被唤醒并处理新消息;当等待的时间超过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转为就绪态。
\quad 消息队列是一种异步的通信方式。通过消息队列服务,任务或中断服务例程可以将一条或多条消息放入消息队列中。同样,一个或多个任务可以从消息队列中获得消息。当有多个消息发送到消息队列时,通常是将先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入消息队列的 消息,即先进先出原则(FIFO),但是也支持后进先出原则(LIFO)。
在这里插入图片描述
特性
FreeRTOS 中使用队列数据结构实现任务异步通信工作,具有如下特性:

  • 消息支持先进先出方式排队,支持异步读写工作方式。
  • 读写队列均支持超时机制。
  • 消息支持后进先出方式排队,往队首发送消息(LIFO)。
  • 可以允许不同长度(不超过队列节点最大值)的任意类型消息。
  • 一个任务能够从任意一个消息队列接收和发送消息。
  • 多个任务能够从同一个消息队列接收和发送消息。
  • 当队列使用结束后,可以通过删除队列函数进行删除。

消息队列可以应用于发送不定长消息的场合,包括任务与任务间的消息交换,队列是 FreeRTOS 主要的任务间通讯方式,可以在任务与任务间、中断和任务间传送信息,发送到队列的消息是通过拷贝方式实现的,这意味着队列存储的数据是原数据,而不是原数据的引用。

二、消息队列的运作机制

\quad 创建消息队列时 FreeRTOS 会先给消息队列分配一块内存空间,这块内存的大小等于消息队列控制块大小加上(单个消息空间大小与消息队列长度的乘积),接着再初始化消息队列,此时消息队列为空。FreeRTOS的消息队列控制块由多个元素组成,当消息队列被创建时,系统会为控制块分配对应的内存空间,用于保存消息队列的一些信息如消息的存 储位置,头指针 pcHead、尾指针 pcTail、消息大小uxItemSize以及队列长度uxLength等。同时每个消息队列都与消息空间在同一段连续的内存空间中,在创建成功的时候,这些内存就被占用了,只有删除了消息队列的时候,这段内存才会被释放掉,创建成功的时候就已经分配好每个消息空间与消息队列的容量,无法更改,每个消息空间可以存放不大于消息大小uxItemSize的任意类型的数据,所有消息队列中的消息空间总数即是消息队列的长度,这个长度可在消息队列创建时指定。

\quad 任务或者中断服务程序都可以给消息队列发送消息,当发送消息时,如果队列未满或者允许覆盖入队,FreeRTOS 会将消息拷贝到消息队列队尾,否则,会根据用户指定的阻塞超时时间进行阻塞,在这段时间中,如果队列一直不允许入队,该任务将保持阻塞状态以等待队列允许入队。当其它任务从其等待的队列中读取入了数据(队列未满),该任务将 自动由阻塞态转移为就绪态。当等待的时间超过了指定的阻塞时间,即使队列中还不允许 入队,任务也会自动从阻塞态转移为就绪态,此时发送消息的任务或者中断程序会收到一个错误码 errQUEUE_FULL。
\quad 发送紧急消息的过程与发送消息几乎一样,唯一的不同是,当发送紧急消息时,发送的位置是消息队列队头而非队尾,这样,接收者就能够优先接收到紧急消息,从而及时进行消息处理。
\quad 当某个任务试图读一个队列时,其可以指定一个阻塞超时时间。在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。当其它任务或中断服务程序往其等待的队列中写入了数据,该任务将自动由阻塞态转移为就绪态。当等待的时间超过了指 定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转移为就绪态。
\quad 当消息队列不再被使用时,应该删除它以释放系统资源,一旦操作完成,消息队列将被永久性的删除。

三、API函数

1、消息队列创建函数

 QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,UBaseType_t uxItemSize);

功能描述:用于创建一个新的队列。
参数:

  • uxQueueLength-队列能够存储的最大消息单元数目,即队列长度。
  • uxItemSize-队列中消息单元的大小,以字节为单位,该大小设置非常重要,否则得到的数据不完整。

返回值:

  • 成功-如果创建成功则返回一个队列句柄,用于访问创建的队列;
  • 失败-如果创建不成功则返回NULL,可能原因是创建队列需要的 RAM 无法分配成功。

2、消息队列静态创建函数

QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t *pucQueueStorageBuffer,StaticQueue_t *pxQueueBuffer );

功能描述:用于创建一个新的队列。
参数:

  • uxQueueLength-队列能够存储的最大消息单元数目,即队列长度。
  • uxItemSize-队列中消息单元的大小,以字节为单位。
  • pucQueueStorageBuffer-指针,指向一个 uint8_t 类型的数组,数组的大小至少有uxQueueLength*uxItemSize 个字节。当 uxItemSize 为 0 时,pucQueueStorageBuffer 可以为 NULL。
  • pxQueueBuffer-指针,指向 StaticQueue_t 类型的变量,该变量用于存储队列的数据结构。

返回值:

  • 成功-如果创建成功则返回一个队列句柄,用于访问创建的队列;
  • 失败-如果创建不成功则返回NULL,可能原因是创建队列需要的 RAM 无法分配成功。

3、用于向队列尾部发送一个队列消息

BaseType_t xQueueSend(QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait);

参数说明:

  • xQueue-队列句柄。
  • pvItemToQueue-指针,指向要发送到队列尾部的队列消息。
  • xTicksToWait-队列满时,等待队列空闲的最大超时时间。如果队列满并且xTicksToWait 被设置成0,函数立刻返回。超时时间的单位为系统节拍周期,常量 portTICK_PERIOD_MS 用于辅助计算真实的时间,单位为 ms。如果
    INCLUDE_vTaskSuspend 设置成 1,并且指定延时为 portMAX_DELAY 将导致任务挂起(没有超时)。

返回值:
\quad 消息发送成功成功返回 pdTRUE,否则返回 errQUEUE_FULL。

4、在中断服务程序中用于向队列尾部发送一个消息

BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);

参数说明:

  • xQueue-队列句柄。
  • pvItemToQueue-指针,指向要发送到队列尾部的消息。
  • pxHigherPriorityTaskWoken-如果入队导致一个任务解锁,并且解锁的任务优先级高于当前被中断的任务,则将*pxHigherPriorityTaskWoken设置成pdTRUE,然后在中断退出前需要进行一次上下文切换,去执行被唤醒的优先级更高的任务,可提高实时性。从FreeRTOS V7.3.0起,pxHigherPriorityTaskWoken 作为一个可选参数,可以设置为 NULL。

返回值:
\quad 消息发送成功成功返回 pdTRUE,否则返回 errQUEUE_FULL。

5、向队列队首发送一个消息

BaseType_t xQueueSendToFront( QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait );

参数说明:

  • xQueue-队列句柄。
  • pvItemToQueue-指针,指向要发送到队列尾部的消息。
  • xTicksToWait-队列满时,等待队列空闲的最大超时时间。如果队列满并且xTicksToWait 被设置成0,函数立刻返回。超时时间的单位为系统节拍周期,常量 portTICK_PERIOD_MS 用于辅助计算真实的时间,单位为 ms。如果 INCLUDE_vTaskSuspend 设置成 1,并且指定延时为 portMAX_DELAY 将导致任务无限阻塞(没有超时)。

返回值:
\quad 消息发送成功成功返回 pdTRUE,否则返回 errQUEUE_FULL。

6、在中断服务程序中向消息队列队首发送一个消息

BaseType_t xQueueSendToFrontFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);

参数说明:

  • xQueue-队列句柄。
  • pvItemToQueue-指针,指向要发送到队首的消息。
  • pxHigherPriorityTaskWoken-如果入队导致一个任务解锁,并且解锁的任务优先级高于当前被中断的任务,则将*pxHigherPriorityTaskWoken设置成pdTRUE,然后在中断退出前需要进行一次上下文切换,去执行被唤醒的优先级更高的任务。从FreeRTOS V7.3.0 起,pxHigherPriorityTaskWoken 作为一个可选参数,可以设置为 NULL。

返回值:
\quad 消息发送成功成功返回 pdTRUE,否则返回 errQUEUE_FULL。

7、从一个队列中接收消息,并把接收的消息从队列中删除

BaseType_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait);

参数说明:

  • xQueue-队列句柄。
  • pvBuffer-指针,指向接收到要保存的数据。
  • xTicksToWait-队列空时,阻塞超时的最大时间。如果该参数设置为 0,函数立刻返 回。超时时间的单位为系统节拍周期,常量portTICK_PERIOD_MS 用 于辅助计算真实的时间,单位为 ms。如果 INCLUDE_vTaskSuspend 设 置成1,并且指定延时为 portMAX_DELAY 将导致任务无限阻塞(没有超时)。

返回值:
\quad 队列项接收成功返回 pdTRUE,否则返回 pdFALSE。

若接收完消息,不想删除,可以使用xQueuePeek函数。

8、在中断中从一个队列中接收消息,并从队列中删除该消息

BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken);

参数说明:

  • xQueue-队列句柄。

pvBuffer-消息

  • pxHigherPriorityTaskWoken-在使用之前必须初始化成
    pdFALSE。如果API函数(即xQueueReceiveFromISR)导致一个任务解锁,并且解锁的任务优先级高于当前运行的任务,则API函数(即xQueueReceiveFromISR)将*pxHigherPriorityTaskWoken设置成pdTRUE。在中断退出前,触发一次任务切换。pxHigherPriorityTaskWoken作为一个可选参数,可以设置为NULL。

返回值:
\quad 队列项接收成功返回 pdTRUE,否则返回 pdFALSE。

9、pdMS_TO_TICKS函数使用

const TickType_t xTicksToWait = pdMS_TO_TICKS( 100 );

宏pdMS_TO_TICKS用于将毫秒转成节拍数,FreeRTOS V8.1.0及以上版本才有这个宏。

四、消息队列使用注意事项

  1. 使用 xQueueSend()、xQueueSendFromISR()、xQueueReceive()等这些函数之前应先创建需消息队列,并根据队列句柄进行操作。
  2. 队列读取采用的是先进先出(FIFO)模式,会先读取先存储在队列中的数据。当 然也 FreeRTOS 也支持后进先出(LIFO)模式,那么读取的时候就会读取到后进队列的数据。
  3. 在获取队列中的消息时候,我们必须要定义一个存储读取数据的地方,并且该数 据区域大小不小于消息大小,否则,很可能引发地址非法的错误。
  4. 无论是发送或者接收消息都是以拷贝的方式进行,当然,可以通过传递指针的指针解决大数据量拷贝慢的问题,可以将消息的地址作为消息进行发送、接收(同样也会存在其它问题,例如接收任务接收到数据之前,该区域内容不得更改等)。
  5. 队列是具有自己独立权限的内核对象,并不属于任何任务。所有任务都可以向同一队列写入和读出。一个队列由多任务或中断写入是经常的事,但由多个任务读出用的比较少。

五、示例代码

1、任务间数据传输

static TaskHandle_t app_task1_handle = NULL;
static TaskHandle_t app_task2_handle = NULL;/* 任务1 */ 
static void app_task1(void* pvParameters);  /* 任务2 */  
static void app_task2(void* pvParameters); QueueHandle_t g_queue;
int main(void)
{/* 设置系统中断优先级分组4 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);/* 系统定时器中断频率为configTICK_RATE_HZ */SysTick_Config(SystemCoreClock/configTICK_RATE_HZ);									/* 初始化串口1 */uart_init(9600);     							/* 创建app_task1任务 */xTaskCreate((TaskFunction_t )app_task1,  		/* 任务入口函数 */(const char*    )"app_task1",			/* 任务名字 */(uint16_t       )512,  				/* 任务栈大小 */(void*          )NULL,				/* 任务入口函数参数 */(UBaseType_t    )5, 					/* 任务的优先级 */(TaskHandle_t*  )&app_task1_handle);	/* 任务控制块指针 */ /* 创建app_task2任务 */		  xTaskCreate((TaskFunction_t )app_task2,  		/* 任务入口函数 */(const char*    )"app_task2",			/* 任务名字 */(uint16_t       )512,  				/* 任务栈大小 */(void*          )NULL,				/* 任务入口函数参数 */(UBaseType_t    )5, 					/* 任务的优先级 */(TaskHandle_t*  )&app_task2_handle);	/* 任务控制块指针 */ //支持5条消息,每条消息的大小是64字节g_queue=xQueueCreate(5,64);/* 开启任务调度 */vTaskStartScheduler(); printf("none run here...\r\n");while(1);}
static void app_task1(void* pvParameters)
{char buf[64]={0};uint32_t i=0;for(;;)//while(1){printf("app_task1 is running ...\r\n");i++;sprintf(buf,"i=%d",i);//发送消息,若队列已满,只等待1秒就进行该函数当返回xQueueSend(g_queue,buf,1000);vTaskDelay(2000);}
}   static void app_task2(void* pvParameters)
{char buf[64]={0};	BaseType_t rt;for(;;)//while(1){rt = xQueueReceive(g_queue,buf,portMAX_DELAY);if(rt == pdTRUE){printf("app_task2 recv msg:%s\r\n",buf);}}
} 

2、任务与中断间的数据传输

static volatile uint8_t  	g_usart1_recv_buf[64]={0};
static volatile uint32_t 	g_usart1_recv_cnt = 0;extern QueueHandle_t Test_Queue; void USART1_IRQHandler(void)
{uint8_t d;uint32_t ulReturn;BaseType_t xHigherPriorityTaskWoken;/* 进入临界段,临界段可以嵌套 */ulReturn = taskENTER_CRITICAL_FROM_ISR();	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  {//接收串口数据d=USART_ReceiveData(USART1);g_usart1_recv_buf[g_usart1_recv_cnt]=d;//记录多少个数据g_usart1_recv_cnt++;//检测到'#'符或接收的数据满的时候则发送数据if(d=='#' || g_usart1_recv_cnt>=(sizeof g_usart1_recv_buf)){
#if 1xQueueSendFromISR(Test_Queue,(void *)g_usart1_recv_buf,NULL);
#elsexQueueSendFromISR(Test_Queue,(void *)g_usart1_recv_buf,&xHigherPriorityTaskWoken);
#endif			g_usart1_recv_cnt=0;}			//清空串口接收中断标志位USART_ClearITPendingBit(USART1, USART_IT_RXNE);} /* 若接收消息队列任务的优先级高于当前运行的任务,则退出中断后立即进行任务切换,执行前者;否则等待下一个时钟节拍才进行任务切换*/if( xHigherPriorityTaskWoken ){portYIELD_FROM_ISR( xHigherPriorityTaskWoken );}	/* 退出临界段 */taskEXIT_CRITICAL_FROM_ISR( ulReturn );	
}

六、pxHigherPriorityTaskWoken

pxHigherPriorityTaskWoken参数位置,作用于更高优先级任务的唤醒

BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxHigherPriorityTaskWoken);

方式1:

让调度器在中断退出后,立即切换到更高优先级的等待消息队列任务。

void USART1_IRQHandler(void)   
{BaseType_t  xHigherPriorityTaskWoken = pdFALSE;......xQueueSendFromISR(g_queue_usart1,g_usart1_buf, &xHigherPriorityTaskWoken );/*  若接收消息队列任务的优先级高于被中断打断的任务,则退出中断后立即进行任务切换,执行前者;
否则等待下一个时钟节拍(≤1ms的时间)才进行任务切换*/if(xHigherPriorityTaskWoken)portYIELD_FROM_ISR( xHigherPriorityTaskWoken );......}

方式2:

让调度器在中断退出后,等待下一个时钟节拍后切换到等待消息的任务。

void USART1_IRQHandler(void)   
{....../* 在中断退出后,等待下一个时钟节拍(≤1ms的时间)才进行任务切换*/xQueueSendFromISR(g_queue_usart1,g_usart1_buf, NULL );.....}

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

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

相关文章

页的初步认识

关于准备 我们在之前的学习中,已经学习了相当一部分有关段的知识,CPU提供了段的机制来给我们的内存进行保护,但实际上我们在x86下的段base是0,实际上并没有偏移 两种分页模式 我们有两种分页模式,29912分页和101012…

题目一:bugku---game1

2024.11.21 1、题目连接: 2、打开是个小游戏 3、正常玩一把结束后,用bp抓包 4、查看url有三个参数,score对应的就是我们结束这把游戏时获得的分数,sign的zM后面为这把游戏分数的base64加密 5、将抓到的包,发送到重放…

小柴冲刺软考中级嵌入式系统设计师系列三、嵌入式硬件设计(1)嵌入式系统电源管理

越努力,越幸运! 人生的意义在于体验! 目录 越努力,越幸运! 一、电源管理 (1)系统上电行为 (2)空闲模式 (3)断电 (4)电压与频率缩放 例如 具体实现如下: ① 12V 转8V ② 12V 转-8V ③ 12V 转5V ④ 5V 转3…

C++ 优先算法 —— 长度最小的子数组(滑动窗口)

目录 题目:长度最小的子数组 1. 题目解析 2. 算法原理 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口(同向双指针) 滑动窗口正确性 3. 代码实现 Ⅰ. 暴力枚举(会超时) Ⅱ. 滑动窗口(同向双指针) 题目:长…

uniapp定义new plus.nativeObj.View实现APP端全局弹窗

为什么要用new plus.nativeObj.View在APP端实现弹窗?因为uni.showModal在APP端太难看了。 AppPopupView弹窗函数参数定义 参数一:弹窗信息(所有属性可不填,会有默认值) 1.title:"", //标题 2.content:"", //内容 3.confirmBoxCo…

网络安全——SpringBoot配置文件明文加密

一、前言 在日常开发中,项目中会有很多配置文件。比如SpringBoot项目核心的数据库配置、Redis账号密码配置都在properties、yml配置文件 中。 如果这些信息以明文的方式存储,你的电脑被拿去修理,就会容易泄露,一旦被其他人获取到…

Linux系统编程之进程基础知识

概述 在Linux系统中,进程是指一个正在运行的程序实例。每个进程都有一个唯一的进程标识符,即PID,操作系统通过这个PID来唯一识别和管理各个进程。进程不仅仅是程序代码的运行实例,它还包含了程序运行时所需的各种资源,…

2024智能机器人与自动控制国际学术会议 (IRAC 2024)

主办,承办,支持单位 会议官网 www.icirac.org 大会时间:2024年11月29-12月1日 大会简介 2024智能机器人与自动控制国际学术会议 (IRAC 2024)由华南理工大学主办,会议将于2024年11月29日-12月1日在中国广…

【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想 requestsyamlpytestallure实现接口自动化框架。结合数据驱动和分层思想,将代码与数据分离,易维护,易上手。使用yaml编写编写测试用例,利用requests库发送请求,使用pytest管理用例,allure生成…

利用 Jsoup 进行高效 Web 抓取与 HTML 处理

Jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 JQuery 的操作方法来取出和操作数据。 官网:https://jsoup.org/ 中文文档:Jsou…

蓝桥杯不知道叫什么题目

小蓝有一个整数,初始值为1,他可以花费一些代价对这个整数进行变换。 小蓝可以花贵1的代价将教数增加1。 小蓝可以花费3的代价将整数增加一个值,这个值是整数的数位中最大的那个(1到9) .小蓝可以花费10的代价将整数变为原来的2倍, 例如,如果整…

【JavaEE初阶】枫叶经霜艳,梅花透雪香-计算机是如何运行的?

本篇博客给大家带来的是与计算机相关的知识点, 包括:计算机的组成, 指令, 进程(重点). 文章专栏: JavaEE初阶 若有问题 评论区见 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 1. 计算机的组成 1.1 计算机的发展史 计算…

SuperMap Objects组件式GIS开发技术浅析

引言 随着GIS应用领域的扩展,GIS开发工作日显重要。一般地,从平台和模式上划分,GIS二次开发主要有三种实现方式:独立开发、单纯二次开发和集成二次开发。上述的GIS应用开发方式各有利弊,其中集成二次开发既可以充分利…

Linux网络——NAT/代理服务器

一.NAT技术 1.NAT IP转换 之前我们讨论了, IPv4 协议中, IP 地址数量不充足的问题,NAT 技术就是当前解决 IP 地址不够用的主要手段, 是路由器的一个重要功能。 NAT 能够将私有 IP 对外通信时转为全局 IP. 也就是一种将私有 IP 和全局IP 相互转化的技术方法: 很…

使用八爪鱼爬虫抓取汽车网站数据,分析舆情数据

我是做汽车行业的,可以用八爪鱼爬虫抓取汽车之家和微博上的汽车文章内容,分析各种电动汽车口碑数据。 之前,我写过很多Python网络爬虫的案例,使用requests、selenium等技术采集数据,这次尝试去采集小米SU7在微博、汽车…

C语言笔记(自定义类型:结构体、枚举、联合体 )

前言 本文对自定义类型的结构体创建、使用、结构体的存储方式和对齐方式,枚举的定义、使用方式以及联合体的定义、使用和存储方式展开叙述,如有错误,请各位指正。 目录 前言 1 结构体 1.1 结构体的声明 1.2 结构体的自引用 1.3 结构体变…

【消息序列】详解(6):深入探讨缓冲区管理与流量控制机制

目录 一、概述 1.1. 缓冲区管理的重要性 1.2. 实现方式 1.2.1. HCI_Read_Buffer_Size 命令 1.2.2. HCI_Number_Of_Completed_Packets 事件 1.2.3. HCI_Set_Controller_To_Host_Flow_Control 命令 1.2.4. HCI_Host_Buffer_Size 命令 1.2.5. HCI_Host_Number_Of_Complete…

Element Plus的快速入门

一、什么是Element Plus Element : 是饿了么团队研发的,基于Vue3,面向设计师和开发者的组件库。 组件:组成网页的部分,例如超链接,按钮,图片,表格,表单,分页条等等。 …

健身房小程序服务渠道开展

健身不单单是锻炼身体、保持身材,也是一种社交方式,城市里门店不少,每家都有一定流量和老客,但仅靠传统线下拉客/自然流量前往和线上朋友圈、短视频发硬广等方式还不够。 商家需要找到更多潜在目标客户,而消费者也对门…

Docker--通过Docker容器创建一个Web服务器

Web服务器 Web服务器,一般指网站服务器,是驻留于因特网上某种类型计算机的程序。 Web服务器可以向浏览器等Web客户端提供文档,也可以放置网站文件以供全世界浏览,或放置数据文件以供全世界下载。 Web服务器的主要功能是提供网上…