【FreeRTOS】小白进阶之如何使用FreeRTOS事件标志组

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liwei16611/article/details/82597043

事件标志组使用浅析。

1、头文件声明

#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"
#include "timers.h" 
#include "supporting_functions.h"

// 中断号 0 to 2 被用于 FreeRTOS Windows port
#define mainINTERRUPT_NUMBER	3

// 事件标志组三个位
#define mainFIRST_TASK_BIT	( 1UL << 0UL ) /* Event bit 0, which is set by a task. */
#define mainSECOND_TASK_BIT	( 1UL << 1UL ) /* Event bit 1, which is set by a task. */
#define mainISR_BIT			( 1UL << 2UL ) /* Event bit 2, which is set by an ISR. */

// 任务声明
static void vIntegerGenerator( void *pvParameters );
static void vEventBitSettingTask( void *pvParameters );
static void vEventBitReadingTask( void *pvParameters );

// daemon 任务,用于处理中断延时回调函数
void vPrintStringFromDaemonTask( void *pvParameter1, uint32_t ulParameter2 );

// 启动模拟中断
static uint32_t ulEventBitSettingISR( void );

// 事件标志组定义
EventGroupHandle_t xEventGroup;

2、启动任务

int main( void )
{
	// 创建事件标志组
	xEventGroup = xEventGroupCreate();

	// 设置事件任务
	xTaskCreate( vEventBitSettingTask, "BitSetter", 1000, NULL, 1, NULL );

    // 读事件标志任务
	xTaskCreate( vEventBitReadingTask, "BitReader", 1000, NULL, 2, NULL );

    // 启动模拟中断任务
	xTaskCreate( vIntegerGenerator, "IntGen", 1000, NULL, 3, NULL );

	// 注册中断函数
	vPortSetInterruptHandler( mainINTERRUPT_NUMBER, ulEventBitSettingISR );

	// 开始调度
	vTaskStartScheduler();

	for( ;; );
	return 0;
}

3、事件位设置任务

static void vEventBitSettingTask( void *pvParameters )
{
	const TickType_t xDelay200ms = pdMS_TO_TICKS( 200UL ), xDontBlock = 0;

	for( ;; )
	{
		vTaskDelay( xDelay200ms );

		// 设置事件位 0
		vPrintString( "Bit setting task -\t about to set bit 0.\r\n" );
		xEventGroupSetBits( xEventGroup, mainFIRST_TASK_BIT );

		vTaskDelay( xDelay200ms );

		// 设置事件位 1
		vPrintString( "Bit setting task -\t about to set bit 1.\r\n" );
		xEventGroupSetBits( xEventGroup, mainSECOND_TASK_BIT );
	}
}

4、中断处理函数

static uint32_t ulEventBitSettingISR( void )
{
	BaseType_t xHigherPriorityTaskWoken;
	
	//
	//The string is not printed within the interrupt service, but is instead
	//sent to the RTOS daemon task for printing.  It is therefore declared static to
	//ensure the compiler does not allocate the string on the stack of the ISR (as the
	//ISR's stack frame will not exist when the string is printed from the daemon
	//task. 
	// 
	static const char *pcString = "Bit setting ISR -\t about to set bit 2.\r\n";

	xHigherPriorityTaskWoken = pdFALSE;

	// 将打印信息传递给中断延时回调函数
	xTimerPendFunctionCallFromISR( vPrintStringFromDaemonTask, ( void * ) pcString, 0, &xHigherPriorityTaskWoken );

	// 设置事件位 2
	xEventGroupSetBitsFromISR( xEventGroup, mainISR_BIT, &xHigherPriorityTaskWoken );

	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

5、读事件标志位

static void vEventBitReadingTask( void *pvParameters )
{
	const EventBits_t xBitsToWaitFor = ( mainFIRST_TASK_BIT | mainSECOND_TASK_BIT | mainISR_BIT );
	EventBits_t xEventGroupValue;

	for( ;; )
	{
		/* Block to wait for event bits to become set within the event group. */
		xEventGroupValue = xEventGroupWaitBits( xEventGroup,     // 要读的事件标志组
												xBitsToWaitFor,  // 需要测试的事件位
												pdTRUE,
												pdFALSE,
												portMAX_DELAY );

		if( ( xEventGroupValue & mainFIRST_TASK_BIT ) != 0 )
		{
			vPrintString( "Bit reading task -\t event bit 0 was set\r\n" );
		}

		if( ( xEventGroupValue & mainSECOND_TASK_BIT ) != 0 )
		{
			vPrintString( "Bit reading task -\t event bit 1 was set\r\n" );
		}

		if( ( xEventGroupValue & mainISR_BIT ) != 0 )
		{
			vPrintString( "Bit reading task -\t event bit 2 was set\r\n" );
		}

		vPrintString( "\r\n" );
	}
}

6、中断延时触发回调函数

void vPrintStringFromDaemonTask( void *pvParameter1, uint32_t ulParameter2 )
{
	vPrintString( ( const char * ) pvParameter1 );
}

7、模拟中断触发函数

static void vIntegerGenerator( void *pvParameters )
{
TickType_t xLastExecutionTime;
const TickType_t xDelay500ms = pdMS_TO_TICKS( 500UL );

	/* Initialize the variable used by the call to vTaskDelayUntil(). */
	xLastExecutionTime = xTaskGetTickCount();

	for( ;; )
	{
		/* This is a periodic task.  Block until it is time to run again.
		The task will execute every 500ms. */
		vTaskDelayUntil( &xLastExecutionTime, xDelay500ms );

		/* Generate the interrupt that will set a bit in the event group. */
		vPortGenerateSimulatedInterrupt( mainINTERRUPT_NUMBER );
	}
}

猜你喜欢

转载自blog.csdn.net/liwei16611/article/details/82597043