60、UART任意时间缓冲打印信息--解决写代码调试时中断中打印信息问题

/**********************************************************************
*file:UART任意时间缓冲打印信息–解决写代码调试时中断中打印信息问题
*author:残梦
*versions:V1.0
*date:2023.12.23
note:
方案:创建一个缓冲区,任意时间添加数据至缓冲区保存,空闲时自动发送数据;
此方案有个弊端,中断过快会导致丢失数据,两个中断优先级不同的任务都添加数据时会出现乱码,因为缓冲区只有一个。
使用方法:
1、修改缓冲区大小+内存分配方式
#define dSendBuffer_BufferSize (1024
5)//缓冲区大小
#define dMemoryType //定义–静态分配;屏蔽–动态分配
2、初始化缓冲区
int32_t SendBuffer_init(uint32_t size)
3、需要的发送数据添加至缓冲区
int32_t SendBuffer_add(uint8_t *pdata);
4、空闲处发送数据
void SendBuffer_IdleSend(void);
5、动态分配时,销毁资源(不再使用这个方案)
void SendBuffer_free(void);
**********************************************************************/
SendBuffer.h

#ifndef _SendBuffer_H_
#define _SendBuffer_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"

#define dSendBuffer_BufferSize (1024*5)//缓冲区大小:不得低于64字节;建议随发送数据的频率适当增加,避免掉数据
//#define dMemoryType //定义--静态分配;屏蔽--动态分配

int32_t SendBuffer_init(uint32_t size);
int32_t SendBuffer_add(uint8_t *pdata);
void SendBuffer_IdleSend(void);
void SendBuffer_free(void);

#ifdef __cplusplus
}
#endif
#endif

SendBuffer.c

/**********************************************************************
*file:UART任意时间缓冲打印信息--解决写代码调试时中断中打印信息问题
*author:残梦
*versions:V1.0
*date:2023.12.23
*note:
方案:创建一个缓冲区,任意时间添加数据至缓冲区保存,空闲时自动发送数据;
此方案有个弊端,中断过快会导致丢失数据,两个中断优先级不同的任务都添加数据时会出现乱码,因为缓冲区只有一个。
使用方法:
1、修改缓冲区大小+内存分配方式
    #define dSendBuffer_BufferSize (1024*5)//缓冲区大小
    #define dMemoryType //定义--静态分配;屏蔽--动态分配
2、初始化缓冲区
    int32_t SendBuffer_init(uint32_t size)
3、需要的发送数据添加至缓冲区
    int32_t SendBuffer_add(uint8_t *pdata);
4、空闲处发送数据
    void SendBuffer_IdleSend(void);
5、动态分配时,销毁资源(不再使用这个方案)
    void SendBuffer_free(void);
7、修改接口#define dUART_DMA_TX(pData,size)
**********************************************************************/
#include "SendBuffer.h"
#include "usart.h"

#define dSOURCE_LIST 6//资源列表种类个数
#define dUART_DMA_TX(pData,size) {\
                                    while(huart1.gState != HAL_UART_STATE_READY)HAL_Delay(1);\
                                    HAL_UART_Transmit_DMA(&huart1,pData,size);\
                                }

#define dMemoryConversion_Unit_String(x)    ((x < 1024)?"Bytes":((x < 1024*1024)?"KB":"MB"))
#define dMemoryConversion_Unit_Value(x)    ((x < 1024)?(float)x:((x < 1024*1024)?(x/1024.0f):(x/1024.0f/1024.0f)))

typedef struct 
{
    uint8_t *pbuf;
    uint32_t size;

    uint32_t pos_write;
    uint32_t pos_read;
}DataPacket_StructDef;
static DataPacket_StructDef DataPacket = {.pbuf = NULL,.size = 0,.pos_write = 0,.pos_read = 0};

#ifdef dMemoryType
static uint8_t xDataBuffer[dSendBuffer_BufferSize] = {0};
#endif

