DEEPSEEK帮写的STM32消息流函数,直接可用.已经测试

news2025/12/14 16:01:12
#include "main.h"
#include "MessageBuffer.h"


static RingBuffer msgQueue = {0};

// 初始化队列
void InitQueue(void) {
    msgQueue.head = 0;
    msgQueue.tail = 0;
    msgQueue.count = 0;
}

// 检查队列状态
type_usart_queue_status GetQueueStatus(void) {
    if (msgQueue.count == 0) {
        return USART_QUEUE_EMPTY;
    } else if (msgQueue.count >= (QUEUE_SIZE - MAX_MSG_LEN - sizeof(uint16_t))) {
        return USART_QUEUE_FULL;
    }
    return USART_QUEUE_OK;
}

// 中断安全的推送消息到队列
type_usart_queue_status PushMsgData(type_Msg *pMsg) {
    uint32_t primask;
    type_usart_queue_status result = USART_QUEUE_ERR;
    
    if (pMsg == NULL || pMsg->Length == 0 || pMsg->pData == NULL) {
        return USART_QUEUE_ERR;
    }

    // 检查消息长度是否有效
    if (pMsg->Length > MAX_MSG_LEN) {
        return USART_QUEUE_ERR;
    }

    // 进入临界区(关闭中断)
    primask = __get_PRIMASK();
    __disable_irq();

    // 检查是否有足够空间
    if ((QUEUE_SIZE - msgQueue.count) >= (pMsg->Length + sizeof(uint16_t))) {
        // 写入消息长度(小端格式)
        msgQueue.buffer[msgQueue.head] = (uint8_t)(pMsg->Length & 0xFF);
        msgQueue.head = (msgQueue.head + 1) % QUEUE_SIZE;
        msgQueue.buffer[msgQueue.head] = (uint8_t)((pMsg->Length >> 8) & 0xFF);
        msgQueue.head = (msgQueue.head + 1) % QUEUE_SIZE;

        // 写入消息数据
        for (uint16_t i = 0; i < pMsg->Length; i++) {
            msgQueue.buffer[msgQueue.head] = pMsg->pData[i];
            msgQueue.head = (msgQueue.head + 1) % QUEUE_SIZE;
        }

        msgQueue.count += (pMsg->Length + sizeof(uint16_t));
        result = USART_QUEUE_OK;
    } else {
        result = USART_QUEUE_FULL;
    }

    // 退出临界区(恢复中断状态)
    __set_PRIMASK(primask);

    return result;
}

// 从队列弹出消息(主程序中使用)
type_usart_queue_status PopMsgData(type_Msg *pMsg) {
    uint32_t primask;
    type_usart_queue_status result = USART_QUEUE_ERR;
    
    if (pMsg == NULL || pMsg->pData == NULL) {
        return USART_QUEUE_ERR;
    }

    // 进入临界区(关闭中断)
    primask = __get_PRIMASK();
    __disable_irq();

    if (msgQueue.count == 0) {
        result = USART_QUEUE_EMPTY;
    } else {
        // 读取消息长度(小端格式)
        uint16_t msgLength = msgQueue.buffer[msgQueue.tail];
        msgQueue.tail = (msgQueue.tail + 1) % QUEUE_SIZE;
        msgLength |= (uint16_t)(msgQueue.buffer[msgQueue.tail] << 8);
        msgQueue.tail = (msgQueue.tail + 1) % QUEUE_SIZE;

        // 检查消息长度是否有效
        if (msgLength <= MAX_MSG_LEN) {
            // 读取消息数据
            for (uint16_t i = 0; i < msgLength; i++) {
                pMsg->pData[i] = msgQueue.buffer[msgQueue.tail];
                msgQueue.tail = (msgQueue.tail + 1) % QUEUE_SIZE;
            }

            pMsg->Length = msgLength;
            msgQueue.count -= (msgLength + sizeof(uint16_t));
            result = USART_QUEUE_OK;
        } else {
            // 无效长度,重置队列
            InitQueue();
            result = USART_QUEUE_ERR;
        }
    }

    // 退出临界区(恢复中断状态)
    __set_PRIMASK(primask);

    return result;
}
#ifndef __MESSAGEBUFFER_H__
#define __MESSAGEBUFFER_H__


#define QUEUE_SIZE  1024*3    // 环形队列缓冲区大小
#define MAX_MSG_LEN 1024       // 单条消息最大长度

typedef struct {
    uint16_t Length;
    uint8_t *pData;
} type_Msg;

typedef struct {
    uint8_t buffer[QUEUE_SIZE];
    volatile uint16_t head;     // 使用volatile确保中断和主程序都能正确访问
    volatile uint16_t tail;
    volatile uint16_t count;
} RingBuffer;


