当前位置 博文首页 > freemote的博客:FreeRTOS事件标志组与事件标志位使用
事件位用于指示事件是否发生。也叫做事件标志位。
可用位表示:当信息收到且准备好处理时,设置为1;当没有收到信息且等待处理时,设置为0。
事件标志组是一组事件位,事件标志组中的事件位通过编号来访问。
configUSE_16_BIT_TICKS这个宏设置为1,那么数据类型是8位;设置为0,那么数据类型是24位。
事件标志组里面的事件标志位存在EventBits类型的变量中,事件标志位0存在这个变量的0位,事件标志位1存在这个变量的1位,以此类推。
事件标志组API允许任务或其他事情设置、清除事件标志组中的1位或多位,也允许任务进入阻塞态等待。
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) //软件定时器任务堆栈大小
再次编译,通过。
运行结果
?
cs