简析队列和中断的综合运用。
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 );
}