FreeRTOS学习笔记(8)

13、队列集

13.1 队列集简介

一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以使用队列集。

队列集相关API函数介绍:

 创建队列集函数:

QueueSetHandle_t     xQueueCreateSet( const  UBaseType_t   uxEventQueueLength );

队列添加到队列集函数:

BaseType_t xQueueAddToSet( QueueSetMemberHandle_t       xQueueOrSemaphore ,                           QueueSetHandle_t           xQueueSet      );

需要注意的是,队列在被添加到队列集之前,队列中不能有有效的消息 

队列集移除队列函数: 

BaseType_t   xQueueRemoveFromSet( QueueSetMemberHandle_t      xQueueOrSemaphore ,                                   QueueSetHandle_t           xQueueSet );

需要注意的是,队列在从队列集移除之前,必须没有有效的消息

获取队列集中有有效消息函数:

QueueSetMemberHandle_t     xQueueSelectFromSet( QueueSetHandle_t         xQueueSet,                                                 TickType_t const         xTicksToWait )

13.2 队列集编程实战

freertos_demo.c:

/**
 ****************************************************************************************************
 * @file        freertos.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.4
 * @date        2022-01-04
 * @brief       FreeRTOS 移植实验
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 精英F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
#include "./MALLOC/malloc.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
 #define START_TASK_STACK_SIZE 128
 #define START_TASK_PRIORITY   1
 TaskHandle_t  Start_Task_Handler;
 void start_task( void * pvParameters );
 
 /* Task1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
 #define TASK1_STACK_SIZE 128
 #define TASK1_PRIORITY   2
 TaskHandle_t  Task1_Handler;
 void task1( void * pvParameters );
 
 /* Task2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
 #define TASK2_STACK_SIZE 128
 #define TASK2_PRIORITY   3
 TaskHandle_t  Task2_Handler;
 void task2( void * pvParameters );
 
 
/******************************************************************************************************/
QueueSetHandle_t QueueSet_Handler;
QueueHandle_t Queue_Handler;
QueueHandle_t Semaphore_Handler;
/*
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
    xTaskCreate(( TaskFunction_t      ) start_task,
               (char *                ) "start_task", 
               (configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,
               (void *                ) NULL,
               (UBaseType_t           ) START_TASK_PRIORITY,
               (TaskHandle_t *        ) &Start_Task_Handler );
    vTaskStartScheduler();//开启任务调度器
}

 void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();                                       /* 进入临界区 */
    QueueSet_Handler = xQueueCreateSet( 2 );                    /*创建队列集*/
    if(QueueSet_Handler != NULL)
    {
        printf("队列集创建成功!\r\n");
    }
    Queue_Handler = xQueueCreate( 1, sizeof(uint8_t) );         /*创建队列*/
    Semaphore_Handler = xSemaphoreCreateBinary();               /*创建二值信号量*/
    
    xQueueAddToSet( Queue_Handler,QueueSet_Handler );           /*将队列添加到队列集中*/
    xQueueAddToSet( Semaphore_Handler,QueueSet_Handler );       /*将信号量添加到队列集中*/
    /*创建任务1*/   
    xTaskCreate(( TaskFunction_t       ) task1,
               (char *                ) "task1", 
               (configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,
               (void *                ) NULL,
               ( UBaseType_t          ) TASK1_PRIORITY,
               (TaskHandle_t *        ) &Task1_Handler );
    
    /*创建任务2*/
    xTaskCreate(( TaskFunction_t       ) task2,
               (char *                ) "task2", 
               (configSTACK_DEPTH_TYPE) TASK2_STACK_SIZE,
               (void *                ) NULL,
               ( UBaseType_t          ) TASK2_PRIORITY,
               (TaskHandle_t *         ) &Task2_Handler );
               
    vTaskDelete(NULL);//删除开始任务
    taskEXIT_CRITICAL();            /* 退出临界区 */
}


/*任务一,实现队列发送以及信号量释放*/
void task1( void * pvParameters )
{
    uint8_t Key = 0;
    BaseType_t Err;
    while(1)
    {
        Key = key_scan(0);
        if(Key == KEY0_PRES)
        {
            Err = xQueueSend(Queue_Handler,&Key,portMAX_DELAY);
            if(Err == pdPASS)
            {
                printf("队列数据写入成功!\r\n");
            }
        }
        else if(Key == KEY1_PRES)
        {
            Err = xSemaphoreGive(Semaphore_Handler);
            if(Err == pdPASS)
            {
                 printf("二值信号量释放成功!\r\n");
            }
        }
        vTaskDelay(10);
    }
}

/*任务二,实现获取队列集的消息*/
void task2( void * pvParameters )
{ 
    QueueSetMemberHandle_t  Member_Handler;
    uint8_t Key;
    while(1)
    {    
        Member_Handler = xQueueSelectFromSet( QueueSet_Handler,portMAX_DELAY );
        if(Member_Handler == Queue_Handler)
        {
            xQueueReceive(Queue_Handler,&Key,portMAX_DELAY);
            printf("获取到的队列数据为:%d\r\n",Key);
        }
        else if(Member_Handler == Semaphore_Handler)
        {
            xSemaphoreTake(Semaphore_Handler,portMAX_DELAY);
            printf("获取信号量成功!!!\r\n");
        }

    }
}



 
 

