freeRTOS——队列集知识总结及实战

1队列集概念

可以在任务间传递不同数据类型的消息
作用:用于对多个队列或信号量进行“监听”,其中不管哪一个消息到来,都可让任务退出阻塞状态

2队列集API函数

freeRTOS——队列集知识总结及实战_第1张图片
1)创建队列集
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength );
形参:uxEventQueueLength 可容纳的队列数量
返回值: NULL 队列集创建失败
其他 队列集创建成功,返回句柄
2)队列集中添加和移除队列
BaseType_t
xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore ,
QueueSetHandle_t xQueueSet );
BaseType_t
xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore ,
QueueSetHandle_t xQueueSet );
形参:xQueueOrSemaphore 队列句柄
xQueueSet 队列集
返回值: pdTURE 操作成功
pdFALSE 操作失败
注意:在队列集添加和移除之前,必须没有有效的消息
3)任务中获取队列集中有效消息队列
QueueSetMemberHandle_t
xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
TickType_t const xTicksToWait )
形参:xQueueSet 队列集
xTicksToWait 超级阻塞时间
返回值: NULL 获取消息失败
其他值 获取到消息的队列句柄

3 队列集使用流程

1、启用队列集功能需要将宏configUSE_QUEUE_SETS 配置为 1
2、创建队列集
3、创建队列或信号量
4、往队列集中添加队列或信号量
5、往队列发送信息或释放信号量
6、获取队列集的消息

4队列集实战

freeRTOS——队列集知识总结及实战_第2张图片

4.1freertos_demo.c


#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

//1 FreeRTOS配置

//1.1START_TASK 任务 配置
//包括: 任务句柄 任务优先级 堆栈大小 创建任务

#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

//1.2TASK1 任务 配置
//包括: 任务句柄 任务优先级 堆栈大小 创建任务
 
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

//1.3 TASK2 任务 配置
// 包括: 任务句柄 任务优先级 堆栈大小 创建任务
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

//1.4 队列集句柄、队列句柄以及信号量句柄定义
QueueSetHandle_t  queueset_handle;          
QueueHandle_t     queue_handle;
SemaphoreHandle_t  semphr_handle;

//1.5 队列集支持消息个数、队列长队、队列每个消息大小、二值信号量消息个数宏定义
#define QUEUE_LENGTH            1                   /* 队列支持的消息个数 */
#define QUEUE_ITEM_SIZE         sizeof(uint8_t)    /* 队列中每条消息的大小 */
#define SEMAPHORE_BINARY_LENGTH 1                   /* 二值信号量的有效长度 */
#define QUEUESET_LENGTH         (QUEUE_LENGTH+ SEMAPHORE_BINARY_LENGTH)  /* 队列集支持的消息个数 */

//2 FreeRTOS例程入口函数
// * @param       无
// * @retval      无
void freertos_demo(void)
{
    //2.1创建队列集
    queueset_handle = xQueueCreateSet(QUEUESET_LENGTH);                //可以存放两个队列
    if(queueset_handle != NULL)
    {
        printf("队列集创建成功!!!\r\n");
    }
    //2.1创建队列
    queue_handle = xQueueCreate(QUEUE_LENGTH,QUEUE_ITEM_SIZE);
    
    //2.2创建二值信号量
    semphr_handle = xSemaphoreCreateBinary();
    
    //2.3 将队列和队列信号量插入到队列集中
    xQueueAddToSet(queue_handle,queueset_handle);
    xQueueAddToSet(semphr_handle,queueset_handle);

    xTaskCreate((TaskFunction_t )start_task,            /* 任务函数 */
                (const char*    )"start_task",          /* 任务名称 */
                (uint16_t       )START_STK_SIZE,        /* 任务堆栈大小 */
                (void*          )NULL,                  /* 传入给任务函数的参数 */
                (UBaseType_t    )START_TASK_PRIO,       /* 任务优先级 */
                (TaskHandle_t*  )&StartTask_Handler);   /* 任务句柄 */
    vTaskStartScheduler();
}

//3 start_task
// * @param       pvParameters : 传入参数(未用到)
// * @retval      无
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           /* 进入临界区 */
   
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    /* 创建任务2 */
    xTaskCreate((TaskFunction_t )task2,
                (const char*    )"task2",
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
    taskEXIT_CRITICAL();            /* 退出临界区 */
}

//4.task1 按key0键往队列中写入数据,按key1键释放二值信号量
// * @param       pvParameters : 传入参数(未用到)
// * @retval      无
void task1(void *pvParameters)
{
    //定义写入队列函数返回值变量与key值变量
    uint8_t key = 0;
    BaseType_t err = 0;
    
    while(1)
    {
        key = key_scan(0);
    //2.1 如果按下按键key0,往队列中写入数据
        if(key == KEY0_PRES)
        {
            err = xQueueSend(queue_handle, &key, portMAX_DELAY);
            if(err == pdPASS)
            {
                printf("往队列queue写入数据成功\r\n");
            }
        }
    //2.2 如果按下按键key1,释放二值信号量
         else if(key == KEY1_PRES)
        {
            err =xSemaphoreGive(semphr_handle);
            if(err == pdPASS)
            {
                printf("释放信号量成功\r\n");
            }
        }
        vTaskDelay(10);
    }
}

//5.task2 获取队列集的消息
// * @param       pvParameters : 传入参数(未用到)
// * @retval      无
void task2(void *pvParameters)
{
    QueueSetMemberHandle_t member_handle; 
    uint8_t key = 0;
    
    while(1)
    {
        member_handle = xQueueSelectFromSet( queueset_handle,portMAX_DELAY);
        if(member_handle == queue_handle)
        {
            xQueueReceive(queue_handle,&key,portMAX_DELAY);
            printf("获取到队列数据:%d\r\n",key);
        }
        else if(member_handle == semphr_handle)
        {
            xSemaphoreTake(semphr_handle, portMAX_DELAY);
            printf("获取二值信号量成功\r\n");
        }
    }
}

你可能感兴趣的:(单片机,stm32,嵌入式硬件)