/****************************************
@function:发送缓冲初始化
@param:void
@return:-1--失败,0--成功
@note:
****************************************/
int32_t SendBuffer_init(uint32_t size)
{
    if(size < 64)return -1;
    printf("%s:Buffer:%.3f %s\n",__func__,dMemoryConversion_Unit_Value(size),dMemoryConversion_Unit_String(size));
    #ifdef dMemoryType
    DataPacket.pbuf = xDataBuffer;
    #else
    DataPacket.pbuf = (uint8_t *)malloc(size);
    #endif
    if(DataPacket.pbuf == NULL)
    {
        printf("%s:memory allocation failure\n",__func__);
        return -1;
    }

    memset(DataPacket.pbuf,0,size);
    DataPacket.size = size;
    DataPacket.pos_write = 0;
    DataPacket.pos_read = 0;
    return 0;
}

/****************************************
@function:添加数据至发送缓冲
@param:void
@return:-1--失败,0--成功
@note:
****************************************/
int32_t SendBuffer_add(uint8_t *pdata)
{
    uint32_t len = 0,w = 0,pos = 0;
    if((pdata == NULL) || (DataPacket.size == 0))return -1;
    len = strlen((char *)pdata);
    if(len == 0)return -1;

    w = 0;
    pos = DataPacket.pos_write;
    while(w < len)
    {
        DataPacket.pbuf[pos++] = pdata[w++];
        if(pos >= DataPacket.size)pos = 0;
    }
    DataPacket.pos_write = pos;
    return 0;
}

/****************************************
@function:空闲时发送缓冲区数据
@param:void
@return:void
@note:
****************************************/
void SendBuffer_IdleSend(void)
{
    uint32_t pos = 0;
    pos = DataPacket.pos_write;
    if(pos == DataPacket.pos_read)return;//缓冲区空
    if(pos > DataPacket.pos_read)
    {
        dUART_DMA_TX(&DataPacket.pbuf[DataPacket.pos_read],(pos - DataPacket.pos_read));
        DataPacket.pos_read = pos;
    }
    else
    {
        if(DataPacket.pos_read < (DataPacket.size - 1)) dUART_DMA_TX(&DataPacket.pbuf[DataPacket.pos_read],(DataPacket.size - DataPacket.pos_read));
        dUART_DMA_TX(&DataPacket.pbuf[0],pos);
        DataPacket.pos_read = pos;
    }
}

/****************************************
@function:发送缓冲释放销毁
@param:void
@return:void
@note:
****************************************/
void SendBuffer_free(void)
{
    #ifndef dMemoryType
    if(DataPacket.pbuf == NULL)return;
    DataPacket.size = 0;
    DataPacket.pos_write = 0;
    DataPacket.pos_read = 0;
    free(DataPacket.pbuf);
    #endif
}

使用宏的方式配合使用更佳:

#define dLOGG(str) {\
  sprintf((char *)Tx_Buffer_DMA,"%s\n%c",str,'\0');\
  SendBuffer_add(Tx_Buffer_DMA);\
}

#define dLOGG_FUN_LINE() {\
  sprintf((char *)Tx_Buffer_DMA,"%s--%d\n%c",__func__,__LINE__,'\0');\
  SendBuffer_add(Tx_Buffer_DMA);\
}

#define dLOGG_FUN_LINE_String(str) {\
  sprintf((char *)Tx_Buffer_DMA,"%s--%d:%s\n%c",__func__,__LINE__,str,'\0');\
  SendBuffer_add(Tx_Buffer_DMA);\
}

实现printf函数

int fputc(int ch,FILE *f)
{
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart1,temp,1,2);
	return(ch);
}

测试:

#define dSendBuffer_BufferSize (100)//缓冲区大小:不得低于64字节;建议随发送数据的频率适当增加,避免掉数据
//#define dMemoryType //定义--静态分配;屏蔽--动态分配
  if(SendBuffer_init(dSendBuffer_BufferSize) < 0)Error_Handler();
  uint32_t i = 0;
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    SendBuffer_add("012345678\n");
    SendBuffer_IdleSend();
    HAL_Delay(1);
    if(++i >= 10000)
    while(1);
  }