14、事件标志组

14.1 事件标志组简介

事件标志位:用一个位来表示事件是否发生。

事件标志组:一组事件标志位的集合,可以简单理解为一个整数。

事件标志组的特点:

1、每一位表示一个事件。(高8位不能表示

2、每一位事件的含义由用户自己决定。

3、任意任务或中断都可以读写这些位。

4、可以等待某一位或者多位同时成立。

一个事件标志组使用32位无符号数据类型变量存储事件标志,其中高8位用作存储事件标志组的控制信息,低24位用作存储事件标志

14.2 事件标志组相关的API函数:

这里主要介绍等待事件标志位API函数:

14.3 事件标志组编程实战

freertos_demo.c:

/**
 ****************************************************************************************************
 * @file        freertos.c
 * @author      正点原子团队(ALIENTEK)
 * @version     V1.4
 * @date        2022-01-04
 * @brief       FreeRTOS 移植实验
 * @license     Copyright (c) 2020-2032, 广州市星翼电子科技有限公司
 ****************************************************************************************************
 * @attention
 *
 * 实验平台:正点原子 精英F103开发板
 * 在线视频:www.yuanzige.com
 * 技术论坛:www.openedv.com
 * 公司网址:www.alientek.com
 * 购买地址:openedv.taobao.com
 *
 ****************************************************************************************************
 */

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
#include "./MALLOC/malloc.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"
/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
 #define START_TASK_STACK_SIZE 128
 #define START_TASK_PRIORITY   1
 TaskHandle_t  Start_Task_Handler;
 void start_task( void * pvParameters );
 
 /* Task1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
 #define TASK1_STACK_SIZE 128
 #define TASK1_PRIORITY   2
 TaskHandle_t  Task1_Handler;
 void task1( void * pvParameters );
 
 /* Task2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
 #define TASK2_STACK_SIZE 128
 #define TASK2_PRIORITY   3
 TaskHandle_t  Task2_Handler;
 void task2( void * pvParameters );
 
 
/******************************************************************************************************/
EventGroupHandle_t EventGroup_Handler;
#define EVENT_BIT0      (1<<0)
#define EVENT_BIT1      (1<<1)
/*
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
    
    xTaskCreate(( TaskFunction_t      ) start_task,
               (char *                ) "start_task", 
               (configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,
               (void *                ) NULL,
               (UBaseType_t           ) START_TASK_PRIORITY,
               (TaskHandle_t *        ) &Start_Task_Handler );
    vTaskStartScheduler();//开启任务调度器
}

 void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();           /* 进入临界区 */
    EventGroup_Handler = xEventGroupCreate();
    if(EventGroup_Handler != NULL)
    {
        printf("事件标志组创建成功!\r\n");
    }
    /*创建任务1*/
    xTaskCreate(( TaskFunction_t       ) task1,
               (char *                ) "task1", 
               (configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,
               (void *                ) NULL,
               ( UBaseType_t          ) TASK1_PRIORITY,
               (TaskHandle_t *        ) &Task1_Handler );
    
    /*创建任务2*/
    xTaskCreate(( TaskFunction_t       ) task2,
               (char *                ) "task2", 
               (configSTACK_DEPTH_TYPE) TASK2_STACK_SIZE,
               (void *                ) NULL,
               ( UBaseType_t          ) TASK2_PRIORITY,
               (TaskHandle_t *         ) &Task2_Handler );
               
    vTaskDelete(NULL);//删除开始任务
    taskEXIT_CRITICAL();            /* 退出临界区 */
}


/*任务一,模拟事件的发生*/
void task1( void * pvParameters )
{
   uint8_t Key;
    while(1)
    {
        Key =key_scan(0);
        if(Key == KEY0_PRES)
        {
            xEventGroupSetBits( EventGroup_Handler,EVENT_BIT0);     /*将事件标志组的Bit0置1*/
        }
        else if(Key == KEY1_PRES)
        {
            xEventGroupSetBits( EventGroup_Handler,EVENT_BIT1);     /*将事件标志位的Bit1置1*/
        }
        vTaskDelay(10);
    }
}

/*任务二,等待事件标志组*/
void task2( void * pvParameters )
{ 
    EventBits_t Event_Bit = 0;
    while(1)
    {    
        Event_Bit = xEventGroupWaitBits(         EventGroup_Handler,        /*事件标志组句柄*/
                                                 EVENT_BIT0|EVENT_BIT1,     /*等待事件标志组的Bit0和Bit1*/
                                                 pdTRUE,                    /*成功等待到事件标志位后,清除事件标志组中的Bit0和Bit1*/
                                                 pdTRUE,                    /*等待事件标志组的Bit0和Bit1位都置1,就成立*/
                                                 portMAX_DELAY );           /*死等*/
        printf("等待到的事件标志位值为:%#x\r\n",Event_Bit);
    }
}



 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值