消息队列
队列又称消息队列,是一种常用于任务间通信的数据结构, 队列可以在任务与任务间、中断和任务间传递信息,实现了任务接收来自其他任务或中断的不固定长度的消息,任务能够从队列里面读取消息,当队列中的消息是空时,读取消息的任务将被阻塞,用户还可以指定阻塞的任务时间 xTicksToWait,在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。 当队列中有新消息时, 被阻塞的任务会被唤醒并处理新消息;当等待的时间超过了指定的阻塞时间,即使队列中尚无有效数据,任务也会自动从阻塞态转为就绪态。 消息队列是一种异步的通信方式。
通过消息队列服务,任务或中断服务例程可以将一条或多条消息放入消息队列中。同样,一个或多个任务可以从消息队列中获得消息。当有多个消息发送到消息队列时,通常是将先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入消息队列的消息,即先进先出原则(FIFO),但是也支持后进先出原则(LIFO) 。
消息队列的运作机制
- 创建消息队列时 FreeRTOS 会先给消息队列分配一块内存空间,这块内存的大小等于
消息队列控制块大小加上(单个消息空间大小与消息队列长度的乘积) ,接着再初始化消息队列,此时消息队列为空。 - 任务或者中断服务程序都可以给消息队列发送消息, 当发送消息时, 如果队列未满或者允许覆盖入队, FreeRTOS 会将消息拷贝到消息队列队尾,否则,会根据用户指定的阻塞超时时间进行阻塞,在这段时间中,如果队列一直不允许入队,该任务将保持阻塞状态以等待队列允许入队。优先级高的先获得控制权。
- 当消息队列不再被使用时,应该删除它以释放系统资源,一旦操作完成,消息队列将被永久性的删除。
消息队列的应用场景
消息队列可以应用于发送不定长消息的场合,包括任务与任务间的消息交换,队列是
FreeRTOS 主要的任务间通讯方式,可以在任务与任务间、中断和任务间传送信息,发送到队列的消息是通过拷贝方式实现的, 这意味着队列存储的数据是原数据,而不是原数据的引用。
->代码说明------------
创建消息队列
xQueueCreate()函数说明
QueueHandle_t xQueueCreate(
UBaseType_t uxQueueLength,
UBaseType_t uxItemSize );
uxQueueLength
:队列能够存储的最大消息单元数目,即队列长度。
uxItemSize
:队列中消息单元的大小,以字节为单位。
返回值:如果创建成功则返回一个队列句柄,用于访问创建的队列。 如果创建不成功则返回NULL, 可能原因是创建队列需要的 RAM 无法分配成功。
发送消息
void Send_Task(void *parameter)
{
BaseType_t xReturn = pdPASS;
uint32_t send_data1 = 1;
uint32_t send_data2 = 2;
while (1)
{
if (Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN) == KEY_ON )
{
printf("发送消息send_data1\r\n");
xReturn = xQueueSend(Text_Queue,//消息队列的内容
&send_data1,//发送的信息内容
0 //等待时间 0
);
if( xReturn == pdPASS )
printf("消息send_data1发送成功\r\n");
}
if (Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN) == KEY_ON )
{
printf("send_data2\r\n");
xReturn = xQueueSend(Text_Queue,//消息队列的内容
&send_data2,//发送的信息内容
0 //等待时间 0
);
if( xReturn == pdPASS )
printf("消息send_data2发送成功\r\n");
}
vTaskDelay(20);
}
}
接收消息
void Receive_Task(void *parameter)
{
BaseType_t xReturn = pdTRUE;
uint32_t r_queue;
while (1)
{
xReturn = xQueueReceive(Text_Queue, //消息队列的句柄
&r_queue, //接受的消息内容
portMAX_DELAY//等待时间:一直等
);
if(xReturn == pdTRUE)
printf("Received message is %d\r\n",r_queue);
else
printf("数据接收错误,错误代码0x%1x\r\n",xReturn);
}
}
结论
消息队列和创建任务的逻辑差不多。
创建消息句柄,利用xQueueReceive
和xQueueSend
即可实现对消息队列消息的发送接收
vscode快捷键
Ctrl+Shift+o
可查看文件中的函数