当前位置: 首页 > article >正文

本篇4K,立志最细,FreeRtos中Queue使用教程与个人理解!!!

                                前言:编写不易,请勿搬运,仅供学习参考!!!

目录

FreeRtos中Queue的使用

Queue创建

Queue实际调用

动态创建和静态区别

Queue接受数据

Queue实际调用

Queue发送数据

Queue实际调用

Queue队列集使用


FreeRtos中Queue的使用

        在FreeRtos操作系统中,Queue是一种用在Task之间传输数据的方法,这种方法传输数据的同时,可以满足互斥同步阻塞唤醒,是一种最为常用的传输数据手段,主要特性有FIFO,同时Queue会自动管理数据的插入删除,当读出来一个数据的时候,这个数据会自动从Queue里面删除,同时使用队列来传输数据,是最稳妥的手段。

Queue创建

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
函数参数相关作用
uxQueueLength用来确定队列里面存放多少个数据元素
uxItemSize队列里面数据的大小,单位是字节
函数返回值句柄:代表创建成功 ,NULL:创建失败

        这里是动态创建Queue函数跟需要的参数,以及参数的意思,下面是静态创建Queue的函数原型,跟参数意思。

QueueHandle_t xQueueCreateStatic( UBaseType_t uxQueueLength,UBaseType_t uxItemSize,uint8_t *pucQueueStorageBuffer,Static Queue_t *pxQueueBuffer);
函数参数相关作用
uxQueueLength用来确定队列里面存放多少个数据元素
uxItemSize队列里面数据的大小,单位是字节
uint8_t *pucQueueStorageBuffer自定义的Queue存储空间
StaticQueue_t *pxQueueBuffer队列控制块,负责管理内部信息
函数返回值句柄:代表创建成功 ,NULL:创建失败

        注意,uint8_t *pucQueueStorageBuffer参数的大小应该是,uxQueueLength*uxItemSize的大小,不能比这个少,不然就放不下。这里静态创建跟动态相比多了两个参数,因为所有的静态创建都需要,主动确定分配空间的大小,动态创建就不用,同时pxQueueBuffer填写这个位置的参数,需要声明为StaticQueue_t类型才能填写。

Queue实际调用

struct rotary_data {
	int32_t cnt;
	int32_t speed;
};
struct input_data {
	uint32_t dev;
	uint32_t val;  
};

static uint8_t g_ucQueueRotaryBuf[10*sizeof(struct rotary_data)];
static StaticQueue_t g_xQueueRotaryStaticStruct;

g_xQueuePlatform = xQueueCreate(10, sizeof(struct input_data));
g_xQueueRotary   = xQueueCreateStatic(10, sizeof(struct rotary_data), g_ucQueueRotaryBuf, &g_xQueueRotaryStaticStruct);
	

        这里使用结构体来传输数据,所以计算结构体数据的大小,作为参数填写到,Queue创建声明的参数。

动态创建和静态区别

        这两种创建方式的主要区别在于,内存分配方式和时机,动态创建也需要内存,前者内存由FreeRtos中的内存管理器分配Heap的内存给他,静态创建内存管理器不会分配,需要自己定义使用空间大小,同时删除静态创建任务,任务使用的内存空间是不会返回的。

        总结下来最大的区别在于,动态分配不需要确定使用空间大小,删除释放使用空间,静态分配使用前要确定内存空间大小,删除创建不会释放使用的内存空间。

Queue接受数据

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

        上面是函数原型,两个函数区别在于后缀有FromISR的函数能在中断中用,上文有提交,使用xQueueReceive()函数读队列数据读出来之后,数据会自动被Queue给移除

函数参数参数解释
xQueue读那个队列填写它的句柄
pvBuffer从队列里面读取的数据,放到这个参数里面。
xTicksToWait

0:没有数据立即返回

portMAX_DELAY:没有数据阻塞到有数据

返回值

pdPASS:从队列读出数据入

errQUEUE_EMPTY:读取失败,因为队列空了。

       这个函数的返回值因为不是句柄,一般不需要取,需要注意的是,存放读取数据的变量跟 0或者portMAX_DELAY值的敲定。

Queue实际调用

struct rotary_data {
	int32_t cnt;
	int32_t speed;
};
struct input_data {
	uint32_t dev;
	uint32_t val;  
};

static uint8_t g_ucQueueRotaryBuf[10*sizeof(struct rotary_data)];
static StaticQueue_t g_xQueueRotaryStaticStruct;

