【FreeRTOS 消息队列】消息队列传递变量

2023-05-16

消息队列创建及运行,参阅安富莱电子demo

static QueueHandle_t xQueue1 = NULL;
static QueueHandle_t xQueue2 = NULL;


typedef struct Msg
{
	uint8_t  ucMessageID;
	uint16_t usData[2];
	uint32_t ulData[2];
}MSG_T;

MSG_T   g_tMsg; /* 定义一个结构体用于消息队列 */



static void vTaskTaskUserIF(void *pvParameters)
{
	MSG_T   *ptMsg;
	uint8_t ucCount = 0;
	uint8_t ucKeyCode;
	uint8_t pcWriteBuffer[500];
	
	/* 初始化结构体指针 */
	ptMsg = &g_tMsg;
	
	/* 初始化数组 */
	ptMsg->ucMessageID = 0;
	ptMsg->ulData[0] = 0;
	ptMsg->usData[0] = 0;

    while(1)
    {
		ucKeyCode = bsp_GetKey();
		
		if (ucKeyCode != KEY_NONE)
		{
			switch (ucKeyCode)
			{
				/* K1键按下 打印任务执行情况 */
				case KEY_DOWN_K1:			 
					printf("=================================================\r\n");
					printf("任务名      任务状态 优先级   剩余栈 任务序号\r\n");
					vTaskList((char *)&pcWriteBuffer);
					printf("%s\r\n", pcWriteBuffer);
				
					printf("\r\n任务名       运行计数         使用率\r\n");
					vTaskGetRunTimeStats((char *)&pcWriteBuffer);
					printf("%s\r\n", pcWriteBuffer);
					break;
				
				/* K2键按下,向xQueue1发送数据 */
				case KEY_DOWN_K2:
					ucCount++;
				
					/* 向消息队列发数据,如果消息队列满了,等待10个时钟节拍 */
					if( xQueueSend(xQueue1,
								   (void *) &ucCount,
								   (TickType_t)10) != pdPASS )
					{
						/* 发送失败,即使等待了10个时钟节拍 */
						printf("K2键按下,向xQueue1发送数据失败,即使等待了10个时钟节拍\r\n");
					}
					else
					{
						/* 发送成功 */
						printf("K2键按下,向xQueue1发送数据成功\r\n");						
					}
					break;
				
				/* K3键按下,向xQueue2发送数据 */
				case KEY_DOWN_K3:
					ptMsg->ucMessageID++;
					ptMsg->ulData[0]++;;
					ptMsg->usData[0]++;
					
					/* 使用消息队列实现指针变量的传递 */
					if(xQueueSend(xQueue2,                  /* 消息队列句柄 */
								 (void *) &ptMsg,           /* 发送结构体指针变量ptMsg的地址 */
								 (TickType_t)10) != pdPASS )
					{
						/* 发送失败,即使等待了10个时钟节拍 */
						printf("K3键按下,向xQueue2发送数据失败,即使等待了10个时钟节拍\r\n");
					}
					else
					{
						/* 发送成功 */
						printf("K3键按下,向xQueue2发送数据成功\r\n");						
					}
				
				/* 其他的键值不处理 */
				default:                     
					break;
			}
		}
		
		vTaskDelay(20);
	}
}

static void vTaskLED(void *pvParameters)
{
	MSG_T *ptMsg;
	BaseType_t xResult;
	const TickType_t xMaxBlockTime = pdMS_TO_TICKS(200); /* 设置最大等待时间为200ms */
	
    while(1)
    {
		xResult = xQueueReceive(xQueue2,                   /* 消息队列句柄 */
		                        (void *)&ptMsg,  		   /* 这里获取的是结构体的地址 */
		                        (TickType_t)xMaxBlockTime);/* 设置阻塞时间 */
		
		
		if(xResult == pdPASS)
		{
			/* 成功接收,并通过串口将数据打印出来 */
			printf("接收到消息队列数据ptMsg->ucMessageID = %d\r\n", ptMsg->ucMessageID);
			printf("接收到消息队列数据ptMsg->ulData[0] = %d\r\n", ptMsg->ulData[0]);
			printf("接收到消息队列数据ptMsg->usData[0] = %d\r\n", ptMsg->usData[0]);
		}
		else
		{
			/* 超时 */
		}
    }
}

