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

在这里插入图片描述

消息队列

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

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.rhkb.cn/news/11394.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

本地缓存~

前言 Caffeine是使用Java8对Guava缓存的重写版本&#xff0c;在Spring Boot 2.0中取而代之&#xff0c;基于LRU算法实现&#xff0c;支持多种缓存过期策略。 以下摘抄于https://github.com/ben-manes/caffeine/wiki/Benchmarks-zh-CN 基准测试通过使用Java microbenchmark ha…

Unity Shader Graph 2D - 角色身体电流覆盖效果

在游戏中,通常会有游戏角色受到“电击”的效果,此时游戏角色身体上会覆盖有电流,该效果能表明游戏角色的当前状态,让玩家能够获得更直观更好的体验。 那么如何实现呢 首先创建一个ShaderGraph文件,命名为Current,再创建对应的材质球M_Current。 基础的资源显示 老规矩,…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.9 广播陷阱:形状不匹配的深层隐患

2.9 广播陷阱&#xff1a;形状不匹配的深层隐患 目录 #mermaid-svg-F0AgBChfSCGzOqa7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-F0AgBChfSCGzOqa7 .error-icon{fill:#552222;}#mermaid-svg-F0AgBChfSCGzOqa7 …

解锁豆瓣高清海报(二) 使用 OpenCV 拼接和压缩

解锁豆瓣高清海报(二): 使用 OpenCV 拼接和压缩 脚本地址: 项目地址: Gazer PixelWeaver.py pixel_squeezer_cv2.py 前瞻 继上一篇“解锁豆瓣高清海报(一) 深度爬虫与requests进阶之路”成功爬取豆瓣电影海报之后&#xff0c;本文将介绍如何使用 OpenCV 对这些海报进行智…

vue入门到实战 二

目录 2.1 计算属性computed 2.1.1什么是计算属性 2.1.2 只有getter方法的计算属性 2.1.3 定义有getter和setter方法的计算属性 2.1.4 计算属性和methods的对比 2.2 监听器属性watch 2.2.1 watch属性的用法 2.2.2 computed属性和watch属性的对比 2.1 计算属性computed…

【DeepSeek】本地快速搭建DeepSeek

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 博客内容主要围绕&#xff1a; 5G/6G协议讲解 高级C语言讲解 Rust语言讲解 文章目录 本地快速搭建DeepSeek一、安装及配置ollama二、DeepSeek模型…

Spring WebFlux揭秘:下一代响应式编程框架,与Spring MVC有何不同?

Spring WebFlux和Spring MVC都是Spring家族里的成员&#xff0c;它们都能帮助我们开发Web应用&#xff0c;但工作方式有所不同。 可以把Spring MVC想象成一个服务员&#xff0c;每次有客人&#xff08;请求&#xff09;来&#xff0c;它就会专门找一个服务员&#xff08;线程&a…

基于微信小程序的实习记录系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

MySQL5.5升级到MySQL5.7

【卸载原来的MySQL】 cmd打开命令提示符窗口&#xff08;管理员身份&#xff09;net stop mysql&#xff08;先停止MySQL服务&#xff09; 3.卸载 切换到原来5.5版本的bin目录&#xff0c;输入mysqld remove卸载服务 测试mysql -V查看Mysql版本还是5.5 查看了环境变量里的…

TensorFlow 简单的二分类神经网络的训练和应用流程

展示了一个简单的二分类神经网络的训练和应用流程。主要步骤包括&#xff1a; 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与部署 加载和应用已训练的模型 1. 数据准备与预处理 在本例中&#xff0c;数据准备是通过两个 Numpy 数…

使用朴素贝叶斯对散点数据进行分类

本文将通过一个具体的例子&#xff0c;展示如何使用 Python 和 scikit-learn 库中的 GaussianNB 模型&#xff0c;对二维散点数据进行分类&#xff0c;并可视化分类结果。 1. 数据准备 假设我们有两个类别的二维散点数据&#xff0c;每个类别包含若干个点。我们将这些点分别存…

AI视频编码器(3.2) 《Swin Transformer V2: Scaling Up Capacity and Resolution》

arxiv链接自监督训练用到了SimMIM 论文链接。我觉得,SimMIM与MAE的区别在于,前者只是一个1-layer的prediction head,而后者是多层transformer结构的decoder。可参考Swin Transformer V2(CVPR 2022)论文与代码解读。总结 图中展示了三个创新,从左到右有三处红色结构,分别…

前端进阶:深度剖析预解析机制

一、预解析是什么&#xff1f; 在前端开发中&#xff0c;我们常常会遇到一些看似不符合常规逻辑的代码执行现象&#xff0c;比如为什么在变量声明之前访问它&#xff0c;得到的结果是undefined&#xff0c;而不是报错&#xff1f;为什么函数在声明之前就可以被调用&#xff1f…

Baklib赋能企业提升内容中台构建效率的全新路径解析

内容概要 在当今数字化转型的大潮中&#xff0c;企业面临着前所未有的挑战与机遇。为了顺应市场的发展趋势&#xff0c;提高运营能力&#xff0c;搭建高效的内容中台已成为企业迫在眉睫的任务。内容中台不仅仅是一个技术架构的集合&#xff0c;它更是企业实现数据共享、资源整…

计算机网络——流量控制

流量控制的基本方法是确保发送方不会以超过接收方处理能力的速度发送数据包。 通常的做法是接收方会向发送方提供某种反馈&#xff0c;如&#xff1a; &#xff08;1&#xff09;停止&等待 在任何时候只有一个数据包在传输&#xff0c;发送方发送一个数据包&#xff0c;…

游戏引擎 Unity - Unity 设置为简体中文、Unity 创建项目

Unity Unity 首次发布于 2005 年&#xff0c;属于 Unity Technologies Unity 使用的开发技术有&#xff1a;C# Unity 的适用平台&#xff1a;PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域&#xff1a;开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…

MySQL基础-多表查询

多表查询-多表关系 多表查询-概述 例如执行下行sql语句就会出现笛卡尔积&#xff1a; select *from emp,dept; --消除笛卡尔积 select * from emp,dept where emp.dept_id dept.id; 多表查询-查询分类 多表查询-连接查询-内连接 --内连接演示 --1.查询每一个员工的姓名,及关…

[权限提升] Wdinwos 提权 维持 — 系统错误配置提权 - Trusted Service Paths 提权

关注这个专栏的其他相关笔记&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01&#xff1a;Trusted Service Paths 提权原理 Windows 的服务通常都是以 System 权限运行的&#xff0c;所以系统在解析服务的可执行文件路径中的空格的时候也会以 System 权限进行解析&a…

【01】共识机制

BTF共识 拜占庭将军问题 拜占庭将军问题是一个共识问题 起源 Leslie Lamport在论文《The Byzantine Generals Problem》提出拜占庭将军问题。 核心描述 军中可能有叛徒&#xff0c;却要保证进攻一致&#xff0c;由此引申到计算领域&#xff0c;发展成了一种容错理论。随着…

本地部署DeepSeek教程(Mac版本)

第一步、下载 Ollama 官网地址&#xff1a;Ollama 点击 Download 下载 我这里是 macOS 环境 以 macOS 环境为主 下载完成后是一个压缩包&#xff0c;双击解压之后移到应用程序&#xff1a; 打开后会提示你到命令行中运行一下命令&#xff0c;附上截图&#xff1a; 若遇…