g_xQueuePlatform = xQueueCreate(10, sizeof(struct input_data));
g_xQueueRotary   = xQueueCreateStatic(10, sizeof(struct rotary_data), g_ucQueueRotaryBuf, &g_xQueueRotaryStaticStruct);
struct input_data idata;
xQueueReceive( g_xQueuePlatform,&idata,portMAX_DELAY);

        这里读g_xQueuePlatform的数据,放入了idata里面,如果读不到数据,陷入阻塞状态,什么时候有了数据,就会唤醒,然后读取数据。

Queue写数据

BaseType_t xQueueSendToBack(QueueHandle_t xQueue,const void *pvItemToQueue,TickType_t xTicksToWait);
BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken );

        上面是写数据的函数同样的ISR这个函数,能用在中断里面,因为Queue的FIFO的原因,后写进去的数据,会在首先进去的后面,下面是函数参数说明。

函数参数参数解释
xQueue

填写谁的句柄数据就会写到哪一个队列

pvItemToQueue需要写进去队列的数据,这个数据需要取地址
xTicksToWait

0:无法写进去数据会立即返回

portMAX_DELAY:没有写进去数据会进入阻塞状态

返回值

errQUEUE_FULL:写入失败,因为队列满了。

pdPASS:数据成功写入了队列

               这里写Queue需要注意的是,写入Queue的数据需要取地址

Queue实际调用

	if( xTimerQueue != NULL )
	{
		/* Send a command to the timer service task to start the xTimer timer. */
		xMessage.xMessageID = xCommandID;
		xMessage.u.xTimerParameters.xMessageValue = xOptionalValue;
		xMessage.u.xTimerParameters.pxTimer = ( Timer_t * ) xTimer;

		if( xCommandID < tmrFIRST_FROM_ISR_COMMAND )
		{
			if( xTaskGetSchedulerState() == taskSCHEDULER_RUNNING )
			{
				xReturn = xQueueSendToBack( xTimerQueue, &xMessage, xTicksToWait );
			}
			else
			{
				xReturn = xQueueSendToBack( xTimerQueue, &xMessage, tmrNO_DELAY );
			}
		}
		else
		{
			xReturn = xQueueSendToBackFromISR( xTimerQueue, &xMessage, pxHigherPriorityTaskWoken );
		}

		traceTIMER_COMMAND_SEND( xTimer, xCommandID, xOptionalValue, xReturn );
	}

        这里的话xTicksToWait并没有取值0或者portMAX_DELAY,这个值你可以指定一个具体的等待时间,表示任务最多等待多少个调度滴答(tick)单位。

        如果填写具体的等待时间,不是0或者portMAX_DELAY也是可以的。

                           我是大狗,欢迎指正,欢迎三连,希望对你,有所帮助!!!


http://www.kler.cn/a/326486.html

相关文章:

  • 【网络协议】开放式最短路径优先协议OSPF详解(四)
  • arcgis的合并、相交、融合、裁剪、联合、标识操作的区别和使用
  • STM32-笔记37-吸烟室管控系统项目
  • 如何配置Cursor的显示主题模式
  • 最近在盘gitlab.0.先review了一下docker
  • 流媒体内网穿透/组网/网络映射EasyNTS上云网关启动失败如何解决?
  • 《向量数据库指南》——Fivetran 的 Partner SDK:构建自定义连接器和目标
  • 【学习笔记】手写 Tomcat 四
  • 实战笔记:Vue2项目Webpack 3升级到Webpack 4的实操指南
  • 双指针---(部分地更新)
  • 解决:使用layui.treeTable.updateNode,更新表格数据后,done里面的事件丢失问题
  • PHP 异步编程:从入门到精通
  • 使用 React Router v6 在 React 中实现面包屑
  • docker 部署nacos
  • uniapp路由跳转
  • 如何提高游戏本地化的质量使用QE门户网站Logrus IT
  • 线性代数:探索矩阵与向量的奥秘
  • Excel中查找某个值的位置,用位置取值
  • 迈威通信闪耀工博会,以创新科技赋能工业自动化
  • vue2的指令和过滤器
  • 【C++】set详解
  • 臀部筋膜炎吃什么药最有效
  • 在Python中实现多目标优化问题(4)
  • 手机二要素接口如何用C#实现调用
  • Jenkins本地安装配置与远程访问管理本地服务详细流程
  • 【LeetCode每日一题】——95.不同的二叉搜索树 II