当前位置:   article > 正文

FreeRTOS学习第10篇--队列使用示例

FreeRTOS学习第10篇--队列使用示例

FreeRTOS学习第10篇–队列使用示例

本文目标:FreeRTOS学习第10篇–队列使用示例

按照本文的描述,可以进行简单的使用队列。

本文实验条件:拥有C语言基础,装有编译和集成的开发环境,比如:Keil uVision5

设计实验

在本次实验中,继续沿用上一篇的工程文件,将输入通过遥控器获取的数据改用队列的方式进行实现。

创建队列

函数原型

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
  • 1

函数描述:

函数 xQueueCreate 用于创建队列。

第 1 个参数uxQueueLength是队列支持的消息个数,最多能存放多少个数据(item)

第 2 个参数uxItemSize是每个消息的大小,单位字节。

返回值:非 0:成功,返回句柄,以后使用句柄来操作队列NULL:失败,因为内存不足

写队列

函数原型

BaseType_t xQueueSend(
     QueueHandle_t xQueue, /* 消息队列句柄 */
     const void * pvItemToQueue, /* 要传递数据地址 */
     TickType_t xTicksToWait /* 等待消息队列有空间的最大等待时间*/
 );
  • 1
  • 2
  • 3
  • 4
  • 5

函数描述:

第 1 个参数xQueue是消息队列句柄。

第 2 个参数pvItemToQueue要传递数据地址,每次发送都是将消息队列创建函数 xQueueCreate 所指定的单个消息大

小复制到消息队列空间中。

第 3 个参数xTicksToWait是当消息队列已经满时,等待消息队列有空间时的最大等待时间,单位系统时钟节拍。如果被设为 0,无法写入数据时函数会立刻返回;如果被设为 portMAX_DELAY,则会一直阻塞直到有空间可写

返回值,如果消息成功发送返回 pdPASS,失败返回 errQUEUE_FULL。

使用这个函数要注意的点:

  1. FreeRTOS 的消息传递是数据的复制,而不是传递的数据地址。

  2. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是xQueueSendFromISR。

  3. 如果消息队列已经满且第三个参数为 0,那么此函数会立即返回。

  4. 如果用户将 FreeRTOSConfig.h 文件中的宏定义 INCLUDE_vTaskSuspend 配置为 1 且第三个参数配置为 portMAX_DELAY,那么此发送函数会永久等待直到消息队列有空间可以使用。

  5. 消息队列还有两个函数 xQueueSendToBack 和 xQueueSendToFront,函数 xQueueSendToBack实现的是 FIFO 方式的存取,函数 xQueueSendToFront 实现的是 LIFO 方式的读写。我们这里说的函数 xQueueSend 等效于 xQueueSendToBack,即实现的是 FIFO 方式的存取。

读队列

函数原型

BaseType_t xQueueReceive(
     QueueHandle_t xQueue, /* 消息队列句柄 */
     void *pvBuffer, /* 接收消息队列数据的缓冲地址 */
     TickType_t xTicksToWait /* 等待消息队列有数据的最大等待时间 */
 );
  • 1
  • 2
  • 3
  • 4
  • 5

函数描述:

第 1 个参数xQueue是消息队列句柄。

第 2 个参数pvBuffer要传递数据地址,bufer 指针,队列的数据会被复制到这个 buffer复制多大的数据?在创建队列时已经指定了数据大小。缓冲区空间要大于等于消息队列创建函数 xQueueCreate 所指定的单个消息大小,否则取出的数据无法全部存储到缓冲区,从而造成内存溢出。

第 3 个参数xTicksToWait是当消息队列为空时,等待消息队列有数据的最大等待时间,单位系统时钟节拍。

本次实验示例代码片段

在本次工程中,按键获取数据的方式来自中断,在中断进行写队列,调用的如下的代码进行写队列:

    // 在中断的代码进行调用
    /* 写队列 */
    idata.dev = datas[0];
    idata.val = datas[2];
    xQueueSendFromISR(g_xQueuePlatform, &idata, NULL);
  • 1
  • 2
  • 3
  • 4
  • 5

而在任务中使用如下的代码进行读队列

xQueueReceive(g_xQueuePlatform, &idata, portMAX_DELAY); 
  • 1

在game1_task游戏中的代码片段

void game1_task(void *params)
{		
	
	uint8_t dev, data, last_data;
	struct input_data idata;
	g_framebuffer = LCD_GetFrameBuffer(&g_xres, &g_yres, &g_bpp);
	
	draw_init();
	draw_end();
	/* 创建队列 */
	g_xQueuePlatform = xQueueCreate(10, sizeof(struct input_data));
//	g_xQueueKey = xQueueCreate(10, sizeof(struct key_data));
	/* 创建一个按键任务,用于获取数据 */
//	xTaskCreate(KeyTask, "KeyTask", 128, NULL, osPriorityNormal, NULL);
    
	uptMove = UPT_MOVE_NONE;

	ball.x = g_xres / 2;
	ball.y = g_yres - 10;
	ball.velX = -0.5;
	ball.velY = -0.6;
//	ball.velX = -1;
//	ball.velY = -1.1;

	blocks = pvPortMalloc(BLOCK_COUNT);
  memset(blocks, 0, BLOCK_COUNT);
	
	lives = lives_origin = 3;
	score = 0;
	platformX = (g_xres / 2) - (PLATFORM_WIDTH / 2);
	
	// 创建一个挡球板任务
//	xTaskCreate(platform_task, "platform_task", 128, NULL, osPriorityNormal, NULL);

	game1_draw();
	LCD_Flush(); 
	while (1)
	{
				/* 读取红外遥控器 */
//		if (0 == IRReceiver_Read(&dev, &data))
		xQueueReceive(g_xQueuePlatform, &idata, portMAX_DELAY);
		data = idata.val;
		
		{
						if (data == 0x00)
						{
								data = last_data;
						}
						
						if (data == 0xe0) /* Left */
						{
								btnLeft();
						}

						if (data == 0x90)  /* Right */
						{
								btnRight();
						}
						last_data = data;
		}
			game1_draw();
			draw_end();
			vTaskDelay(50);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

实验结果

使用如上的代码在我硬件中进行测试,当我按下遥控器的左键时,挡球板跟着向左移动,当我按下遥控器的右键时,挡球板跟着向右进行移动,完成改造成使用队列读写demo。

在这里插入图片描述

本文中使用的工程

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/246361
推荐阅读
相关标签
  

闽ICP备14008679号