xQueueReceive FreeRTOS 消息接收

xQueueReceive
[Queue Management]

queue. h

 

BaseType_t xQueueReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait );

This is a macro that calls the xQueueGenericReceive() function.

Receive an item from a queue. The item is received by copy so a buffer of adequate size must be provided. The number of bytes copied into the buffer was defined when the queue was created.

This function must not be used in an interrupt service routine. See xQueueReceiveFromISR for an alternative that can.

 

Parameters:

xQueue The handle to the queue from which the item is to be received. //消息句柄
pvBuffer Pointer to the buffer into which the received item will be copied. //指向接收的BUFF
xTicksToWait The maximum amount of time the task should block waiting for an item to receive should the queue be empty at the time of the call. Setting xTicksToWait to 0 will cause the function to return immediately if the queue is empty. The time is defined in tick periods so the constant portTICK_PERIOD_MS should be used to convert to real time if this is required.

If INCLUDE_vTaskSuspend is set to ‘1’ then specifying the block time as portMAX_DELAY will cause the task to block indefinitely (without a timeout).//任务接收超时 如果在调用时队列为空,任务应等待等待接收项目的最长时间。 如果队列为空,则将xTicksToWait设置为0将导致该函数立即返回。 时间以滴答周期定义,因此如果需要,应使用常数portTICK_PERIOD_MS转换为实时。

Returns:

pdTRUE if an item was successfully received from the queue, otherwise pdFALSE.



/* Define a variable of type struct AMMessage.  The examples below demonstrate
how to pass the whole variable through the queue, and as the structure is
moderately large, also how to pass a reference to the variable through a queue. */
struct AMessage
{
   char ucMessageID;
   char ucData[ 20 ];
} xMessage;

/* Queue used to send and receive complete struct AMessage structures. */
QueueHandle_t xStructQueue = NULL;

/* Queue used to send and receive pointers to struct AMessage structures. */
QueueHandle_t xPointerQueue = NULL;


void vCreateQueues( void )
{
   xMessage.ucMessageID = 0xab;
   memset( &( xMessage.ucData ), 0x12, 20 ); //初始化结构体

   /* Create the queue used to send complete struct AMessage structures.  This can
   also be created after the schedule starts, but care must be task to ensure
   nothing uses the queue until after it has been created. 303/5000
 */
   xStructQueue = xQueueCreate(
                         /* The number of items the queue can hold. */
                         10,
                         /* Size of each item is big enough to hold the
                         whole structure.包含整个结构体 内存大*/
                         sizeof( xMessage ) );

   /* Create the queue used to send pointers to struct AMessage structures. */
   xPointerQueue = xQueueCreate(
                         /* The number of items the queue can hold. */
                         10,
                         /* Size of each item is big enough to hold only a
                         pointer.这个只仅仅是指针 */
                         sizeof( &xMessage ) );

   if( ( xStructQueue == NULL ) || ( xPointerQueue == NULL ) )
   {
      /* One or more queues were not created successfully as there was not enough
      heap memory available.  Handle the error here.  Queues can also be created
      statically. */
   }
}

/* Task that writes to the queues. */
void vATask( void *pvParameters )
{
struct AMessage *pxPointerToxMessage;

   /* Send the entire structure to the queue created to hold 10 structures. */
   xQueueSend( /* The handle of the queue. */
               xStructQueue,
               /* The address of the xMessage variable.  sizeof( struct AMessage )
               bytes are copied from here into the queue. */
               ( void * ) &xMessage,
               /* Block time of 0 says don't block if the queue is already full.
               Check the value returned by xQueueSend() to know if the message
               was sent to the queue successfully. 阻塞时间为0表示如果队列已满,则不阻塞。
                检查xQueueSend()返回的值以了解消息是否
                已成功发送到队列。 */
               ( TickType_t ) 0 );

   /* Store the address of the xMessage variable in a pointer variable. 初始化结构体指针*/
   pxPointerToxMessage = &xMessage;

   /* Send the address of xMessage to the queue created to hold 10    pointers. */
   xQueueSend( /* The handle of the queue. */
               xPointerQueue,
               /* The address of the variable that holds the address of xMessage.
               sizeof( &xMessage ) bytes are copied from here into the queue. As the
               variable holds the address of xMessage it is the address of xMessage
               that is copied into the queue. */
               ( void * ) &pxPointerToxMessage,
               ( TickType_t ) 0 );

   /* ... Rest of task code goes here. */
}

