FreeRTOS实时操作系统(十二)事件标志组

系列文章

FreeRTOS实时操作系统(一)RTOS的基本概念

FreeRTOS实时操作系统(二)任务创建与任务删除(HAL库)

FreeRTOS实时操作系统(三)任务挂起与恢复

FreeRTOS实时操作系统(四)中断任务管理

FreeRTOS实时操作系统(五)进入临界区、任务调度器挂起与恢复

FreeRTOS实时操作系统(六)列表与列表项

FreeRTOS实时操作系统(七)时间片调度及RTOS的滴答定时器

FreeRTOS实时操作系统(八)任务状态查询及时间统计函数

FreeRTOS实时操作系统(九)时间延时函数及消息队列

FreeRTOS实时操作系统(十)信号量

FreeRTOS实时操作系统(十一)队列集

FreeRTOS实时操作系统(十二)事件标志组

FreeRTOS实时操作系统(十三)任务通知

FreeRTOS实时操作系统(十四)软件定时器

FreeRTOS实时操作系统(十五)Tickless低功耗模式

FreeRTOS实时操作系统(十六)内存管理



事件标志组

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

事件标志组是一组事件标志位的集合

特点:
1.每一个位表示一个事件(高8位不是)
2.每一位事件的含义由用户自己决定,1表示事件发生了,0表示事件未发生
3.任意任务或中断都可以读写这些位
4.可以等待某一位成立或等待多位同时成立

一个事件组包含了一个EventBits_t数据类型的变量,是一个16位或32位的无符号数据类型

typedef TickType_t EventBits_t;
#if ( configUSE_16_BIT_TICKS  = =  1 )
	typedef   uint16_t   TickType_t;
#else	
	typedef   uint32_t   TickType_t;
#endif

在这里插入图片描述

但是高8位用作存储事件标志组的控制信息,低24位用作存储事件标志,最多存储24个事件标志。

队列和信号量在事件发生的时候,只能有一个任务被唤醒,而且队列的数据在读取后就消失了,信号量在获取后就减少了;
事件标志组不同,事件发生的时候,会唤醒所有符合条件的任务,且可以选择保留事件或者清除事件。

事件组由 EventGroupHandle_t 类型的变量引用。
在事件组中实现的位数(或标志数)取决于 configUSE_16_BIT_TICKS or configTICK_TYPE_WIDTH_IN_BITS 是否用于控制 TickType_t 的类型:

如果 configUSE_16_BIT_TICKS 设置为 1,则事件组内实现的位数(或标志数)为 8; 如果 configUSE_16_BIT_TICKS 设置为 0,则为 24。

事件组中的所有事件位都 存储在 EventBits_t 类型的单个无符号整数变量中。 事件位 0 存储在位 0 中, 事件位 1 存储在位1 中,依此类推。

事件标志组API函数

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

1.动态创建API函数

EventGroupHandle_t    xEventGroupCreate ( void ) ; 

返回值:
NULL:事件标志组创建失败
其他值:事件标志组创建成功,返回其句柄

2.清除事件标志位API函数

EventBits_t  xEventGroupClearBits( EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToClear ) 

形参:
xEventGroup:待操作的事件标志组句柄
uxBitsToSet :待清零的事件标志位

返回值:
整数 :清零事件标志位之前事件组中事件标志位的值

3.设置事件标志位API函数

EventBits_t   xEventGroupSetBits(  EventGroupHandle_t xEventGroup,const EventBits_t uxBitsToSet ) 

形参:
xEventGroup :待操作的事件标志组句柄
uxBitsToSet :待设置的事件标志位

返回值:
整数:函数返回时,事件组中的事件标志位值

4.等待事件标志位API函数

EventBits_t   xEventGroupWaitBits( EventGroupHandle_t 	xEventGroup,
                             	   const EventBits_t 	uxBitsToWaitFor,
                                   const BaseType_t 	xClearOnExit,
                                   const BaseType_t 	xWaitForAllBits,
                                   TickType_t 		    xTicksToWait  )