//typedef enum
//{
//	USART_QUEUE_EMPTY = 0,
//	USART_QUEUE_FULL = 1,
//	USART_QUEUE_OK = 2,
//    USART_QUEUE_ERR = 3,
//} type_usart_queue_status;


void MessageBufferInitFunc(void);
type_usart_queue_status PopMsgData(type_Msg *pMsg);
type_usart_queue_status PushMsgData(type_Msg *pMsg);


#endif

中断压入:

type_Msg RevMsg;    //接收消息                   

  RevMsg.Length = counter;
 RevMsg.pData  = RevBuff;
  PushMsgData(&RevMsg);

主程序取出:

if (PopMsgData(&RevMsg) == USART_QUEUE_OK)
    {
        SendFlag = 1;
        SendUartDataFunc(USART1, RevMsg.pData, RevMsg.Length);
    }

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

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

相关文章

建造者模式:优雅构建复杂对象

引言 在软件开发中&#xff0c;有时我们需要创建一个由多个部分组成的复杂对象&#xff0c;这些部分可能有不同的变体或配置。如果直接在一个构造函数中设置所有参数&#xff0c;代码会变得难以阅读和维护。当对象构建过程复杂&#xff0c;且需要多个步骤时&#xff0c;我们可…

现场总线结构在楼宇自控系统中的技术要求与实施要点分析

在建筑智能化程度不断提升的当下&#xff0c;楼宇自控系统承担着协调建筑内各类设备高效运行的重任。传统的集中式控制系统在面对复杂建筑环境时&#xff0c;逐渐暴露出布线繁琐、扩展性差、可靠性低等问题。而现场总线结构凭借其分散控制、通信高效等特性&#xff0c;成为楼宇…

学习路之PHP--easyswoole使用视图和模板

学习路之PHP--easyswoole使用视图和模板 一、安装依赖插件二、 实现渲染引擎三、注册渲染引擎四、测试调用写的模板五、优化六、最后补充 一、安装依赖插件 composer require easyswoole/template:1.1.* composer require topthink/think-template相关版本&#xff1a; "…

《云原生安全攻防》-- K8s网络策略:通过NetworkPolicy实现微隔离

默认情况下&#xff0c;K8s集群的网络是没有任何限制的&#xff0c;所有的Pod之间都可以相互访问。这就意味着&#xff0c;一旦攻击者入侵了某个Pod&#xff0c;就能够访问到集群中任意Pod&#xff0c;存在比较大的安全风险。 在本节课程中&#xff0c;我们将详细介绍如何通过N…

06 APP 自动化- H5 元素定位

文章目录 H5 元素定位1、APP 分类2、H5 元素3、H5 元素定位环境的搭建4、代码实现&#xff1a; H5 元素定位 1、APP 分类 1、Android 原生 APP2、混合 APP(Android 原生控件H5页面)3、纯 H5 App 2、H5 元素 H5 元素容器 WebViewWebView 控件实现展示网页 3、H5 元素定位环…

定时线程池失效问题引发的思考

最近在做的一个新功能&#xff0c;在结果探测的时候使用了定时线程池和普通线程池结合&#xff0c;定时线程池周期性创建子任务并往普通线程池提交任务。 问题&#xff1a; 在昨天测试老师发现&#xff0c;业务实际上已经成功了&#xff0c;但是页面还是一直显示进行中。 收到…

AXURE安装+汉化-Windows

安装网站&#xff1a;https://www.axure.com/release-history/rp9 Axure中文汉化包下载地址 链接:https://pan.baidu.com/s/1U62Azk8lkRPBqWAcrJMFew?pwd5418 提取码:5418 下载完成之后&#xff0c;crtlc lang文件夹 到下载的Axure路径下 双击点进这个目录里面。ctrlv把lan…

ArcGIS Pro字段计算器与计算几何不可用,显示灰色

“字段计算器”不可用 如果计算字段命令不可用&#xff0c;请考虑以下可能性&#xff1a; 由 ArcGIS 管理的字段无法手动编辑。因此&#xff0c;无法计算 ObjectID&#xff08;OID 或 FID&#xff09;字段或地理数据库要素类的 Shape_Length 和 Shape_Area 字段的字段值。表中…

mac电脑安装 nvm 报错如何解决

前言 已知&#xff1a;安装nvm成功&#xff1b;终端输入nvm -v 有版本返回 1. 启动全局配置环境变量失败 source ~/.zshrc~ 返回&#xff1a; source: no such file or directory: /Users/你的用户名/.zshrc~2 安装node失败 nvm install 16.13返回&#xff1a; mkdir: /U…