/* Task that reads from the queues. */
void vADifferentTask( void *pvParameters )
{
struct AMessage xRxedStructure, *pxRxedPointer;

   if( xStructQueue != NULL )
   {
      /* Receive a message from the created queue to hold complex struct AMessage
      structure.  Block for 10 ticks if a message is not immediately available.
      The value is read into a struct AMessage variable, so after calling
      xQueueReceive() xRxedStructure will hold a copy of xMessage./从创建的队列中接收一条消息,
以保留复杂的结构AMessage 结构体。10个滴答定时器周期后,如果没有立即可用的消息,。
       该值被读入struct AMessage变量中,因此在调用xQueueReceive()之后
       xRxedStructure将保存xMessage的副本。 */
      if( xQueueReceive( xStructQueue,
                         &( xRxedStructure ),
                         ( TickType_t ) 10 ) == pdPASS )
      {
         /* xRxedStructure now contains a copy of xMessage. 包含xMessage的副本,是整个结构体*/
      }
   }

   if( xPointerQueue != NULL )
   {
      /* Receive a message from the created queue to hold pointers.  Block for 10
      ticks if a message is not immediately available.  The value is read into a
      pointer variable, and as the value received is the address of the xMessage
      variable, after this call pxRxedPointer will point to xMessage. */
      if( xQueueReceive( xPointerQueue,
                         &( pxRxedPointer ),
                         ( TickType_t ) 10 ) == pdPASS )
      {
         /* *pxRxedPointer now points to xMessage.指向 xMessage的指针,指向&xMessage*/
      }
   }

   /* ... Rest of task code goes here. */
}
     

 

### FreeRTOS 消息队列接收异常解决方案 当遇到 FreeRTOS 消息队列接收过程中出现问题时,可以从以下几个方面着手排查并解决: #### 1. 数据类型和大小一致性验证 确保发送方和接收方使用的数据类型完全一致,并且数据项的大小匹配。任何不一致可能导致内存越界或其他未定义行为[^5]。 ```c // 发送端代码示例 BaseType_t xStatus; static const char *pcTextForTx = "String to send"; xStatus = xQueueSend( xQueue, &pcTextForTx, ( TickType_t ) 0 ); ``` ```c // 接收端代码示例 char pcReceivedString[ sizeof( pcTextForTx ) ]; if( pdPASS == xQueueReceive( xQueue, &( pcReceivedString ), portMAX_DELAY ) ) { // Process received string here. } ``` #### 2. 设置合理的阻塞时间 对于 `xQueueReceive` 函数而言,参数 `xTicksToWait` 设定的任务等待时间至关重要。过短可能会导致频繁轮询浪费 CPU 资源;太长则可能影响响应速度。通常情况下可以选择适当长度的时间间隔作为超时值,也可以利用 `portMAX_DELAY` 实现无限期等待直到有可用的消息到达[^3]。 #### 3. 正确处理队列满/空情况 如果尝试向已满的队列发送新消息会失败,同样地,试图从未填充过的空闲队列读取消息也会失败。因此建议在每次操作前后检查当前队列的状态,必要时采取相应措施如丢弃旧消息或通知生产者暂停生成更多内容。 #### 4. 监控队列状态变化 为了更好地理解系统运行状况以及定位潜在错误源头,可以在应用程序中加入日志记录功能来跟踪各个时刻下的队列水位线变动趋势。这有助于发现是否存在某些特定条件下发生的拥塞现象或者其他异常模式。 #### 5. 中断上下文中使用特殊版本API 考虑到中断服务程序(ISR)执行环境较为敏感的特点,在此类场合下应当选用专门针对ISR优化后的接口函数比如 `xQueueSendFromISR()` 来完成相应的入队动作而不是普通的 `xQueueSend()`. 同样道理适用于其他类型的同步原语对象例如信号量(semaphore)[^4].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值