形参:
xEvenrGroup :等待的事件标志组句柄
uxBitsToWaitFor:等待的事件标志位,可以用逻辑或等待多个事件标志位
xClearOnExit:等待到事件标志位后,清除对应的事件标志位,pdTRUE 清除uxBitsToWaitFor指定位,pdFALSE不清除
xWaitForAllBits :等待 uxBitsToWaitFor 中的所有事件标志位(逻辑与)pdTRUE等待的位全部为1,pdFALSE某个为1
xTicksToWait:等待的阻塞时间

返回值:
等待的事件标志位值 :等待事件标志位成功,返回等待到的事件标志位
其他值 :等待事件标志位失败,返回事件组中的事件标志位

可以等待某一位,也可以等待多位

5.同步函数

EventBits_t    xEventGroupSync(  EventGroupHandle_t xEventGroup,
								const EventBits_t uxBitsToSet,
								const EventBits_t 	uxBitsToWaitFor,
								TickType_t 		xTicksToWait) 

形参:
xEventGroup :等待事件标志所在事件组
uxBitsToSet :达到同步点后,要设置的事件标志
uxBitsToWaitFor: 等待的事件标志
xTicksToWait: 等待的阻塞时间

返回值:
等待的事件标志位值 :等待事件标志位成功,返回等待到的事件标志位
其他值 :等待事件标志位失败,返回事件组中的事件标志位

任务同步点是应用程序代码中的一个位置,在该位置任务将在阻塞状态(不消耗任何 CPU 时间)下等待,直到参与同步的所有其他任务 也到达其同步点。

实验测试

任务1:创建任务2和任务3,并且创建事件标志组
任务2;将事件标志组相应事件位置1,模拟事件发生
任务3:同时等待事件标志组中的多个事件位发生,发生全部置1进行处理

在这里插入图片描述

EventGroupHandle_t  eventgroup_handle;
#define EVENTBIT_0  (1 << 0)
#define EVENTBIT_1  (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_PRIO,
                (TaskHandle_t *         )   &start_task_handler );
    vTaskStartScheduler();
}


void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();               /* 进入临界区 */
    eventgroup_handle = xEventGroupCreate();
    if(eventgroup_handle != NULL)
    {
        printf("事件标志组创建成功!!\r\n");
    }
    
    xTaskCreate((TaskFunction_t         )   task1,
                (char *                 )   "task1",
                (configSTACK_DEPTH_TYPE )   TASK1_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK1_PRIO,
                (TaskHandle_t *         )   &task1_handler );
                
    xTaskCreate((TaskFunction_t         )   task2,
                (char *                 )   "task2",
                (configSTACK_DEPTH_TYPE )   TASK2_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK2_PRIO,
                (TaskHandle_t *         )   &task2_handler );
                             
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();                /* 退出临界区 */
}

/* 任务一,释放二值信号量 */
void task1( void * pvParameters )
{
    uint8_t key = 0;
    while(1) 
    {
        key = key_scan(0);
        if(key == KEY0_PRES)
        {
            xEventGroupSetBits( eventgroup_handle, EVENTBIT_0); /* 将事件标志组的bit0位置1 */
        }else if(key == KEY1_PRES)
        {
            xEventGroupSetBits( eventgroup_handle, EVENTBIT_1); /* 将事件标志组的bit1位置1 */
        }
        vTaskDelay(10);
    }
}

/* 任务二,获取二值信号量 */
void task2( void * pvParameters )
{
    EventBits_t event_bit = 0;
    while(1)
    {
        event_bit = xEventGroupWaitBits( eventgroup_handle,         /* 事件标志组句柄 */
                                         EVENTBIT_0 | EVENTBIT_1,   /* 等待事件标志组的bit0和bit1位 */
                                         pdTRUE,                    /* 成功等待到事件标志位后,清除事件标志组中的bit0和bit1位 */
                                         pdTRUE,                    /* 等待事件标志组的bit0和bit1位都置1,就成立 */
                                         portMAX_DELAY );           /* 死等 */
        printf("等待到的事件标志位值为:%#x\r\n",event_bit);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值