在这里插入图片描述
测试验证正常情况下没有丢数据现象,但是小心中断同时输入数据会数据错乱问题

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++设计模式 #3策略模式(Strategy Method)

动机 在软件构建过程中&#xff0c;某些对象使用的的算法可能多种多样&#xff0c;经常改变。如果将这些算法都写在类中&#xff0c;会使得类变得异常复杂&#xff1b;而且有时候支持不频繁使用的算法也是性能负担。 如何在运行时根据需求透明地更改对象的算法&#xff1f;将…

重生奇迹mu翅膀合成

在重生奇迹mu中&#xff0c;合成翅膀需要准备好翅膀碎片、宝石、羽毛、强化精华等材料&#xff0c;而其中不同翅膀合成要求的材料和数量略有不同。以下是一般合成翅膀的步骤&#xff1a; 1.首先&#xff0c;需要在背包中准备好所有的合成材料。如果缺少任何一种材料&#xff0…

Postman —— HTTP请求基础组成部分

一般来说&#xff0c;所有的HTTP Request都有最基础的4个部分组成&#xff1a;URL、 Method、 Headers和body。 &#xff08;1&#xff09;Method 要选择Request的Method是很简单的&#xff0c;Postman支持所有的请求方式。 &#xff08;2&#xff09;URL 要组装一条Request&…

【C++进阶02】多态

一、多态的概念及定义 1.1 多态的概念 多态简单来说就是多种形态 同一个行为&#xff0c;不同对象去完成时 会产生出不同的状态 多态分为静态多态和动态多态 静态多态指的是编译时 在程序编译期间确定了程序的行为 比如&#xff1a;函数重载 动态多态指的是运行时 在程序运行…

Java整合APNS推送消息-IOS-APP(基于.p12推送证书)

推送整体流程 1.在开发者中心申请对应的证书&#xff08;我用的是.p12文件&#xff09; 2.苹果手机用户注册到APNS&#xff0c;APNS将注册的token返回给APP&#xff08;服务端接收使用&#xff09;。 3.后台服务连接APNS&#xff0c;获取连接对象 4.后台服务构建消息载体 5.后台…

Windows漏洞利用开发——利用SEH绕过GS保护

实验6 Windows漏洞利用开发 6.1实验名称 Windows漏洞利用开发 6.2实验目的 学习windows漏洞利用开发&#xff0c;使用kali linux相关工具对windows内目标程序进行漏洞利用 6.3实验步骤及内容 第二阶段&#xff1a;利用SEH绕过GS保护 了解GS编译选项&#xff0c;SHE异常处…

最小二乘法简介

最小二乘法简介 1、背景描述2、最小二乘法2.1、最小二乘准则2.2、最小二乘法 3、最小二乘法与线性回归3.1、最小二乘法与线性回归3.2、最小二乘法与最大似然估计 4、正态分布&#xff08;高斯分布&#xff09; 1、背景描述 在工程应用中&#xff0c;我们通常会用一组观测数据去…

数据大模型与低代码开发:赋能技术创新的黄金组合

在当今技术领域&#xff0c;数据大模型和低代码开发已经成为两个重要的趋势。数据大模型借助庞大的数据集和强大的计算能力&#xff0c;助力我们从海量数据中挖掘出有价值的洞见和预测能力。与此同时&#xff0c;低代码开发通过简化开发流程和降低编码需求&#xff0c;使得更多…

Flink实时电商数仓(五)

FlinkSQL的join Regular join普通join&#xff0c;两条流的数据都时存放在内存的状态中&#xff0c;如果两条流数据都很大&#xff0c;对内存压力很大。Interval Join: 适合两条流到达时间有先后关系的&#xff1b;一条流的存活时间短&#xff0c;一条流的存活时间长。Lookup …

【机器学习】贝叶斯决策论

参考课程视频&#xff1a;https://www.icourse163.org/course/NEU-1462101162?tid1471214452 1 概述 1.1 相关概念与变量描述 1.2 贝叶斯定理 2 分类准则 2.1 最大后验概率分类准则 2.2 最小错误概率分类准则 ) 2.3 最小风险分类准则 2.4 栗子 —— 根据身高预测性别

