FreeRTOS事件标志组与事件标志位使用

事件标志位

事件位用于指示事件是否发生。也叫做事件标志位。

可用位表示:当信息收到且准备好处理时,设置为1;当没有收到信息且等待处理时,设置为0。

 事件标志组

事件标志组是一组事件位,事件标志组中的事件位通过编号来访问。

事件标志组和事件标志位的数据类型 

configUSE_16_BIT_TICKS这个宏设置为1,那么数据类型是8位;设置为0,那么数据类型是24位。

事件标志组里面的事件标志位存在EventBits类型的变量中,事件标志位0存在这个变量的0位,事件标志位1存在这个变量的1位,以此类推。

特性

事件标志组API允许任务或其他事情设置、清除事件标志组中的1位或多位,也允许任务进入阻塞态等待。

部分API

typedef void * EventGroupHandle_t;           //事件标志组句柄
EventGroupHandle_t xEventGroupCreate( void );//创建事件标志组
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
                               const EventBits_t uxBitsToSet );
//设置标志位,参数uxBitsToSet是要设置的值
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, 
                                       const EventBits_t uxBitsToSet, 
                               BaseType_t *pxHigherPriorityTaskWoken );
//设置标志位,同于中断函数里面
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
                                 const EventBits_t uxBitsToWaitFor,
                                 const BaseType_t xClearOnExit,
                                 const BaseType_t xWaitForAllBits,
		                 const TickType_t xTicksToWait );
//读取标志位,参数uxBitsToWaitFor表示要读取的位,xClearOnExit表示读取之后是否清除,
//xWaitForAllBits表示是否等待所有位就绪,参数xTicksToWait 表示阻塞时间。

测试程序

总体设计:2个任务,1个事件标志组;

counttask:打印计数值,到50的时候设置事件标志1;

串口中断:收到数据后,设置事件标志0;

serialtask:读取事件标志位,打印相应的事件类型。

创建任务和事件标志组

#define COUNT_TASK_PRIO		            1	   //任务优先级
#define COUNT_TASK_STK_SIZE 		    80     //任务堆栈大小
TaskHandle_t CountTaskHandler;                     //任务句柄
void CountTaskFunc(void *pvParameters);            //任务函数

#define SERIAL_TASK_PRIO	            4	   //任务优先级
#define SERIAL_TASK_STK_SIZE 		    80     //任务堆栈大小
TaskHandle_t SerialTaskHandler;                    //任务句柄
void SerialTaskFunc(void *pvParameters);           //任务函数

EventGroupHandle_t  TestEventGroup;

#define BIT_0   1<<0
#define BIT_1   1<<1
#define BIT_2   1<<2

void OtherTest(void )
{
    BaseType_t ret;
	
    BoardInitMcu();
    BoardInitPeriph();

    TestEventGroup=xEventGroupCreate();

    ret=xTaskCreate( (TaskFunction_t )CountTaskFunc,     	
		     (const char*    )"counttask",   	
		     (uint16_t       )COUNT_TASK_STK_SIZE, 
		     (void*          )NULL,				
		     (UBaseType_t    )COUNT_TASK_PRIO,	
		     (TaskHandle_t*  )&CountTaskHandler); 
				
    ret=xTaskCreate((TaskFunction_t )SerialTaskFunc,     
		    (const char*    )"serialtask",   
		    (uint16_t       )SERIAL_TASK_STK_SIZE, 
		    (void*          )NULL,
		    (UBaseType_t    )SERIAL_TASK_PRIO,
		    (TaskHandle_t*  )&SerialTaskHandler); 
				
    vTaskStartScheduler(); 
}

任务函数

void  CountTaskFunc(void *pvParameters)
{
    static uint8_t i;
	
    for(;;)
    {
	i++;
		
	printf("count =%d\r\n",i);

	if(i==50)
	{
	    i=0;
	    xEventGroupSetBits( TestEventGroup, BIT_1 );
	}
						
	vTaskDelay(500);                 //延时500ms,也就是500个时钟节拍	
    }
}
  
void SerialTaskFunc(void *pvParameters)
{
    EventBits_t value;
	
    for(;;)
    {
	value =xEventGroupWaitBits( TestEventGroup,
	        BIT_0|BIT_1,  //位0和位1
	        pdTRUE ,      //读取之后,清除相应的位,若设置为pdFALSE则不清除
	        pdFALSE,      //任意一个位置1,如果设置为pdTRUE,则要等待全部的位0和位1都置1
	        portMAX_DELAY ); //阻塞时间

	if((value&BIT_0)==BIT_0)
	{
            printf("serial \r\n");
	}
	else
	{
	    if((value&BIT_1)==BIT_1)
	    {
		printf("count \r\n");
	    }
	    else
	    {
		printf("default");
	    }
	}			
	vTaskDelay(10);
    }
}

串口中断

void USART1_IRQHandler( void )
{
    BaseType_t pxHigherPriorityTaskWoken=pdFALSE;

    //省略部分代码,列出关键部分

    if(RESET != __HAL_UART_GET_FLAG(&UartHandle,UART_FLAG_IDLE))//空闲中断
    {                   
	__HAL_UART_CLEAR_IDLEFLAG(&UartHandle);

        /*事件标志组*/
	xEventGroupSetBitsFromISR(TestEventGroup,(1<<0),&pxHigherPriorityTaskWoken );
	portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
    }
}

编译报错

Error: L6218E: Undefined symbol xEventGroupSetBitsFromISR (referred from uart-board.o).

搜索发现xEventGroupSetBitsFromISR这个函数是条件编译,需要configUSE_TRACE_FACILITY、INCLUDE_xTimerPendFunctionCall、configUSE_TIMERS都设置为1。

再次编译报错

..\src\FreeRTOS\include\FreeRTOS.h(286): error:  #35: #error directive: If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined.

  #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined.

搜索代码发现,如果configUSE_TIMERS 设置为1,那么就需要设置timer任务的优先级、堆大小、队列长度等。

#define configTIMER_TASK_PRIORITY    (configMAX_PRIORITIES-1)     //软件定时器优先级
#define configTIMER_QUEUE_LENGTH     5                            //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPT  (configMINIMAL_STACK_SIZE*2) //软件定时器任务堆栈大小

再次编译,通过。

运行结果

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

freemote

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值