static void vTaskMsgPro(void *pvParameters)
{
	BaseType_t xResult;
	const TickType_t xMaxBlockTime = pdMS_TO_TICKS(300); /* 设置最大等待时间为300ms */
	uint8_t ucQueueMsgValue;
	
    while(1)
    {
		xResult = xQueueReceive(xQueue1,                   /* 消息队列句柄 */
		                        (void *)&ucQueueMsgValue,  /* 存储接收到的数据到变量ucQueueMsgValue中 */
		                        (TickType_t)xMaxBlockTime);/* 设置阻塞时间 */
		
		if(xResult == pdPASS)
		{
			/* 成功接收,并通过串口将数据打印出来 */
			printf("接收到消息队列数据ucQueueMsgValue = %d\r\n", ucQueueMsgValue);
		}
		else
		{
			/* 超时 */
		}
    }
}

int main(void)
{
	/* 
	  在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
	  这样做的好处是:
	  1. 防止执行的中断服务程序中有FreeRTOS的API函数。
	  2. 保证系统正常启动,不受别的中断影响。
	  3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
	  在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
	  和cpsie i是等效的。
     */
	__set_PRIMASK(1);  
	
	/* 创建任务 ,具体创建任务参阅上一篇【FreeRTOS 任务】任务创建及运行 */
	AppTaskCreate();

	/* 创建任务通信机制 */
		/* 创建10个uint8_t型消息队列 */
	xQueue1 = xQueueCreate(10, sizeof(uint8_t));
    if( xQueue1 == 0 )
    {
        /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
    }
	/* 创建10个存储指针变量的消息队列,由于CM3/CM4内核是32位机,一个指针变量占用4个字节 */
	xQueue2 = xQueueCreate(10, sizeof(struct Msg *));
    if( xQueue2 == 0 )
    {
        /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
    }
	
    /* 启动调度,开始执行任务 */
    vTaskStartScheduler();

	/* 
	  如果系统正常启动是不会运行到这里的,运行到这里极有可能是用于定时器任务或者空闲任务的
	  heap空间不足造成创建失败,此要加大FreeRTOSConfig.h文件中定义的heap大小:
	  #define configTOTAL_HEAP_SIZE	      ( ( size_t ) ( 17 * 1024 ) )
	*/
	while(1);
}