基于AWD攻防对Web漏洞的研究

写在前面 Copyright © [2023] [Myon⁶]. All rights reserved. 基于awd攻防环境和xshell远程连接&#xff0c;配合kali linux渗透系统、蚁剑、D盾、河马、Seay代码审计系统等&#xff0c;演示现实中网站可能存在的漏洞&#xff0c;对网站进行漏洞扫描&#xff0c;渗透测…

网络爬虫之Ajax动态数据采集

动态数据采集 规则 有时候我们在用 requests 抓取页面的时候&#xff0c;得到的结果可能和在浏览器中看到的不一样&#xff0c;在浏览器中可以看到正常显示的页面教据&#xff0c;但是使用 requests 得到的结果并没有&#xff0c;这是因为requests 获取的都是原始的 HTML 文档…

nodejs+vue+ElementUi家政服务系统c90g5

项目中登录模块用到token家政服务平台有管理员&#xff0c;雇主&#xff0c;雇员三个角色。管理员功能有个人中心&#xff0c;雇主管理&#xff0c;雇员管理&#xff0c;资料认证管理&#xff0c;项目类型管理&#xff0c;服务项目管理&#xff0c;需求信息管理&#xff0c;服务…

探索微软Edge:使用方法和心得分享

学习目标&#xff1a; 了解微软Edge的基本功能和使用方法。掌握在微软Edge上进行浏览、搜索和书签管理的技巧。学习如何使用微软Edge进行隐私和安全管理。探索微软Edge的扩展和其他高级功能。 学习内容&#xff1a; 微软Edge的简介&#xff1a;了解微软Edge的起源、特点和与其…

NiNNet

目录 一、网络介绍 1、全连接层存在的问题 2、NiN的解决方案(NiN块) 3、NiN架构 4、总结 二、代码实现 1、定义NiN卷积块 2、NiN模型 3、训练模型 一、网络介绍 NiN&#xff08;Network in Network&#xff09;是一种用于图像识别任务的卷积神经网络模型。它由谷歌研究…

设计模式除盲

目录 1.设计模式概述1.1 软件设计模式的产生背景1.2.软件设计模式的概念1.3 学习设计模式的必要性1.4 设计模式分类 2.UML图2.1 类图概述2.2 类图的作用2.3 类图表示法2.3.1 类的表示方式2.3.2 类与类之间关系的表示方式2.3.2.1 关联关系2.3.2.2 聚合关系2.3.2.3 组合关系2.3.2…

驱动开发-1

一、驱动课程大纲 内核模块字符设备驱动中断 二、ARM裸机代码和驱动有什么区别&#xff1f; 1、共同点&#xff1a; 都能够操作硬件 2、不同点&#xff1a; 1&#xff09;裸机就是用C语言给对应的寄存器里面写值&#xff0c;驱动是按照一定的套路往寄存器里面写值 2&#xff09…

微服务之配置中心与服务跟踪

zookeeper 配置中心 实现的架构图如下所示&#xff0c;采取数据加载到内存方式解决高效获取的问题&#xff0c;借助 zookeeper 的节点监听机制来实现实时感知。 配置中心数据分类 事件调度&#xff08;kafka&#xff09; 消息服务和事件的统一调度&#xff0c;常用用 kafka …

vulnhub-Tre(cms渗透)

&#x1f42e;博主syst1m 带你 acquire knowledge&#xff01; ✨博客首页——syst1m的博客&#x1f498; &#x1f618;《CTF专栏》超级详细的解析&#xff0c;宝宝级教学让你从蹒跚学步到健步如飞&#x1f648; &#x1f60e;《大数据专栏》大数据从0到秃头&#x1f47d;&…

MATLAB画球和圆柱

1. 画球 修改了一下MATLAB的得到球的坐标的函数&#xff1a; GetSpherePoint function [xx,yy,zz] GetSpherePoint(xCenter,yCenter,zCenter,r,N) % 在[xCenter,yCenter,zCenter]为球心画一个半径为r的球,N表示球有N*N个面&#xff0c;N越大球的面越密集 if nargin < 4 …