一、队列简介
队列 是任务到任务、任务到中断、中断到任务数据交流 的一种机制(消息传递 )使用队列的情况下如图,在写 、读队列 时,会进入临界区 ,无法触发任务调度,不会出现多任务冲突,只需要调用API函数即可 在队列中可以存储数量有限 、大小固定的数据 。队列中的每一个数据叫做“队列项目 ”,队列能够存储“队列项目”的最大数量 称为队列的长度 队列采用先进先出 (FIFO)的数据存储缓冲机制,即先入队的数据会先从队列中被读取,FreeRTOS也可以配置成先进后出的方式 FreeRTOS中队列采用实际值 传递,或传递地址 任何任务和中断 都可以向队列发送/读取消息当任务向一个队列发送消息时,可以指定一个阻塞时间 ,设置阻塞时间,确定是否等待或者返回 当任务A写入队列时,队列已满 的情况下,可以将该任务挂在阻塞列表 或等待发送列表 。当任务B从队列读取数据时,队列无数据 的情况下,将任务挂在阻塞列表 或等待接收列表里
二、队列相关函数
2.1 队列结构体
typedef struct QueueDefinition
{
int8_t * pcHead;
int8_t * pcWriteTo;
union
{
QueuePointers_t xQueue;
SemaphoreData_t xSemaphore;
} u;
List_t xTasksWaitingToSend;
List_t xTasksWaitingToReceive;
volatile UBaseType_t uxMessagesWaiting;
UBaseType_t uxLength;
UBaseType_t uxItemSize;
volatile int8_t cRxLock;
volatile int8_t cTxLock;
} xQUEUE;
2.2 队列相关API函数
使用队列时,主要流程为:创建队列 -> 写队列 -> 读队列 创建队列 相关API函数
xQueueCreate ( ) ;
xQueueCreateStatic ( ) ;
# define xQueueCreate ( uxQueueLength, uxItemSize)
xQueueGenericCreate ( ( uxQueueLength) , ( uxItemSize) , ( queueQUEUE_TYPE_BASE) )
xQueueSend ( ) ;
xQueueSendToBack ( ) ;
xQueueSendToFront ( ) ;
xQueueOverwrite ( ) ;
xQueueSendFromISR ( ) ;
xQueueSendToBackFromISR ( ) ;
xQueueSendToFrontFromISR ( ) ;
xQueueOverwriteFromISR ( ) ;
# define 函数名 xQueueGenericSend ( ( xQueue) , ( pvItemToQueue) , ( xTicksToWait) , 位置)
# define queueSEND_TO_BACK ( ( BaseType_t) 0 )
# define queueSEND_TO_FRONT ( ( BaseType_t) 1 )
# define queueOVERWRITE ( ( BaseType_t) 2 )
xQueueReceive ( ) ;
xQueuePeek ( ) ;
xQueueReceiveFromISR ( ) ;
xQueuePeekFromISR ( ) ;
BaseType_t xQueueReceive ( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait)
BaseType_t xQueuePeek ( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait)
三、队列操作实验
创建四个任务 start_task :创建task1、task2和task3task1 :当按键key0或key1按下,将按键键码拷贝到队列key_queue(入队 ),当key2按下,将传输大数据 ,拷贝大数据内容到队列big_data_queue 里task2 :读取队列key_queue中的消息(出队 ),打印出接收的键值task3 :从队列big_data_queue读取大数据 地址,通过地址访问大数据
# define configSUPPORT_DYNAMIC_ALLOCATION 1
# define INCLUDE_vTaskSuspend 1
# define START_TASK_STACK_SIZE 128
# define START_TASK_PRIO 1
TaskHandle_t start_task_handle;
# define TASK1_STACK_SIZE 128
# define TASK1_PRIO 2
TaskHandle_t task1_handle;
# define TASK2_STACK_SIZE 128
# define TASK2_PRIO 3
TaskHandle_t task2_handle;
# define TASK3_STACK_SIZE 128
# define TASK3_PRIO 4
TaskHandle_t task3_handle;
QueueHandle_t key_queue;
QueueHandle_t big_key_queue;
char buff[ ] = "hello world" ;
void task1 ( void * pvParameters )
{
uint8_t KeyNum = 0 ;
char * buf;
buf = buff;
BaseType_t err = 0 ;
while ( 1 )
{
KeyNum = Key_GetNum ( ) ;
if ( KeyNum== 0 || KeyNum== 1 )
{
err = xQueueSend ( key_queue, & KeyNum, portMAX_DELAY) ;
}
else if ( KeyNum == 2 )
{
err = xQueueSend ( big_date_queue, & buf, portMAX_DELAY) ;
}
vTaskDelay ( 10 ) ;
}
}
void task2 ( void * pvParameters )
{
uint8_t KeyNum = 0 ;
BaseType_t err = 0 ;
while ( 1 )
{
err = xQueueReceive ( key_queue, & keyNum, portMAX_DELAY) ;
}
}
void task3 ( void * pvParameters )
{
char * buf;
BaseType_t err = 0 ;
while ( 1 )
{
err = xQueueReceive ( big_date_queue, & buf, portMAX_DELAY) ;
}
}
void Start_task ( void * pvParameters )
{
taskENTER_CRITICAL ( ) ;
xTaskCreate ( task1,
"task1" ,
TASK1_STACK_SIZE,
NULL ,
TASK1_PRIO,
& task1_handle
) ;
xTaskCreate ( task2,
"task2" ,
TASK2_STACK_SIZE,
NULL ,
TASK2_PRIO,
& task2_handle
) ;
xTaskCreate ( task3,
"task3" ,
TASK3_STACK_SIZE,
NULL ,
TASK3_PRIO,
& task3_handle
) ;
vTaskDelete ( start_task_handle) ;
taskEXIT_CRITICAL ( ) ;
}
void freertos_demo ( )
{
key_queue = xQueueCreate ( 2 , sizeof ( uint8_t ) ) ;
big_date_queue = xQueueCreate ( 1 , sizeof ( char * ) ) ;
xTaskCreate ( Start_task,
"Start_task" ,
START_TASK_STACK_SIZE,
NULL ,
START_TASK_PRIO,
& start_task_handle
) ;
vTaskStartScheduler ( ) ;
}