IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> freertos 队列集发送接收消息 -> 正文阅读

[嵌入式]freertos 队列集发送接收消息

最近看队列集,看到网上说队列集成员句柄里的消息要一次性全拿出来

我理解成是不是往队列集的同一个成员发送多次消息也只会触发一次事件呢?

还是说队列集和队列一样一次发送就触发一次事件?

动手测试一下

代码如下,两个出队列方法:

//test   消息队列集测试

	//方法1,是每次只从队列集获取一个消息
	printf("\r\n\r\n ********方法1,是每次只从队列集获取一个消息 ********\r\n\r\n" );
	Send_data = 1 ;
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
	Send_data = 2 ;
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
	Send_data = 3 ;
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);

	Send_data = 4 ;
	xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
	Send_data = 5 ;
	xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
	Send_data = 6 ;
	xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);


	while(1)
	{
		HAL_Delay(100);
			
		ActivatedQueue = xQueueSelectFromSet(T_QueueSet, 0);

		if(ActivatedQueue == T_queue1)
		{
			result = xQueueReceive(T_queue1, &Rev_data, 0);
			if( result == pdPASS ) 
			{
				 printf("\r\n方法1: T_queue1 Receive = %d \r\n", Rev_data ); 
			}
			else
			{ 
				printf("\r\n方法1: xQueueReceive T_queue1 fail !!!  result = %d \r\n",  result  ); 
			}
		}
		else if(ActivatedQueue == T_queue2)
		{
			result = xQueueReceive(T_queue2, &Rev_data, 0);
			if( result == pdPASS ) 
			{ 
				printf("\r\n方法1: T_queue2 Receive = %d \r\n", Rev_data ); 
			}
			else
			{ 
				printf("\r\n方法1: xQueueReceive T_queue2 fail !!!  result = %d \r\n",  result  ); 
			}
		}
		else { break; }
	}

//方法2,是每次从队列集获取到句柄之后,就把该消息队列句柄里的消息全拿出来
	printf("\r\n\r\n ********方法2,是每次从队列集获取到句柄之后,就把该消息队列句柄里的消息全拿出来 ********\r\n\r\n" );
	Send_data = 11 ;
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
	Send_data = 12 ;
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
	Send_data = 13 ;
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);

	Send_data = 14 ;
	xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
	Send_data = 15 ;
	xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
	Send_data = 16 ;
	xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
	while(1)
	{
		HAL_Delay(100);
			
		ActivatedQueue = xQueueSelectFromSet(T_QueueSet, 0);

		if(ActivatedQueue == T_queue1)
		{
			while( 1 )
			{
				result = xQueueReceive(T_queue1, &Rev_data, 0);
				if( result == pdPASS ) 
				{ 
					printf("\r\n方法2: T_queue1 Receive = %d \r\n", Rev_data ); 
				}
				else
				{ 
					printf("\r\n方法2: T_queue1 已全部出队列 !!!  result = %d \r\n",  result  );  
					break; 
				}
			}
			
		}
		else if(ActivatedQueue == T_queue2)
		{
			while( 1 )
			{
				result = xQueueReceive(T_queue2, &Rev_data, 0);
				if( result == pdPASS ) 
				{ 
					printf("\r\n方法2: T_queue2 Receive = %d \r\n", Rev_data ); 
				}
				else
				{ 
					printf("\r\n方法2: T_queue2 已全部出队列 !!!  result = %d \r\n",  result  );  
					break; 
				}
			}
		}
		else { break; }
	}

//test   消息队列集测试

最后log结果如下:

********方法1,是每次只从队列集获取一个消息 ********


方法1: T_queue1 Receive = 1 

方法1: T_queue1 Receive = 2 

方法1: T_queue1 Receive = 3 

方法1: T_queue2 Receive = 4 

方法1: T_queue2 Receive = 5 

