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);
}
}