FreeRTOS队列使用

 队列的基本特性

队列是任务间通信的主要形式。常被用于任务与任务、中断与任务之间的消息传递,通常是FIFO的形式。

队列阻塞任务

 当一个任务读取空队列时,这个任务将进入阻塞态(不消耗cpu,cpu会去运行其他任务),直到队列不为空或者阻塞时长超过设定的阻塞时间,将进入就绪态。

当一个任务向满队列写时,这个任务会进入阻塞态(不消耗cpu,cpu会去运行其他任务),直到队列不为满或者阻塞时长超过设定的阻塞时间,将进入就绪态。

如果有多个任务因为同一个队列而进入阻塞态,当队列满足条件的时候,优先级最高的任务先解除阻塞态,其他任务继续阻塞。

中断里面只能使用后缀带有“FromISR”的API。

 队列使用(部分API使用)

typedef void * QueueHandle_t; //队列句柄

QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,UBaseType_t uxItemSize );//创建队列

BaseType_t xQueueSend( QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait);//向队列写数据

BaseType_t xQueueReceive(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait);//从队列里面读取数据

BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,const void   *pvItemToQueue,BaseType_t*pxHigherPriorityTaskWoken); 
//向队列里面写入数据,用在中断中

测试程序

总体设计:总共4个任务,2个队列

lcdtask:显示当前计数,并向队列TaskToTaskQueue里面写入当前计数;

testtask0:读取队列TaskToTaskQueue里面的数据,并串口打印;

testtask1:1s串口打印一次数据;

queuetask:读取队列TaskToIrqQueue的数据并打印出来;

串口中断:收到数据后往队列TaskToIrqQueue里面写入收到的数据。

创建任务和队列:

#define LCD_TASK_PRIO		        1   //任务优先级
#define LCD_TASK_STK_SIZE 		80  //任务堆栈大小
TaskHandle_t LCDTaskHandler;                //任务句柄
void LCDTaskFunc(void *pvParameters);       //任务函数

#define TEST_TASK0_PRIO		        2   //任务优先级
#define TEST_TASK0_STK_SIZE 		50  //任务堆栈大小
TaskHandle_t TestTask0Handler;              //任务句柄
void TestTask0Func(void *pvParameters);     //任务函数

#define TEST_TASK1_PRIO			3   //任务优先级
#define TEST_TASK1_STK_SIZE 		80  //任务堆栈大小
TaskHandle_t TestTask1Handler;              //任务句柄
void TestTask1Func(void *pvParameters);     //任务函数

#define QUEUE_TASK_PRIO		         4  //任务优先级
#define QUEUE_TASK_STK_SIZE 		80  //任务堆栈大小
TaskHandle_t QueueTaskHandler;              //任务句柄
void QueueTaskFunc(void *pvParameters);     //任务函数

QueueHandle_t TaskToIrqQueue;	//信息队列句柄
QueueHandle_t TaskToTaskQueue;	//信息队列句柄

void OtherTest(void )
{
    BaseType_t ret;
	
    BoardInitMcu();
    BoardInitPeriph();
	
    TaskToIrqQueue=xQueueCreate(1,255); //创建一个队列,队列有1项,每个项长为255byte。
    TaskToTaskQueue=xQueueCreate(5,2); //创建一个队列,队列有5项,每个项长为2byte
	
    ret=xTaskCreate((TaskFunction_t )LCDTaskFunc,     	
		    (const char*    )"lcdtask",   	
		    (uint16_t       )LCD_TASK_STK_SIZE, 
		    (void*          )NULL,				
		    (UBaseType_t    )LCD_TASK_PRIO,	
		    (TaskHandle_t*  )&LCDTaskHandler); 
	
    ret=xTaskCreate((TaskFunction_t )TestTask0Func,     	
		    (const char*    )"testtask0",   	
		    (uint16_t       )TEST_TASK0_STK_SIZE, 
		    (void*          )NULL,				
		    (UBaseType_t    )TEST_TASK0_PRIO,	
		    (TaskHandle_t*  )&TestTask0Handler);   
				
    ret=xTaskCreate((TaskFunction_t )TestTask1Func,     
		    (const char*    )"testtask1",   
		    (uint16_t       )TEST_TASK1_STK_SIZE, 
		    (void*          )NULL,
		    (UBaseType_t    )TEST_TASK1_PRIO,
		    (TaskHandle_t*  )&TestTask1Handler); 
	
    ret=xTaskCreate((TaskFunction_t )QueueTaskFunc,     
		    (const char*    )"queue task",   
		    (uint16_t       )QUEUE_TASK_STK_SIZE, 
		    (void*          )NULL,
		    (UBaseType_t    )QUEUE_TASK_PRIO,
		    (TaskHandle_t*  )&QueueTaskHandler); 
				
    vTaskStartScheduler(); 
}

各个任务函数:

//LCD显示任务当前计数,并把当前计数写入TaskToTaskQueue队列函数 
void  LCDTaskFunc(void *pvParameters)
{
    char  string[21] = {0};
    static uint8_t i=0;

    for(;;)
    {
        i++;
        sprintf(string, "%03d ", i);
        dis_string(1,0,(uint8_t *)string,1);
				
	xQueueSend(TaskToTaskQueue,&i,20);
		
	vTaskDelay(500);                 //延时500ms,也就是500个时钟节拍	
    }    
}

//Test0任务函数,读取 TaskToTaskQueue的数据并打印
void TestTask0Func(void *pvParameters)
{
    uint16_t i=0;
	
    while(1)
    {	
	if(TaskToTaskQueue!=NULL)	
	{			
	    xQueueReceive(TaskToTaskQueue,&i,portMAX_DELAY);
	    printf("current count:%d\r\n",i);
	}
    }
}   

//Test1任务函数
void TestTask1Func(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(1000);
	printf("task1\r\n");
    }
}

//从队列读取串口收到的数据并打印任务函数
void QueueTaskFunc(void *pvParameters)
{
    for(;;)
    {
	if(TaskToIrqQueue!=NULL)
	{
	    if(xQueueReceive(TaskToIrqQueue,str,10))
	    {
	        printf("serial:%s\r\n",str);
	    }
	}
    }
}

串口中断函数中写数据到队列:

void USART1_IRQHandler( void )
{
    BaseType_t pxHigherPriorityTaskWoken=pdFALSE;
	
    ……//省略部分代码
		
    xQueueSendFromISR(TaskToIrqQueue,SerialFrame.Buff,&pxHigherPriorityTaskWoken);
    //向队列写入数据,如果写队列使某个任务就绪,并且这个任务是当前所有任务中优先级最高的,那么pxHigherPriorityTaskWoken将会被设置为pdTRUE
		
    portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);
    //如果pxHigherPriorityTaskWoken为真将进行任务切换
}

 运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

freemote

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值