第11节 Node.js 模块系统

为了让Node.js的文件可以相互调用&#xff0c;Node.js提供了一个简单的模块系统。 模块是Node.js 应用程序的基本组成部分&#xff0c;文件和模块是一一对应的。换言之&#xff0c;一个 Node.js 文件就是一个模块&#xff0c;这个文件可能是JavaScript 代码、JSON 或者编译过的…

上海工作机会:Technical Writer Senior Technical Writer - 中微半导体设备

大名鼎鼎的中微半导体招聘文档工程师了&#xff0c;就是那家由中国半导体产业的领军人物尹志尧领导的、全员持股的公司。如果你还不了解他&#xff0c;赶快Deepseek一下“尹志尧”了解。 招聘职位&#xff1a;Technical Writer & Senior Technical Writer 公司名称&#…

Python微积分可视化:从导数到积分的交互式教学工具

Python微积分可视化:从导数到积分的交互式教学工具 一、引言 微积分是理解自然科学的基础,但抽象的导数、积分概念常让初学者感到困惑。本文基于Matplotlib开发一套微积分可视化工具,通过动态图像直观展示导数的几何意义、积分的近似计算及跨学科应用,帮助读者建立"数…

Juce实现Table自定义

Juce实现Table自定义 一.总体展示概及概述 在项目中Juce中TableList往往无法满足用户需求&#xff0c;头部和背景及背景颜色设置以及在Cell中添加自定义按钮&#xff0c;所以需要自己实现自定义TabelList&#xff0c;该示例是展示实现自定义TableList&#xff0c;实现自定义标…

【后端高阶面经:架构篇】51、搜索引擎架构与排序算法:面试关键知识点全解析

一、搜索引擎核心基石&#xff1a;倒排索引技术深度解析 &#xff08;一&#xff09;倒排索引的本质与构建流程 倒排索引&#xff08;Inverted Index&#xff09;是搜索引擎实现快速检索的核心数据结构&#xff0c;与传统数据库的正向索引&#xff08;文档→关键词&#xff0…

Windows应用-音视频捕获

下载“Windows应用-音视频捕获”项目 本应用可以同时捕获4个视频源和4个音频源&#xff0c;可以监视视频源图像&#xff0c;监听音频源&#xff1b;可以将视频源图像写入MP4文件&#xff0c;将音频源写入MP3或WAV文件&#xff1b;还可以录制系统播放的声音。本应用使用MFC对话框…

【OCCT+ImGUI系列】012-Geom2d_AxisPlacement

Geom2d_AxisPlacement 教学笔记 一、类概述 Geom2d_AxisPlacement 表示二维几何空间中的一个坐标轴&#xff08;轴系&#xff09;&#xff0c;由两部分组成&#xff1a; gp_Pnt2d&#xff1a;原点&#xff08;Location&#xff09;gp_Dir2d&#xff1a;单位方向向量&#xff…

【C++高并发内存池篇】性能卷王养成记:C++ 定长内存池,让内存分配快到飞起!

&#x1f4dd;本篇摘要 在本篇将介绍C定长内存池的概念及实现问题&#xff0c;引入内存池技术&#xff0c;通过实现一个简单的定长内存池部分&#xff0c;体会奥妙所在&#xff0c;进而为之后实现整体的内存池做铺垫&#xff01; &#x1f3e0;欢迎拜访&#x1f3e0;&#xff…

mac下通过anaconda安装Python

本次分享mac下通过anaconda安装Python、Jupyter Notebook、R。 anaconda安装 点击&#x1f449;https://www.anaconda.com/download&#xff0c; 点击Mac系统安装包&#xff0c; 选择Mac芯片&#xff1a;苹果芯片 or intel芯片&#xff0c; 选择苹果芯片图形界面安装&#x…

微软PowerBI考试 PL300-Power BI 入门

Power BI 入门 上篇更新了微软PowerBI考试 PL-300学习指南&#xff0c;今天分享PowerBI入门学习内容。 简介 Microsoft Power BI 是一个完整的报表解决方案&#xff0c;通过开发工具和联机平台提供数据准备、数据可视化、分发和管理。 Power BI 可以从使用单个数据源的简单…

逻辑回归知识点

一、逻辑回归概念 逻辑回归(Logistic Regression)是一种广泛应用于分类问题的统计方法&#xff0c;尤其适用于二分类问题。 注意: 尽管名称中有"回归"二字&#xff0c;但它实际上是一种分类算法。 解决二分类的问题。 API&#xff1a;sklearn.linear_model.Logis…