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);
  }

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

  • 21
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值