Перевод может содержать ошибки. Читайте первоисточник: FreeRTOS xQueueReceive() API function descriptions
| Назад: [xQueueSendToFrontFromISR()] | Вверх: [ИПП: Очереди] | Вперёд: [xQueueReceiveFromISR()] |
Функция объявляется в файле queue.h
BaseType_t xQueueReceive
(
QueueHandle_t xQueue,
void *pvBuffer,
TickType_t xTicksToWait
);
До версии FreeRTOS V9.0.1 это макрос, который вызвает функцию xQueueGenericReceive(). Начиная с версии FreeRTOS V10.0.0 это самостоятельная функция.
Макрос принимает элемент из очереди. Элемент забирается копированием (НЕ по указателю), поэтому необходимо предоставить буфер достаточного размера. Количество копируемых байт зависит от размера элемента очереди. А размер элемента определяется при создании очереди.
Данный макрос нельзя вызывать из обработчиков прерываний. Используйте xQueueReceiveFromISR(), если необходимо принять элемент из очереди, находясь в обработчике прерывания.
Параметры
| xQueue | Хэндлер очереди, из которой необходимо принять элемент. |
| pvBuffer | Указатель на буфер, в который будут скопированы данные из области хранения очереди. При этом количество байт, скопированное из области хранения очереди в буфер, определяется размером элемента очереди. А собственно размер элемента указывается при создании очереди. |
| xTicksToWait | Максимальное время, в течение которого задача будет блокироваться в ожидании получения элемента из очереди, если очередь пуста на момент вызова. Время задаётся в тиках ядра ОС. Для перевода реального времени в тики ядра ОС следует использовать константу portTICK_PERIOD_MS или макрос pdMS_TO_TICKS(). Если значение xTicksToWait установлено равным 0, то возврат будет выполнен немедленно, без блокировки задачи, даже если очередь пуста. Если значение xTicksToWait установлено равным portMAX_DELAY и INCLUDE_vTaskSuspend во FreeRTOSConfig.h установлен в '1', то задача будет блокироваться на неопределённое время до тех пор, пока в очереди не появится элемент. |
Возвращаемое значение
pdTRUE если элемент был получен из очереди. Иначе возвращается pdFALSE .
Пример использования:
Данный пример показывает, как можно отправлять в очередь и принимать из неё целые структуры и указатели на структуры.
/* В данном примере показано, как передавать через очередь всю структуру и,
поскольку структура достаточно большая, как передавать ссылку на на
переменные этого типа.
/* Определяем переменную, имеющую тип структуры AMMessage. */
struct AMessage
{
char ucMessageID;
char ucData[ 20 ];
} xMessage;
/* Очередь для отправки и приёма структур struct AMessage целиком. */
QueueHandle_t xStructQueue = NULL;
/* Очередь для отправки и приёма указателей на структуры struct AMessage. */
QueueHandle_t xPointerQueue = NULL;
void vCreateQueues( void )
{
xMessage.ucMessageID = 0xab;
memset( &( xMessage.ucData ), 0x12, 20 );
/* Создаём очередь, используемую для пересылки структур struct AMessage целиком.
Очередь может быть создана после запуска планировщика FreeRTOS, но нужно
позаботиться о том, чтобы эта очередь нигде не использовалась до её создания. */
xStructQueue = xQueueCreate(
10, /* Количество элементов, которое может содержаться в очереди. */
sizeof( xMessage ) /* Размер каждого элемента очереди. В данном случае он весьма большой. */
);
/* Создаём очередь, которая используется для пересылки указателей
на структуры struct AMessage. */
xPointerQueue = xQueueCreate(
10, /* Количество элементов, которое может содержаться в очереди. */
sizeof( &xMessage )/* Размер элемента выбирается таким, чтобы вместить указатель на структуру struct AMessage. */
);
if( ( xStructQueue == NULL ) || ( xPointerQueue == NULL ) )
{
/* По меньшей мере одна из очередей не была создана, т.к. в куче
не хватило памяти. Обрабатываем здесь эту ошибку. Также очереди
могут быть созданы статически. */
}
}
/* Задача, в которой выполняется отправка в очереди.. */
void vATask( void *pvParameters )
{
struct AMessage *pxPointerToxMessage;
/* Отправка всей структуры в очередь. Длина очереди - 10 элементов (структур). */
xQueueSend(
xStructQueue, /* Хэндлер очереди. */
( void * ) &xMessage,/* Адрес переменной xMessage. Отсюда в область хранения очереди будет скопировано sizeof( struct AMessage ) байт. */
( TickType_t ) 0 /* Задача не будет блокироваться, если очередь заполнена. Чтобы проверить, был ли элемент отправлен в очередь, необходимо проверить значение, возвращаемое xQueueSend(). */
);
/* Сохраняем адрес переменной xMessage в переменной-указателе. */
pxPointerToxMessage = &xMessage;
/* Отправляем адрес переменной xMessage в очередь. Длина очереди - 10 элементов (указателей на структуры). */
xQueueSend(
xPointerQueue, /* Хэндлер очереди. */
( void * ) &pxPointerToxMessage,/* 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. */
( TickType_t ) 0 /* Задача не будет блокироваться, если очередь заполнена. Чтобы проверить, был ли элемент отправлен в очередь, необходимо проверить значение, возвращаемое xQueueSend(). */
);
/* ... */
}
/* Задача, в которой выполняетс чтение из очередей. */
void vADifferentTask( void *pvParameters )
{
struct AMessage xRxedStructure, *pxRxedPointer;
if( xStructQueue != NULL )
{
/* Принимаем сообщение из очереди, содержащей элементы в виде
структуры struct AMessage. Задача блокируется не более, чем
на 10 тиков ядра ОС, если очередь пуста на момент выполнения чтения.
Элемент считывается в переменную с типом struct AMessage, поэтому
после возврата из xQueueReceive() переменная xRxedStructure будет
содержать копию переменной xMessage. */
if( xQueueReceive( xStructQueue,
&(xRxedStructure),
(TickType_t) 10 ) == pdPASS )
{
/* Теперь переменная xRxedStructure содержит копию переменной xMessage. */
}
}
if( xPointerQueue != NULL )
{
/* Принимаем сообщение из очереди, содержащей указатели
на структуры struct AMessage. Задача блокируется не более,
чем на 10 тиков ядра ОС, если очередь пуста на момент выполнения чтения.
Элемент из очереди считывается в переменную-указатель,
и поскольку полученное значение является указателем
на переменную xMessage, после возврата из xQueueReceive()
переменная-указатель pxRxedPointer будет указывать
на переменную xMessage. */
if( xQueueReceive( xPointerQueue,
&(pxRxedPointer),
(TickType_t) 10 ) == pdPASS )
{
/* Теперь переменная-указатель *pxRxedPointer указывает
на переменную xMessage. */
}
}
/* ... */
}