背景:使用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);
}