简析队列和中断的综合运用。

1、头文件声明

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "supporting_functions.h"

// 模拟中断号,中断号 0 和 2 已经被 FreeRTOS Windows port 占用
#define mainINTERRUPT_NUMBER	3

// 任务
static void vIntegerGenerator( void *pvParameters );
static void vStringPrinter( void *pvParameters );

// 中断函数
static uint32_t ulExampleInterruptHandler( void );

// 队列
QueueHandle_t xIntegerQueue, xStringQueue;

2、启动任务

int main( void )
{
    // 创建队列
    xIntegerQueue = xQueueCreate( 10, sizeof( uint32_t ) );
	xStringQueue = xQueueCreate( 10, sizeof( char * ) );

	// 创建任务:传递整形数据到中断
	xTaskCreate( vIntegerGenerator, "IntGen", 1000, NULL, 1, NULL );

	// 创建任务:处理字符串
	xTaskCreate( vStringPrinter, "String", 1000, NULL, 2, NULL );

	// 注册中断处理函数
	vPortSetInterruptHandler( mainINTERRUPT_NUMBER, ulExampleInterruptHandler );

	// 启动任务调度
	vTaskStartScheduler();

	for( ;; );
	return 0;
}

 3、任务

static void vIntegerGenerator( void *pvParameters )
{
	TickType_t xLastExecutionTime;
	const TickType_t xDelay200ms = pdMS_TO_TICKS( 200UL ), xDontBlock = 0;
	uint32_t ulValueToSend = 0;
	BaseType_t i;

	// 获取当前 tick
	xLastExecutionTime = xTaskGetTickCount();

	for( ;; )
	{
		// 延时 200ms 并更新时间 tick
		vTaskDelayUntil( &xLastExecutionTime, xDelay200ms );

		// 写数据到队列
		for( i = 0; i < 5; i++ )
		{
			xQueueSendToBack( xIntegerQueue, &ulValueToSend, xDontBlock );
			ulValueToSend++;
		}

		// 启动模拟中断
		vPrintString( "Generator task - About to generate an interrupt.\r\n" );
		vPortGenerateSimulatedInterrupt( mainINTERRUPT_NUMBER );
		vPrintString( "Generator task - Interrupt generated.\r\n\r\n\r\n" );
	}
}

static void vStringPrinter( void *pvParameters )
{
	char *pcString;

	for( ;; )
	{
		// block 等待数据
		xQueueReceive( xStringQueue, &pcString, portMAX_DELAY );

		vPrintString( pcString );
	}
}

// 中断处理函数
static uint32_t ulExampleInterruptHandler( void )
{
	BaseType_t xHigherPriorityTaskWoken;
	uint32_t ulReceivedNumber;

	static const char *pcStrings[] =
	{
		"String 0\r\n",
		"String 1\r\n",
		"String 2\r\n",
		"String 3\r\n"
	};

	xHigherPriorityTaskWoken = pdFALSE;

	// 读取队列数据
	while( xQueueReceiveFromISR( xIntegerQueue, &ulReceivedNumber, &xHigherPriorityTaskWoken ) != errQUEUE_EMPTY )
	{
		ulReceivedNumber &= 0x03;
		xQueueSendToBackFromISR( xStringQueue, &pcStrings[ ulReceivedNumber ], &xHigherPriorityTaskWoken );
	}

	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}