12.FreeRTOS队列集和事件标志组

01.初识freeRTOS
02.FreeRTOS的移植
03.FreeRTOS系统配置
04.FreeRTOS任务创建与删除
05.FreeRTOS任务挂起与恢复
06.FreeRTOS中断管理
07.FreeRTOS列表与列表项
08.FreeRTOS任务调度与任务切换
09.FreeRTOS时间片调度与任务相关函数
10.FreeRTOS队列操作
11.FreeRTOS信号量操作
12.FreeRTOS队列集和事件标志组
13.FreeRTOS任务通知
14.FreeRTOS软件定时器
15.FreeRTOS低功耗
16.FreeRTOS内存管理

12. FreeRTOS队列集和事件标志组

1. 队列集简介

在使用队列进行任务之间的“沟通交流”时,一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以使用队列集。FreeRTOS提供的队列集功能可以对多个队列进行“监听”,只要被监听的队列中有一个队列有有效的消息,那么队列集的读取任务都可以读取到消息,如果读取任务因读取队列集而被阻塞,那么队列集将解除读取任务的阻塞。使用队列集的好处在于,队列集可以读取多个队列中的消息,而无需遍历所有待读取的队列,以确定具体读取哪一个队列。

在这里插入图片描述

2. 队列集相关API函数

函数描述
xQueueCreateSet()创建队列集
xQueueAddToSet()队列添加到队列集中
xQueueRemoveFromSet()从队列集中移除队列
xQueueSelectFromSet()获取队列集中有有效消息的队列
xQueueSelectFromSetFromISR()在中断中获取队列集中有有效消息的队列
  • 创建队列集:

在这里插入图片描述

  • 往队列集中添加队列:

在这里插入图片描述

  • 从队列集中移除队列:

在这里插入图片描述

  • 获取队列集中的队列:

在这里插入图片描述

3. 队列集操作实验

  • 创建任务:

在这里插入图片描述

  • 相关变量定义与创建:

    //定义队列集
    QueueSetHandle_t queueset_handle;
    //定义队列
    QueueHandle_t    queue_handle;
    //定义信号量
    QueueHandle_t    semphr_handle;
    
    //队列集与队列的创建
    //创建队列集
    queueset_handle = xQueueCreateSet(2);  
    if(queueset_handle != NULL)
    {
        printf("队列集创建成功!\r\n");
    }
    
    //创建队列
    queue_handle = xQueueCreate(1, sizeof(uint8_t));   
    if(queue_handle != NULL)
    {
        printf("队列创建成功!\r\n");
    }
    
    //创建二值信号量
    semphr_handle = xSemaphoreCreateBinary();   
    if(semphr_handle != NULL)
    {
        printf("二值信号量创建成功!\r\n");
    }
    
  • 任务一:实现队列发送以及信号量释放

    void task1(void* pvParamter)
    {	
    	uint8_t key = 0;
    	
    	while(1)
    	{
    		key = key_scan(0);
    		
    		switch(key)
    		{
    			case KEY0_PRES: 
    			{
    				if(pdPASS == xQueueSend(queue_handle, &key, portMAX_DELAY))
    				{
    					printf("往队列queue_handle写入数据成功!\r\n");
    				}
    				break;
    			}
    			case KEY1_PRES: 
    			{
    				if(pdPASS == xSemaphoreGive(semphr_handle))
    				{
    					printf("信号量semphr_handle释放成功!\r\n");
    				}
    				break;
    			}
    			default:
    				break;
    		}	
    		vTaskDelay(20);
    	}
    }
    
  • 任务二:获取队列集消息

    void task2(void* pvParamter)
    {	
    	QueueSetMemberHandle_t member_handle;
    	uint8_t key = 0;
    	
    	while(1)
    	{
    		member_handle = xQueueSelectFromSet(queueset_handle, portMAX_DELAY);
    		
    		if(member_handle == queue_handle)
    		{
    			xQueueReceive(member_handle, &key, portMAX_DELAY);
    			printf("获取到的队列数据:%d\r\n", key);
    		}
    		else if(member_handle == semphr_handle)
    		{
    			xSemaphoreTake(member_handle, portMAX_DELAY);
    			printf("获取信号量成功!\r\n");
    		}
    	}
    }
    
  • 实验结果

    在这里插入图片描述

4. 事件标志组简介

  • 时间标志组简介:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 事件标志组与队列、信号量的区别:

    功能唤醒对象事件清除
    队列、信号量事件发生时,只会唤醒一个任务是消耗型的资源,队列的数据被读走就没了;信号量被获取后就减少
    事件标志组事件发生时,会唤醒所有符合条件的任务,可以理解为“广播”的作用被唤醒的任务有两个选择,可以让事件保留不动,也可以清除事件

5. 事件标志组相关API函数

函数描述
xEventGroupCreate()使用动态方式创建事件标志组
xEventGroupCreateStatic()使用静态方式创建事件标志组
xEventGroupClearBits()清零事件标志位
xEventGroupClearBitsFromISR()在中断中清零事件标志位
xEventGroupSetBits()设置事件标志位
xEventGroupSetBitsFromISR()在中断中设置事件标志位
xEventGroupWaitBits()等待事件标志位
xEventGroupSync()设置事件标志位,并等待事件标志位
  • 动态方式创建事件标志组:

    在这里插入图片描述

  • 清除事件标志位:

    在这里插入图片描述

  • 设置事件标志位:

    在这里插入图片描述

  • 等待事件标志位:

    在这里插入图片描述

  • 同步函数:

    在这里插入图片描述

6. 事件标志组实验

  • 创建任务:

    在这里插入图片描述

  • 相关变量定义与创建:

    //定义事件标志组句柄
    EventGroupHandle_t  eventgroup_handle;
    #define EVENTBIT_0  (1 << 0)
    #define EVENTBIT_1  (1 << 1)
    
    //事件标志组的创建
    eventgroup_handle = xEventGroupCreate();
    if(eventgroup_handle != NULL)
    {
        printf("事件标志组创建成功!\r\n");
    }
    
  • 任务一:按键设置事件标志位

    void task1(void* pvParamter)
    {	
    	uint8_t key = 0;
    	
    	while(1)
    	{
    		key = key_scan(0);
    		
    		if(key == KEY0_PRES)
    		{
    			xEventGroupSetBits(eventgroup_handle, EVENTBIT_0);   //将事件标志组
    		}
    		else if(key == KEY1_PRES)
    		{
    			xEventGroupSetBits(eventgroup_handle, EVENTBIT_1);
    		}
    		vTaskDelay(20);
    	}
    }
    
  • 任务二:等待时间标志位

    void task2(void* pvParamter)
    {	
    	EventBits_t event_bit = 0;
    	
    	while(1)
    	{
    		event_bit = xEventGroupWaitBits(eventgroup_handle, EVENTBIT_0 | EVENTBIT_1, pdTRUE, pdTRUE, portMAX_DELAY);
    		printf("等待的事件标志位的值为%#x\r\n", event_bit);
    	}
    }
    
  • 实验结果:

    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值