抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

消息队列

消息队列是一种用于线程间通信的技术,在FreeRTOS​中则用于任务间通信,其中的任务可以视为线程。

支持先进先出、后进先出

消息队列运行机制

  1. 创建消息队列单独划分一个内存空间,内存大小=控制块大小+单个消息空间*队列长度,然后初始化消息队列,空间大小无法更改。

  2. 初始化后,内存空间中会包含头指针等信息,消耗部分内存,删除消息队列后空间释放。

  3. 每个空间存放不大于uxItemSize​ 的任意类型数据。

  4. 队列未满,消息会被拷贝到队列末尾。紧急消息则发送至队列首。

  5. 当有任务请求队列消息时,任务变为阻塞态在等待时间内等待消息,若消息空间内无消息直至超时,则任务变为就绪态,否则接收消息变为就绪态。

  6. 消息队列不再使用后,应该及时删除,释放资源。

  7. 任务等待消息的几种状态

    1. 即刻型:任务等待消息,若队列中没有消息,任务直接变为就绪态,不再等待消息。

    2. 等待型:任务变为阻塞态,在等待时间内等待队列消息,若有消息则接收并变为就绪态,若无就超时变为就绪态。

    3. 无限型:任务一直等待消息,直到消息出现。

    • 注意事项:只有任务才能进入阻塞态,中断不能进入阻塞态,中断有单独的消息函数

队列常见函数

  1. xQueueCreate()​创建一个队列返回一个指针类型的句柄

    • 使用的是动态内存,需要开启configSUPPORT_DYNAMIC_ALLOCATION 1​宏定义
    • 创建的时候,申请内存是连续的,保证队列控制块和消息空间的连续
  2. xQueueStaticCreate()​使用静态内存创建一个队列

  3. vQueueDelete()​队列删除

  4. xQueueSend()​向队列发送消息,以拷贝的形式在队列尾部加入一个消息,不能在中断中使用

  5. xQueueSendToBack()​和xQueueSend()​等效

  6. xQueueSendFromISR()​用于中断中向队列尾部发送一个消息

  7. xQueueSendToBackFromISR()​和xQueueSendFromISR()​等效

  8. xQueueGenericSend()​通用消息队列发送,是上述发送的原型

  9. xQueueGenericSendFromISR()​中断通用消息队列发送,中断发送的原型

  10. xQueueReceive()​从队列中接收消息,并将消息删除,将消息拷贝至缓冲区

  11. xQueuePeek()​从队列中接收消息,不删除消息

  12. xQueueReceiveFromISR()​中断中使用

  13. xQueuePeekFromISR()​中断中使用

  14. xQueueGenericReceive()​通用接收消息,上述的原型

创建队列

设计2个Button​任务,通过按键发送不同的Data​数据,然后将发送的Data​数据在另一个任务中接收,最终在串口显示

队列消息句柄,创建一个引用,并不是创建一个真实的队列消息,同时设置队列的属性

1
2
3
4
//创建一个Queue句柄
QueueHandle_t Test_Queue=NULL;
#define QUEUE_LEN 4 //队列长度
#define QUEUE_SIZE 4 //单个消息空间大小

创建一个真实的队列

1
2
//创建一个Queue队列
Test_Queue=xQueueCreate((UBaseType_t)QUEUE_LEN,(UBaseType_t)QUEUE_SIZE);

接收数据任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void Receive_Task(void *paramter)
{
BaseType_t xReturn=pdTRUE;
uint32_t r_queue;
while (1)
{
//消息队列句柄,缓冲区,等待时间:一直等待
xReturn = xQueueReceive(Test_Queue,&r_queue,portMAX_DELAY);
if(xReturn==pdTRUE)
{
printf("本次接收到的消息是%d\r\n",r_queue);
}else
{
printf("数据接收错误,错误代码:0x%l\r\n",xReturn);
}
}
}

Button控制发送数据任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
static void Send_Task(void *paramter)
{
BaseType_t xReturn=pdTRUE;
uint32_t send_data1=1;
uint32_t send_data2=2;
while (1)
{
if (Key_BTN(BTN1)==KEY_ON)
{
printf("发送消息send_data1\r\n");
//消息队列句柄,数据,等待时间:0
xReturn = xQueueSend(Test_Queue,&send_data1,0);

if (xReturn==pdTRUE)
{
printf("消息send_data1发送成功\r\n");
}
}

if (Key_BTN(BTN2)==KEY_ON)
{
printf("发送消息send_data2\r\n");
xReturn = xQueueSend(Test_Queue,&send_data2,0);
if (xReturn==pdTRUE)
{
printf("消息send_data2发送成功\r\n");
}
}
vTaskDelay(20);
}
}