Message Buffer 和 Stream Buffer 的不同点
- Message buffer 一次只能传输一个一条完整的 Message。
官方函数文档
Message Buffer API
[[FreeRTOS_Reference_Manual_V10.0.0.pdf#page=372&selection=4,0,4,18|FreeRTOS_Reference_Manual_V10.0.0, page 372]]
xMessageBufferCreate()
#include "FreeRTOS.h"
#include "message_buffer.h"
MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );
函数说明:
- 创建一个消息缓冲区传输句柄。
参数:
xBufferSizeBytes:
消息缓冲区中可以同时存储的总字节数,而不是可以存储的消息数量。洗哦啊西缓冲区的容量是以字节为单位的,即在任何时候消息缓冲区能够保存的最大字节数。
注意:
- 消息缓冲区的内容,会额外包含一个字节的数据,用来存储消息的长度。
xMessageBufferSend()
#include "FreeRTOS.h"
#include "message_buffer.h"
size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer,
const void *pvData,
size_t xDataLengthBytes,
TickType_t xTicksToWait );
函数说明:
- 向消息缓冲区发送数据。
参数:
xMessageBuffer:
消息缓冲区句柄。pvData:
存放消息内容的指针。xDataLengthBytes:
消息内容长度,单位字节。xTicksToWait:
超时等待时长。
返回值:
- 如果消息发送成功,则返回消息的长度。
- 如果消息发送因为超时而失败,则返回 0。
xMessageBufferReceive()
#include "FreeRTOS.h"
#include "message_buffer.h"
size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
const void *pvData,
size_t xDataLengthBytes,
TickType_t xTicksToWait );
函数说明:
- 从消息缓冲区接收消息。
参数:
xMessageBuffer:
消息缓冲区句柄。pvData:
存放消息内容的指针。xDataLengthBytes:
消息内容长度,单位字节。xTicksToWait:
超时等待时长。
返回值:
- 如果消息接收成功,则返回消息的长度。
- 如果消息接收因为超时而失败,则返回 0。
- 如果因为存储消息的指针小于消息的长度,也返回 0。
注意:
- 接收消息时,如果存储消息内容的指针容量消息消息的大小,则不会接收该消息。
示例代码
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "freertos/event_groups.h"
#include "freertos/message_buffer.h"
// 创建消息句柄
static MessageBufferHandle_t message_handle;
void task_send(void *pvPara)
{
char *tx_message = (char *)malloc(100); // 存储消息的指针,虽然分配了100字节的容量,但是实际发送长度是根据实际消息长度来决定的
memset(tx_message, 0, 100);
size_t message_len = 0;
size_t message_sent_len = 0;
for (int i = 0; i < 3; i++) {
// 将消息内容存储到指针中
message_len = sprintf(tx_message, "Hello, it's message NO.%d.", i);
// 发送消息,并获取发送的消息长度
message_sent_len = xMessageBufferSend(message_handle, tx_message, message_len, portMAX_DELAY);
// 获取消息句柄剩余可用空间
printf("[TASK SEND]: Available spaces = %d.\n", xMessageBufferSpacesAvailable(message_handle));
printf("[TASK SEND]: message_len = %d, message_sent_len = %d, message: %s\n", message_len, message_sent_len, tx_message);
}
vTaskDelete(NULL);
}
void task_receive(void *pvPara)
{
vTaskDelay(pdMS_TO_TICKS(1000));
char *rx_message = (char *)malloc(100);
memset(rx_message, 0, 100);
size_t message_received_len = 0;
while (true) {
// 阻塞 5s ,等待发送任务完成
vTaskDelay(pdMS_TO_TICKS(5000));
// 接收并存储消息到指针,同时获取接收到的消息长度
message_received_len = xMessageBufferReceive(message_handle, rx_message, 100, portMAX_DELAY);
printf("[TASK RECEIVE]: Available spaces = %d.\n", xMessageBufferSpacesAvailable(message_handle));
printf("[TASK RECEIVE]: message_received_len = %d, message: %s\n", message_received_len, rx_message);
}
}
void app_main(void)
{
// 创建消息缓冲区,大小为 30 字节
message_handle = xMessageBufferCreate(30);
xTaskCreate(task_send, "Task Send", 2048, NULL, 1, NULL);
xTaskCreate(task_receive, "Task Receive", 2048, NULL, 1, NULL);
}
示例输出
![[MessageBuffer.gif]]
Task Send 先开始发送消息,等待 Task Receive 接收,因为 Task Receive 要 5s 的时间才能接收一个消息,所以阻塞了 Task Send,即便如此,Message Buffer 也只是在每次发送一个消息。
另外,消息长度是 25,但是显示剩余可用空间为 1,因为消息缓冲区句柄中的消息长度定义,占据了 4 个字节的内存。