消息队列应用示例MessageQueues-STM32CubeMX-FreeRTOS《嵌入式系统设计》P343-P347

news2025/2/3 7:33:34

在这里插入图片描述

消息队列

使用信号量、事件标志组和线标志进行任务同步时,只能提供同步的时刻信息,无法在任务之间进行数据传输。要实现任务间的数据传输,一般使用两种方式:

1. 全局变量

在 RTOS 中使用全局变量时,必须保证每个任务对全局变量的互斥访问,一般借助互斥量来实现。另一个方法是在任务设计时,设计成只有一个任务修改这个全局变量,其他任务只是读取这个全局变量,而不修改它的值,并在全局变量前面加上 volatile 的关键字修饰,以避免编泽器的优化。

2. 消息队列

消息队列类似于一个数据缓冲区,可以保存有限个、具有确定大小的数据。通常情况下,消息队列按照 FI FO(先进先出)的模式使用,即数据由队尾写入,从队首读出。
任务向消息队列中放人消息时,需要判断消息队列是否有多余的空间:如果有空间,则放人一个新的消息;如果消息队列已经存满,该任务将进人到阻塞态,直到消息队列中有多余的空间。
任务从消息队列中获取消息时,需要判断消息队列是否有消息:如果消息队列中没有消息,该任务将进人到阻塞态。当消息队列中有新的消息时,处于阻塞态的任务将被唤醒并获得该消息。任务在获取消息时,需要提前定义存放消息的缓冲区,这个缓冲区的大小不能小于消息队列中单个消息的大小。
注意: FreeRTOS 利用消息队列进行消息传递时,放入消息队列的是实际的数据,而不是数据的地址。例如,串口一次接收 10 字节的数据,如果使用消息队列来传递串口接收的数据,则应该将消息队列的单个消息大小设置为 10 字节,以便一次性存放串口接收的10 字节数据。
消息队列和全局变量相比,解决了多任务访问共享资源的冲突问题,还提供了任务的同步和超时处理等机制,并且可以实现中断服务程序和任务之间的数据传递。例如,多个任务都要使用串口进行数据传输时,可以采用两种方法:一种方法是利用互斥量实现对串口的互斥访问;另一种方法是创建一个消息队列和一个负责串口数据收发的任务。任务 A 发送的数据放人消息队列,任务 B 发送的数据也放人消息队列,串口发送任务则按照 FIFO 的原则从消息队列中取出消息发送。
在实际应用时,由于消息队列采用数据复制的方式传输数据,而不是传输存放数据的地址。如果任务间传输的数据量较大时,使用消息队列的效率会比较低。这时,可以考虑使用全局变量来实现任务间的通信,只是要注意全局变量的互斥访问(利用互斥量实现)。

应用示例

利用消息队列传输串口接收的数据。串口采用中断方式接收 10 字节的数据,并放入消息队列。数据处理任务从消息队列中取出数据并发送到 PC 显示。消息队列设置为可以容纳 5 个消息,每个消息的大小为10 字节。
修改HAL库的时间基准
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

// main.h
/**
 * @file main.h
 * @brief 主程序头文件,包含系统所需的基本定义和声明
 */

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>			// 标准输入输出头文件,用于printf和fputc
#include "cmsis_os2.h"		// CMSIS RTOS2,支持FreeRTOS
#include "usart.h"			// USART头文件,包含串口相关函数
#define LENGTH 10			// 缓冲区长度
extern uint8_t RxBuf[LENGTH];	// 串口接收缓冲区,用于存储接收到的数据
extern uint8_t TxBuf[LENGTH];	// 串口发送缓冲区,用于存储待发送的数据
extern osMessageQueueId_t ComQueueHandle;	// RTOS消息队列句柄,用于任务间通信
/* USER CODE END Includes */
// main.c
/**
 * @file main.c
 * @brief 主程序源文件,包含系统初始化和中断回调函数
 */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**
 * @brief 重定向printf函数相关配置
 * @note 支持不同编译器(ARMCC、GNUC)下的printf功能实现
 */
/* suport printf function, usemicrolib is unnecessary */
#if (__ARMCC_VERSION > 6000000)
__asm (".global __use_no_semihosting\n\t");
void _sys_exit(int x)
{
  x = x;
}
/* __use_no_semihosting was requested, but _ttywrch was */
void _ttywrch(int ch)
{
  ch = ch;
}
FILE __stdout;
#else
#ifdef __CC_ARM
#pragma import(__use_no_semihosting)
struct __FILE
{
  int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
  x = x;
}
#endif
#endif
#if defined ( __GNUC__ ) && !defined (__clang__)
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif


/**
 * @brief  Retargets the C library printf function to the USART.
 * @param  None
 * @retval None
 */
PUTCHAR_PROTOTYPE
{	// 采用轮询方式发送1字节数据,使用阻塞方式,超时时间设置为无限等待
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
	return ch;
}

