FreeRTOS学习-消息队列
转载自https://blog.csdn.net/weixin_43866583/article/details/125555241?spm=1001.2014.3001.5502
FreeRTOS的消息队列
FreeRTOS中提供了任务之间互相通信的另外的一种手段——消息队列。它的作用主要有:
1)为了在任务与任务之间、任务与中断之间的通信而准备的,可以在任务与任务之间,任务与中断之间传递消息;
2)消息队列可以存储有限的、大小固定的数据项目;
它具有的特点有几个:
1)FreeRTOS中的消息队列传递的是一个实际的数据,而不是数据的地址。在RTX、ucos-ii、ucos-iii中的消息队列传递的是消息的地址。
2)消息队列不属于某个特定的任务,任何的任务都可以向队列中发送消息,也可以从队列中提取消息。
3)消息队列所能容纳的最大的数据项目就是队列的长度。
FreeRTOS的消息队列的管理
队列的出队方式 & 数据存储
通常的队列都是采取先进先出(FIFO)的存储缓冲机制方式,即往队列中发送消息的时候永远是先发到队列的尾部,而从队列中提取消息的时候是从头部提取的。同时FreeRTOS也支持 后进先出(LIFO)的方式。
因为FreeRTOS的消息队列传递的是实际的数据,所以数据发送到队列中会导致数据拷贝,会浪费一些时间。但是好处在于一旦消息被拷贝到了消息队列中,那么原始的数据缓冲区或者数据就可以删除或者改变,达到反复利用的效果。
队列的阻塞
队列阻塞的作用是在当任务从队列中获取消息的时候,所指定的一个等待时间。队列在出队和入队都是可以设置阻塞的。有三种阻塞的时间:
不等待:不等待直接执行之后的内容(为0不等待);
定时等待:任务等待一个固定的时间间隔,可以为 0 ~ portMAX_DELAY;
一直等待:设置为 portMAX_DELAY 的时候,会一直等待。
FreeRTOS的队列的实现
消息队列的两种通信方式
FreeRTOS 消息队列实现的API函数
创建消息队列
1 |
|
函数描述:
函数 xQueueCreate 用于创建消息队列。
第 1 个参数是消息队列支持的消息个数。即队列长度。
第 2 个参数是每个消息的大小,单位字节。
返回值:如果创建成功会返回消息队列的句柄,失败会返回 NULL。
使用这个函数要注意以下问题:
1)FreeRTOS 的消息传递是数据的复制,而不是传递的数据地址,这点要特别注意。每一次传递都是
uxItemSize 个字节。
2.)uxItemSize:所要发送/接收的消息队列的总字节数。比如要发送10个消息,每个消息占4个字节,所以
uxItemSize = 4(byte) * 10(个) = 40 Byte
向消息队列中发送消息
1 |
|
函数描述:
函数 xQueueSend 用于任务中消息发送。
第 1 个参数:是消息队列句柄。
第 2 个参数:要传递的数据地址,每次发送都是将消息队列创建函数 xQueueCreate 所指定的单个消息大
小复制到消息队列空间中。
第 3 个参数:是当消息队列已经满时,等待消息队列有空间时的最大等待时间,单位为系统时钟节拍。
返回值:如果消息成功发送返回 pdTRUE,否则返回errQUEUE_FULL。
使用这个函数要注意以下问题:
1)FreeRTOS 的消息传递是数据的复制,而不是传递的数据地址。
2)此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是
xQueueSendFromISR。
3)如果消息队列已经满且第三个参数为 0,那么此函数会立即返回。
4)如果用户将 FreeRTOSConfig.h 文件中的宏定义INCLUDE_vTaskSuspend 配置为 1 且第三个参数配
置为 portMAX_DELAY,那么此发送函数会永久等待直到消息队列有空间可以使用。
5)消息队列还有两个函数 xQueueSendToBack 和 xQueueSendToFront,函数 xQueueSendToBack
实现的是 FIFO 方式的存取,函数 xQueueSendToFront 实现的是 LIFO 方式的读写。一般说的函
数 xQueueSend 等效于 xQueueSendToBack,即实现的是 FIFO 方式的存取。
从消息队列中读取消息
1 |
|
函数描述:
函数 xQueueReceive 用于接收消息队列中的数据。
第 1 个参数:是消息队列句柄。
第 2 个参数:是从消息队列中复制出数据后所储存的缓冲地址,缓冲区空间要大于等于消息队列创建函
数 xQueueCreate 所指定的单个消息大小,否则取出的数据无法全部存储到缓冲区,从而造成内存溢
出。
第 3 个参数:是消息队列为空时,等待消息队列有数据的最大等待时间,单位系统时钟节拍。
返回值:如果接到到消息返回 pdTRUE,否则返回 pdFALSE。
使用这个函数要注意以下问题:
1)此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序使用的是
xQueueReceiveFromISR 。
2)如果消息队列为空且第三个参数为 0,那么此函数会立即返回。
3)如果将 FreeRTOSConfig.h 文件中的宏定义 INCLUDE_vTaskSuspend 配置为 1 且第三个参数配
置为 portMAX_DELAY,那么此函数会永久等待直到消息队列有数据。
队列初始化函数
1 |
|
队列复位
1 |
|
创建两个任务,一个任务发送三个数据给另外一个任务,另一个任务接收并打印,循环发送,每次发送都对发送的数据增加后发送。代码如下:
1 |
|