方法1: T_queue2 Receive = 6 


 ********方法2,是每次从队列集获取到句柄之后,就把该消息队列句柄里的消息全拿出来 ********


方法2: T_queue1 Receive = 11 

方法2: T_queue1 Receive = 12 

方法2: T_queue1 Receive = 13 

方法2: T_queue1 已全部出队列 !!!  result = 0 

方法2: T_queue1 已全部出队列 !!!  result = 0 

方法2: T_queue1 已全部出队列 !!!  result = 0 

方法2: T_queue2 Receive = 14 

方法2: T_queue2 Receive = 15 

方法2: T_queue2 Receive = 16 

方法2: T_queue2 已全部出队列 !!!  result = 0 

方法2: T_queue2 已全部出队列 !!!  result = 0 

方法2: T_queue2 已全部出队列 !!!  result = 0 

事实证明队列集还是和队列集一样,每send一次就会产生一个事件.

实践出真知

测到这里,我又想到,freertos的消息队列实际是值得拷贝,

那我们往队列集发送一串数组会怎么样呢?

稍加修改上面的代码

static QueueHandle_t T_queue1 = NULL;
static QueueHandle_t T_queue2 = NULL;
static xQueueSetHandle T_QueueSet = NULL;

void Master_EventCreat(void)
{
	T_queue1 = xQueueCreate(3, sizeof(char)*100);
	if(T_queue1 == NULL){
		Error_Handler(__FILE__, __LINE__);
	}

	T_queue2 = xQueueCreate(3, sizeof(char)*100);
	if(T_queue2 == NULL){
		Error_Handler(__FILE__, __LINE__);
	}

	/* 创建多事件等待集合 */
	T_QueueSet = xQueueCreateSet( 6 );
	if( T_QueueSet == NULL ){
		Error_Handler(__FILE__, __LINE__);
	}

	/* 添加消息队列和信号量到Core_QueueSet, 添加时消息队列和信号量必须是空的 */
	xQueueAddToSet(T_queue1,		T_QueueSet);
	xQueueAddToSet(T_queue2,		T_QueueSet);
	
}



//方法1,是每次只从队列集获取一个消息
	printf("\r\n\r\n ********方法1,是每次只从队列集获取一个消息 ********\r\n\r\n" );

	snprintf( Send_data, 100, " I AM head1"); 
	snprintf( &Send_data[50], 50, " I AM test1"); 
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);

	snprintf( Send_data, 100, " I AM head2"); 	
	snprintf( &Send_data[50], 50, " I AM test2"); 
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);

	snprintf( Send_data, 100, " I AM head3"); 	
	snprintf( &Send_data[50], 50, " I AM test3"); 
	xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);

	while(1)
	{
		HAL_Delay(100);
			
		ActivatedQueue = xQueueSelectFromSet(T_QueueSet, 0);

		if(ActivatedQueue == T_queue1)
		{
			result = xQueueReceive(T_queue1, &Rev_data, 0);
			if( result == pdPASS ) 
			{
				 printf("\r\n方法1: T_queue1 Receive[0]  = %s \r\n", Rev_data ); 
				 printf("\r\n方法1: T_queue1 Receive[50] = %s \r\n\r\n", &Rev_data[50] ); 
			}
			else
			{ 
				printf("\r\n方法1: xQueueReceive T_queue1 fail !!!  result = %d \r\n",  result  ); 
			}
		}
		else { break; }
	}

最后log结果如下:

????????所以我想xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);是把 Send_data这个变量的的sizeof(char)*100个字节 (因为T_queue1 = xQueueCreate(3, sizeof(char)*100);) 拷贝到自己的消息区了.

? ? ? ? 那么,问题来了,假设我们xQueueSend 和xQueueReceive 的变量小于创建的内存大小,因为他是一直复制xQueueCreate时的大小,那么就会发生访问非法地址!!!

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-04 07:29:03  更:2022-05-04 07:29:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:45:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码