int fgetc(FILE *f)
{	// 采用轮询方式接收1字节数据,使用阻塞方式,超时时间设置为无限等待
	uint8_t ch;	
	HAL_UART_Receive( &huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY );
	return ch;
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
	printf("/**  FreeRTOS for task creat  **/\n");
	HAL_UART_Receive_IT(&huart1,RxBuf,LENGTH);		// 启动串口中断接收功能,接收长度为 LENGTH 的数据到 RxBuf 缓冲区
/* USER CODE END 2 */

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)	
{	// 串口接收完成中断回调函数,当串口接收到指定长度的数据后,会触发此回调函数
	if(huart->Instance==USART1)	// 检查触发中断的串口是否为 USART1
	{	// 将收到的数据放入消息队列 ComQueueHandle中
		osMessageQueuePut(ComQueueHandle, (void *)RxBuf,0,0);	
		HAL_UART_Receive_IT(&huart1,RxBuf,LENGTH);	// 重新开始串口中断接收,准备接收下一组数据
	}
}
/* USER CODE END 4 */

// app_freertos.c

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
uint8_t RxBuf[LENGTH];	// 串口接收缓冲区
uint8_t TxBuf[LENGTH];	// 串口发送缓冲区
/* USER CODE END Variables */

/* USER CODE BEGIN Header_StartProcessTask */
/**
* @brief Function implementing the ProcessTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartProcessTask */
void StartProcessTask(void *argument)
{
  /* USER CODE BEGIN StartProcessTask */
  /* Infinite loop */
  for(;;)
  {		// 从消息队列中获取数据,无限等待
		if(osMessageQueueGet(ComQueueHandle,(void *)TxBuf,NULL,osWaitForever)==osOK)
		{	// 通过UART1发送数据
			HAL_UART_Transmit(&huart1,(void *)&TxBuf,LENGTH,HAL_MAX_DELAY);
		}
  }
  /* USER CODE END StartProcessTask */
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2291153.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络攻防实战指北专栏讲解大纲与网络安全法

专栏 本专栏为网络攻防实战指北&#xff0c;大纲如下所示 进度&#xff1a;目前已更完准备篇、HTML基础 计划&#xff1a;所谓基础不牢&#xff0c;地动山摇。所以下一步将持续更新基础篇内容 讲解信息安全时&#xff0c;结合《中华人民共和国网络安全法》&#xff08;以下简…

Spark的基本概念

个人博客地址&#xff1a;Spark的基本概念 | 一张假钞的真实世界 编程接口 RDD&#xff1a;弹性分布式数据集&#xff08;Resilient Distributed Dataset &#xff09;。Spark2.0之前的编程接口。Spark2.0之后以不再推荐使用&#xff0c;而是被Dataset替代。Dataset&#xff…

效用曲线的三个实例

效用曲线的三个实例 文章目录 效用曲线的三个实例什么是效用曲线风险与回报&#xff1a;投资决策消费选择&#xff1a;价格与质量的平衡程序员绩效评估&#xff1a;准时与程序正确性 分析- 风险与回报&#xff1a;投资决策分析- 消费选择&#xff1a;价格与质量的平衡- 程序员绩…

neo4j-community-5.26.0 create new database

1.edit neo4j.conf 把 # The name of the default database initial.dbms.default_databasehonglouneo4j # 写上自己的数据库名称 和 # Name of the service #5.0 server.windows_service_nameneo4j #4.0 dbms.default_databaseneo4j #dbms.default_databaseneo4jwind serve…

pytorch实现门控循环单元 (GRU)

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 特性GRULSTM计算效率更快&#xff0c;参数更少相对较慢&#xff0c;参数更多结构复杂度只有两个门&#xff08;更新门和重置门&#xff09;三个门&#xff08;输入门、遗忘门、输出门&#xff09;处理长时依赖一般适…

有没有个性化的UML图例

绿萝小绿萝 (53****338) 2012-05-10 11:55:45 各位大虾&#xff0c;有没有个性化的UML图例 绿萝小绿萝 (53****338) 2012-05-10 11:56:03 例如部署图或时序图的图例 潘加宇 (35***47) 2012-05-10 12:24:31 "个性化"指的是&#xff1f; 你的意思使用你自己的图标&…

Vue3.0实战:大数据平台可视化

文章目录 创建vue3.0项目项目初始化项目分辨率响应式设置项目顶部信息条创建页面主体创建全局引入echarts和axios后台接口创建express销售总量图实现完整项目下载项目任何问题都可在评论区,或者直接私信即可。 创建vue3.0项目 创建项目: vue create vueecharts选择第三项:…

洛谷 P1130 红牌 C语言

题目描述 某地临时居民想获得长期居住权就必须申请拿到红牌。获得红牌的过程是相当复杂&#xff0c;一共包括 N 个步骤。每一步骤都由政府的某个工作人员负责检查你所提交的材料是否符合条件。为了加快进程&#xff0c;每一步政府都派了 M 个工作人员来检查材料。不幸的是&…

语音识别播报人工智能分类垃圾桶(论文+源码)

2.1 需求分析 本次语音识别播报人工智能分类垃圾桶&#xff0c;设计功能要求如下∶ 1、具有四种垃圾桶&#xff0c;分别为用来回收厨余垃圾&#xff0c;有害垃圾&#xff0c;可回收垃圾&#xff0c;其他垃圾。 2、当用户语音说出“旧报纸”&#xff0c;“剩菜”等特定词语时…

MVC、MVP和MVVM模式

MVC模式中&#xff0c;视图和模型之间直接交互&#xff0c;而MVP模式下&#xff0c;视图与模型通过Presenter进行通信&#xff0c;MVVM则采用双向绑定&#xff0c;减少手动同步视图和模型的工作。每种模式都有其优缺点&#xff0c;适合不同规模和类型的项目。 ### MVVM 与 MVP…

shiro学习五:使用springboot整合shiro。在前面学习四的基础上,增加shiro的缓存机制,源码讲解:认证缓存、授权缓存。

文章目录 前言1. 直接上代码最后在讲解1.1 新增的pom依赖1.2 RedisCache.java1.3 RedisCacheManager.java1.4 jwt的三个类1.5 ShiroConfig.java新增Bean 2. 源码讲解。2.1 shiro 缓存的代码流程。2.2 缓存流程2.2.1 认证和授权简述2.2.2 AuthenticatingRealm.getAuthentication…

属性编程与权限编程

问题 如何获取文件的大小&#xff0c;时间戳以及类型等信息&#xff1f; 再论 inode 文件的物理载体是硬盘&#xff0c;硬盘的最小存储单元是扇区 (每个扇区 512 字节) 文件系统以 块 为单位(每个块 8 个扇区) 管理文件数据 文件元信息 (创建者、创建日期、文件大小&#x…

用 HTML、CSS 和 JavaScript 实现抽奖转盘效果

顺序抽奖 前言 这段代码实现了一个简单的抽奖转盘效果。页面上有一个九宫格布局的抽奖区域&#xff0c;周围八个格子分别放置了不同的奖品名称&#xff0c;中间是一个 “开始抽奖” 的按钮。点击按钮后&#xff0c;抽奖区域的格子会快速滚动&#xff0c;颜色不断变化&#xf…

R语言绘制有向无环图(DAG)

有向无环图&#xff08;Directed Acyclic Graph&#xff0c;简称DAG&#xff09;是一种特殊的有向图&#xff0c;它由一系列顶点和有方向的边组成&#xff0c;其中不存在任何环路。这意味着从任一顶点出发&#xff0c;沿着箭头方向移动&#xff0c;你永远无法回到起始点。 从流…

Spring Web MVC基础第一篇

目录 1.什么是Spring Web MVC&#xff1f; 2.创建Spring Web MVC项目 3.注解使用 3.1RequestMapping&#xff08;路由映射&#xff09; 3.2一般参数传递 3.3RequestParam&#xff08;参数重命名&#xff09; 3.4RequestBody&#xff08;传递JSON数据&#xff09; 3.5Pa…

129.求根节点到叶节点数字之和(遍历思想)

Problem: 129.求根节点到叶节点数字之和 文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(利用二叉树的先序遍历) 直接利用二叉树的先序遍历&#xff0c;将遍历过程中的节点值先利用字符串拼接起来遇到根节点时再转为数字并累加起来&#xff0c;在归的过程中&#xf…

unity中的动画混合树

为什么需要动画混合树&#xff0c;动画混合树有什么作用&#xff1f; 在Unity中&#xff0c;动画混合树&#xff08;Animation Blend Tree&#xff09;是一种用于管理和混合多个动画状态的工具&#xff0c;包括1D和2D两种类型&#xff0c;以下是其作用及使用必要性的介绍&…

MySQL存储过程和存储函数_mysql 存储过 call proc_stat_data(3,null)

2&#xff09;很难调试存储过程。只有少数数据库管理系统允许调试存储过程。不幸的是&#xff0c;MySQL不提供调试存储过程的功能。 1.2 数据准备 创建数据库&#xff1a; DEFAULT CHARACTER SET utf8; use test;这里记得设置编码&#xff01; 创建测试表&#xff1a; DROP…

Flink2支持提交StreamGraph到Flink集群

最近研究Flink源码的时候&#xff0c;发现Flink已经支持提交StreamGraph到集群了&#xff0c;替换掉了原来的提交JobGraph。 新增ExecutionPlan接口&#xff0c;将JobGraph和StreamGraph作为实现。 Flink集群Dispatcher也进行了修改&#xff0c;从JobGraph改成了接口Executio…

Vue 入门到实战 七

第7章 渲染函数 目录 7.1 DOM树 7.2 什么是渲染函数 7.3 h()函数 7.3.1 基本参数 7.3.2 约束 7.3.3 使用JavaScript代替模板功能 7.1 DOM树 7.2 什么是渲染函数 在多数情况下&#xff0c;Vue推荐使用模板template来创建HTML。然而在一些应用场景中&#xff0c;需要使用J…