版权声明:本文为博主原创文章,未经博主允许不得转载。 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 );
}
}