FreeRTOS可变数据长度的队列

背景:使用xQueueCreate创建队列时,我们发现只有两个参数,队列深度和单元长度,单元长度为该队列每组数据的最大长度,由于实际应用中,可能每个消息的数据长度都不一样,因此都设同样的长度会造成内存浪费。

方案:我们把消息数据打包成结构体,然后传入该结构体的指针到队列,接收到该指针时转换为结构体,最终获取实际的数据。

1、定义队列变量和队列结构体类型

xQueueHandle test_queue;    //队列变量

typedef struct{
	uint8_t len;			//数据长度
	uint8_t data[];			//数据指针
}queue_data_t;

2、在初始化函数创建队列和任务

test_queue = xQueueCreate(5, sizeof(int));                //创建队列,这里队列深度为5,可以自行修改

xTaskCreate(user_test1_task, "", 256, NULL, 2, NULL);    //创建任务1,用于发送队列数据
xTaskCreate(user_test2_task, "", 256, NULL, 2, NULL);    //创建任务2,用于发送队列数据
xTaskCreate(user_test3_task, "", 256, NULL, 2, NULL);    //创建任务3,用于接收队列数据

3、定义任务函数


/********************************************************************
 *@brief	  任务1,发送队列数据
 *@param[in] arg 传入参数
 *@return	 none
 *******************************************************************/
static void user_test1_task(void *arg)
{
	while(1)
	{
		vTaskDelay(1000/portTICK_RATE_MS);

		//数据长度	
		int len = 10;

        //创建队列内存,需要一个字节保存数据的长度,所以数据长度+1
		queue_data_t *queue_data = (queue_data_t *)zalloc(len+1);
		queue_data->len 	= len;

        //填入需要发送的数据
		int i;
		for(i=0;i<len;i++)
		{
			queue_data->data[i] = i;
		}

        //把结构体指针保存到address
		int address;
		address = (int)queue_data;

		//相当于保存queue_data的指针到队列
        if (xQueueSend(test_queue, (void *)&address, 0) == pdFALSE)
        {
        	USER_LOG_ERROR("test queue overflow.\r\n");
        }
	}

	vTaskDelete(NULL);
}

/********************************************************************
 *@brief	  任务2,发送队列数据
 *@param[in] arg 传入参数
 *@return	 none
 *******************************************************************/
static void user_test2_task(void *arg)
{
	while(1)
	{
		vTaskDelay(1000/portTICK_RATE_MS);

		//数据长度	
		int len = 5;

        //创建队列内存,需要一个字节保存数据的长度,所以数据长度+1
		queue_data_t *queue_data = (queue_data_t *)zalloc(len+1);
		queue_data->len 	= len;

        //填入需要发送的数据
		int i;
		for(i=0;i<len;i++)
		{
			queue_data->data[i] = i;
		}

        //把结构体指针保存到address
		int address;
		address = (int)queue_data;

		//相当于保存queue_data的指针到队列
        if (xQueueSend(test_queue, (void *)&address, 0) == pdFALSE)
        {
        	USER_LOG_ERROR("test queue overflow.\r\n");
        }
	}

	vTaskDelete(NULL);
}
/********************************************************************
 *@brief	  任务3,接收队列数据
 *@param[in] arg 传入参数
 *@return	 none
 *******************************************************************/
static void user_test3_task(void *arg)
{
	while(1)
	{
		int address;

    	//等待接收队列数据
        if (xQueueReceive(test_queue, (void *)&address, 100/portTICK_RATE_MS) == pdTRUE)
        {
            //把指针转换为结构体
        	queue_data_t *queue_data;
       	    queue_data = (queue_data_t *)address;

            //打印数据长度
    		USER_LOG_DEBUG("queue_data2 %d\r\n",queue_data->len);
            //打印数据字节
    		USER_LOG_HEXDUMP(queue_data->data,queue_data->len);

            //释放内存
    		free(queue_data);
     	}
	}
	vTaskDelete(NULL);
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dear_Wally

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值