/* 如果程序使用到了硬件中断请使用以下方式 */
static void TIM1_IRQHandler(void)
{
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	g_uiCount++;
	/* 向消息队列发数据 */
	xQueueSendFromISR(xQueue1,
					  (void *)&g_uiCount,
					  &xHigherPriorityTaskWoken);
	/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

static void TIM2_IRQHandler(void)
{
	MSG_T *ptMsg;
	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	/* 初始化结构体指针 */
	ptMsg = &g_tMsg;
	/* 初始化数组 */
	ptMsg->ucMessageID++;
	ptMsg->ulData[0]++;
	ptMsg->usData[0]++;
	/* 向消息队列发数据 */
	xQueueSendFromISR(xQueue2,
					 (void *)&ptMsg,
					 &xHigherPriorityTaskWoken);
	/* 如果 xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

STM32CubeMX 队列创建及运行
以下是普通变量队列创建和运行

注意: STM32CubeMX 生成的代码消息队列目前只能传递普通变量,如果传递结构体或者其它类型变量,最好不使用 cmsis_os.h封装好的API


/* USER CODE BEGIN 4 */

void MessageQTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  osEvent EventMessage;
  for(;;)
  {
		EventMessage = osMessageGet (myMessageQueueIdHandle, 10);
		if(EventMessage.status == osEventMessage)
		{
			printf("MessageGet v : %d\r\n", EventMessage.value.v);
		}else{
			printf("MessageGet v null\r\n");
		}
		osDelay(1000);	
  }
  /* USER CODE END 5 */
}


void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
	int32_t count = 0;
	uint8_t bits  = 1;
  for(;;)
  {
		//HAL_UART_Transmit(&huart1,"StartDefaultTask\r\n",strlen("StartDefaultTask\r\n"),1000);	
		count++;
		if(count == 1)
		{
				count = 0;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
				bits = bits + 1;
				osMessagePut (myMessageQueueIdHandle, bits, 10);
		}
	  osDelay(10);	
	  osThreadSuspend(defaultTaskHandle);	//挂起任务
  }
  /* USER CODE END 5 */
}
int main(void)
{
  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
	
  /* 参数说明:队列结构体名称, 队列深度, 队列类型 */
  osMessageQDef(myMessageQueueName, 10, uint8_t);
  /* 参数说明:取定义好的队列结构体地址, 默认NULL */
  myMessageQueueIdHandle = osMessageCreate (osMessageQ(myMessageQueueName), NULL)
  /* USER CODE END RTOS_QUEUES */
  
  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
	
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
	
  osThreadDef(MessageQTask, MessageQTask, osPriorityHigh, 0, 128);
  SignalTaskHandle = osThreadCreate(osThread(MessageQTask), NULL);
  /* USER CODE END RTOS_THREADS */
  
  /* Start scheduler */
  osKernelStart();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【FreeRTOS 消息队列】消息队列传递变量 的相关文章

  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • freeRTOS使用uxTaskGetStackHighWaterMark函数查看任务堆栈空间的使用情况

    摘要 每个任务都有自己的堆栈 堆栈的总大小在创建任务的时候就确定了 此函数用于检查任务从创建好到现在的历史剩余最小值 这个值越小说明任务堆栈溢出的可能性就越大 FreeRTOS 把这个历史剩余最小值叫做 高水位线 此函数相对来说会多耗费一点
  • FreeRTOS_中断

    传送门 博客汇总帖 传送门 Cortex M3 中断 异常 传送门 Cortex M3笔记 基础 笔记内容参考 正点原子的FreeRTOS开发手册 cortex m3权威指南 Cortex M3和Cortex M4权威指南等 文中stm32
  • 使用RabbitMQ实现延时队列

    之前公司是一个类电商公司 会有用户下单后未支付取消订单的场景 解决方案是使用RabbitMQ的死信队列来实现一个延时队列 下单时 将订单丢进消息队列 设置过期时间 订单失效时间 然后到时候检查订单状态 如果未支付则取消订单 1 什么是死信
  • 将mysql中的数据移到另一个数据库中

    1 导出整个数据库 mysqldump u 用户名 p 数据库名 gt 导出的文件名 mysqldump u admin p vmiplatform gt sql sql 运行结果如下 2 导出一个表 mysqldump u 用户名 p 数
  • FreeRTOS笔记(一)简介

    这个笔记主要依据韦东山freertos快速入门系列记录 感谢韦东山老师的总结 什么是实时操作系统 操作系统是一个控制程序 负责协调分配计算资源和内存资源给不同的应用程序使用 并防止系统出现故障 操作系统通过一个调度算法和内存管理算法尽可能把
  • 基于STM32的FreeRTOS学习之中断测试实验(五)

    记录一下 方便以后翻阅 本章内容是接着上一章节进行的实际演练 1 实验目的 FreeRTOS可以屏蔽优先级低于configMAX SYSCALL INTERRUPT PRIORITY的中断 不会屏蔽高于其的中断 本次实验就是验证这个说法 本
  • RocketMQ 简介

    本文根据阿里云 RocketMQ产品文档整理 地址 https help aliyun com document detail 29532 html userCode qtldtin2 简介 RocketMQ是由阿里捐赠给Apache的一款
  • [FreeRTOS入门学习笔记]定时器

    定时器的使用步骤 1 定义一个handle xTimerCreate创建 2 启动定时器 在Task1中调用 通过队列通知守护任务来执行定时器任务 要再config头文件中定义守护任务相关配置 虽然定时器是在task1中启动 但是定时器的任
  • RT-Thread记录(五、RT-Thread 临界区保护与FreeRTOS的比较)

    本文聊聊临界区 以及RT Thread对临界区的处理 通过源码分析一下 RT Thread 对临界区保护的实现以及与 FreeRTOS 处理的不同 目录 前言 一 临界区 1 1 什么是临界区 1 2 RTOS中的临界区 二 RT Thre
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • 关于rocketmq 中日志文件路径的配置

    前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住分享一下给大家 点击跳转到网站 rocketmq 中的数据和日志文件默认都是存储在user home路径下面的 往往我们都需要修改这些路径到指定文件夹以便管理 服务端日志 网
  • kafka详解及集群环境搭建

    一 kafka详解 安装包下载地址 https download csdn net download weixin 45894220 87020758 1 1Kafka是什么 1 Kafka是一个开源消息系统 由Scala写成 是由Apac
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • RT-Thread记录(七、IPC机制之邮箱、消息队列)

    讲完了线程同步的机制 我们要开始线程通讯的学习 线程通讯中的邮箱消息队列也属于 RT Thread 的IPC机制 目录 前言 一 邮箱 1 1 邮箱控制块 1 2 邮箱操作 1 2 1 创建和删除 1 2 2 初始化和脱离 1 2 3 发送
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • 如何更改 FreeRTOS 中任务的最大可用堆大小?

    我通过以下方式在任务中创建元素列表 l dllist pvPortMalloc sizeof dllist dlllist 有 32 字节大 我的嵌入式系统有 60kB SRAM 所以我希望系统可以轻松处理我的 200 个元素列表 我发现在
  • 如何将 void* 转换为函数指针?

    我在 FreeRTOS 中使用 xTaskCreate 其第四个参数 void const 是传递给新线程调用的函数的参数 void connect to foo void const task params void on connect
  • FreeRTOS 匈牙利表示法 [重复]

    这个问题在这里已经有答案了 我是 RTOS 和 C 编程的新手 而且我仍在习惯 C 的良好实践 因此 我打开了一个使用 FreeRTOS 的项目 我注意到操作系统文件使用匈牙利表示法 我知道一点符号 但面临一些新的 标准 FreeRTOS
  • 有关 CMake 错误的问题:没有为目标提供源

    我正在尝试使用 cmake 和 eclipse 将 FreeRtos 添加到我的项目中 但出现错误 我运行的是 debian 10 我的 cmake 版本是 3 13 4 cmake 的文件可以在以下位置找到这个 git 仓库 https

随机推荐

  • 你对自己做的项目感兴趣吗

    一家公司 主要是开发OA的 xff0c 大家知道OA的简单含义是办公自动化系统 用途是利用信息化系统帮助企业或者政府单位办公协作 xff0c 目的是为了提高办公效率 xff0c 减少过去由于手工操作带来的 麻烦 xff0c 和提高工作的准确
  • Nginx反向代理解决跨域问题(个人学习总结)

    一 理解Nginx Nginx是一款轻量级的Web服务器 反向代理服务器及电子邮件 xff08 IMAP POP3 xff09 代理服务器 xff0c 在BSD like 协议下发行 其特点是占有内存少 xff0c 并发能力强 xff0c
  • C语言:文本加密

    文本加密 输入一个英文句子 xff0c 以 结束 将其中所有的大写英文字母 43 3 xff0c 小写英文字母 3 xff0c 非英文字母不变 xff0c 输出加密后的句子 提示 xff1a xff08 1 xff09 当读入的字符为 时
  • (三)决策树

    0 基本流程 每个结点对应一个属性测试 xff0c 结点包含的样本集合根据结果分到不同的子结点决策树算法流程 xff1a 总结 xff1a 每次选择其中一个特征对样本集进行分类 xff0c 对分类后的子集重复前步骤根据8中的划分方法 xff
  • Nuttx 字符设备驱动

    字符设备是非常普遍的一种设备 xff0c 这种设备在I O传输过程中只能以字符为单位进行传输 xff0c 如键盘 鼠标 以及一些传感器设备都是字符设备 Nuttx采用VFS xff0c 和linux一样的设计思路 xff0c 即 一切设备皆
  • 阿木实验室 ubuntu 20.04 Prometheus 系统 编译问题

    1 compile detection sh error make 2 CMakeFiles darknet ros lib dir build make 2017 xff1a CMakeFiles darknet ros lib dir
  • prometheus 无人机平台 gazeboORBSLAM3调试实现rgbd模式

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 目录 前言 一 镜像系统安装 二 prometheus镜像快速使用 1 prometheus px4 xff0c Prometheus编译
  • TX2上用D435i跑Vins-RGBD+Octomap生成八叉树地图

    1 realsense的SDK 和普通电脑不同 xff0c TX2是ARM xff0c 不能直接从官网下载编译 教程 xff1a https blog csdn net rosfreshman article details 1164040
  • PX4和Airsim通信操作流程

    坑真几把多 先在Windows上安装UE4和Airsim不再赘述 xff0c 官网都有 虚拟机或其他计算机安装好ubuntu并安装PX4 1 安装PX4的ROS相关包 xff08 mavros xff09 1 第一种 xff1a 进入官网安
  • mavros安装流程(超简单)

    只适用于Ubuntu18 04 在Ubuntu中新建一个空白文本 xff0c 命名为123 sh bin bash Bash script for setting up ROS Melodic with Gazebo 9 developme
  • mavros与PX4建立连接(仿真)

    安装好 mavros 之后 xff0c 进入 home melodic catkin ws src mavros mavros launch 将 px4 launch 文件中 34 fcu url 34 修改成如下 xff1a lt arg
  • Airsim和ROS直连(自带飞控)

    安装Airsim git clone https github com Microsoft AirSim git cd AirSim setup sh build sh 安装好了之后编译ROS包 cd AirSim ros catkin b
  • SD卡Ubuntu制作镜像

    查看挂载盘 xff1a df h 备份命令 xff1a sudo dd if 61 dev sdc gzip gt home shi raspberry gz 查看备份进度 xff08 5s xff09 xff1a sudo watch n
  • 无需命令行,用 VSCode 轻松提交 Git 代码

    前言 Git 作为版本控制工具 xff0c 通过在开发过程中记录代码的变化 xff0c 简化了开发者之间的代码协作 而对于许多开发者而言 xff0c 命令行提交 Git 代码却是一项让人感到困难的任务 然而 xff0c 现在你可以轻松地通过
  • 开挂的人生背后  不仅仅是热爱

    在大城市飘来飘去 xff0c 看似潇洒 xff0c 其实内心还是会感到彷徨不安 身边的同事 xff0c 朋友不是努力的考取各种证书就是在人群中游刃有余 对于从小就酷爱甜食的 80 后女生 Zoe 来说 xff0c 今年 5 月份的一个决定
  • 轻松掌握 CSS,实现 loading 加载中的多种形式

    前言 现如今网页越来越趋近于动画 xff0c 相信大家平时浏览网页或多或少都能看到一些动画效果 xff0c 今天我们来做一个有意思的动画效果 xff0c 纯 css 实现 loading 加载中 xff08 多种展现形式 xff09 xff
  • Ubuntu16.04在线安装RealSense SDK与使用

    Ubuntu16 04在线安装RealSense SDK与使用 2019年5月左右 xff0c 拿到了两个Intel RealSense设备 D425和D435i xff0c 感觉不错就拿过来研究研究 xff0c 刚开始真是一窍不通 xff
  • linux中用gcc编译源代码的四个步骤(转载)

    在Linux下进行C语言编程 xff0c 必然要采用GNU GCC来编译C源代码生成可执行程序 一 GCC快速入门 Gcc指令的一般格式为 xff1a Gcc 选项 要编译的文件 选项 目标文件 其中 xff0c 目标文件可缺省 xff0c
  • 随笔之ros多线程

    nt main int argc char argv ros init argc argv 34 convert to mono 34 ros NodeHandle nh ros Publisher image pub 61 nh adve
  • 【FreeRTOS 消息队列】消息队列传递变量

    消息队列创建及运行 xff0c 参阅安富莱电子demo span class token keyword static span QueueHandle t xQueue1 span class token operator 61 span