一个简单的接收缓存设计——C语言实现

#include "string.h"
#include "stdlib.h"
#include "stdio.h"
/************************/
#include "SYS_ENUM.h"
#include "LoopRecBuff.h"

/*******************************************************
MIT License

Copyright (c) 2018 w64228013

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*******************************************************/

//LoopBuff uartbuff = 
//{
//		NULL, //ucBuff address
//		MaxBuffLength,//usBuffLength
//		LimitedBuffHead,//usRecPos
//		LimitedBuffHead,//usReadPos
//		MaxReTryCount,//usRetryCount
//		0,//ucIsReadBusy
//};

unsigned char ucBuffArray[MaxBuffLength] = {0};

/**
  * @brief  内部使用,当重试次数超过MaxReTryCount后调用
  * @note   
  * @param  *t_AimLoopBuffPtr:缓存块结构体的指针;RecPos:接收的缓存位置
  * @retval None
*/
void Syn_Loop_Buff_Pos(LoopBuff *t_AimLoopBuffPtr,unsigned short RecPos)
{
	t_AimLoopBuffPtr->usReadPos = RecPos;
	t_AimLoopBuffPtr->usRetryCount = MaxReTryCount;
}
/**
  * @brief  未使用,重置读取位置和接收位置
  * @note   
  * @param  *t_AimLoopBuffPtr:缓存块结构体的指针;
  * @retval None
*/
void Reset_Loop_Buff(LoopBuff *t_AimLoopBuffPtr)
{
	/*前面需要增加响应的中断停止函数,防止Reset的瞬间触发中断*/
	
	t_AimLoopBuffPtr->usReadPos = t_AimLoopBuffPtr->usRecPos = 0;
}
/**
  * @brief  内部调用,确认缓存长度是否有效
  * @note   
  * @param  *t_AimLoopBuffPtr:缓存块结构体的指针;curLength:新增缓存的长度;AimLength:目标需要的长度;RecPos:接收的缓存位置,IsCheckAddtionalLength:是否需要检测超出的长度;
  * @retval RET_OK:长度正确;RET_ERR:长度错误
*/
__inline return_value Check_RetryCount_IsOver(LoopBuff *t_AimLoopBuffPtr,unsigned short curLength,unsigned short AimLength,unsigned short RecPos,unsigned char IsRetainAddtionalLength)
{
	/*如果新增长度 >= 目标长度 说明正常返回true*/
	if(curLength == AimLength)
		{
			t_AimLoopBuffPtr->usRetryCount = MaxReTryCount;
			return RET_OK;
		}
	else if(curLength > AimLength)
		{
			/*如果新增长度 > 目标长度 并且需要检测额外长度*/	
		 if(IsRetainAddtionalLength != NotCheckAddtionalLength)
			{
				/*执行同步并且返回StatusErr*/
				Syn_Loop_Buff_Pos(t_AimLoopBuffPtr,RecPos);
				return RET_ERR;
			}
			t_AimLoopBuffPtr->usRetryCount = MaxReTryCount;
			return RET_OK;
		}	
	else
	{
		/*如果重试次数到了则执行同步*/
		if( --t_AimLoopBuffPtr->usRetryCount == 0 )
		{
//			printf("%d\r\n",t_AimLoopBuffPtr->usRetryCount);
			Syn_Loop_Buff_Pos(t_AimLoopBuffPtr,RecPos);
		}
//		else {printf("%d\r\n",t_AimLoopBuffPtr->usRetryCount);}
		return RET_ERR;
	}
}
/**
  * @brief  外部调用,读取响应长度的
  * @note   
  * @param  *t_AimLoopBuffPtr:缓存块结构体的指针;*Buffdst:弹出数据的拷贝地址;AimLength:目标需要的长度,IsCheckAddtionalLength:是否需要检测超出的长度;
  * @retval *Buffdst:正确的话返回拷贝地址;NULL:错误的话返回空指针地址
*/	
unsigned char* Takeout_Buff(LoopBuff *t_AimLoopBuffPtr,unsigned char *Buffdst,unsigned short AimLength,BuffConsType IsCheckAddtionalLength)
{
	const unsigned short constRecPos = t_AimLoopBuffPtr->usRecPos;
	int offset = constRecPos - t_AimLoopBuffPtr->usReadPos; 
	unsigned short tempoffset = {0}; 
	/*没有新数据,或者AimLength为0*/
	if((offset == 0)||(AimLength==0))
		return NULL;
	/*offset>0,Pos正序,新增长度是 = offset*/
	else if(offset > 0)
	{	
		if(Check_RetryCount_IsOver(t_AimLoopBuffPtr,offset,AimLength,constRecPos,IsCheckAddtionalLength) != RET_OK)
			return NULL;
		/*Pos正序方式读取*/
		/*保存初始ReadPos*/		
		tempoffset = t_AimLoopBuffPtr->usReadPos;
		
		#if BuffMode == PreciseMode
			t_AimLoopBuffPtr->usReadPos += AimLength;
		#elif	BuffMode == RoughMode
			t_AimLoopBuffPtr->usReadPos = constRecPos;
		#endif /*BuffMode == RoughMode*/
		
		/*数据搬到dst地址所指的区域,并返回dst地址*/
		return memcpy(Buffdst,&t_AimLoopBuffPtr->ucBuff[tempoffset],AimLength);
	}
	/*offset<0,Pos倒序,新增长度 = offset+t_AimLoopBuffPtr->usBuffLength */
	else if(offset < 0)
	{		
		/*如果目标长度 > 新增长度,返回NULL,不对Buff做读取*/
		/*
			发生这种情况的原因有:
		  1,读取的瞬间数据片段还在发送,解决:等待或再多调用几次本函数,超过次数同步
		  2,读取的可能是被破坏的碎片数据,解决:超过次数同步
		*/
		/*先计算出当前 这里:offset 是负数 + 整个buff长度 = 实际新增buff长度*/
		/*返回 NULL 说明数据有问题 return NULL*/
		if (Check_RetryCount_IsOver(t_AimLoopBuffPtr,offset+t_AimLoopBuffPtr->usBuffLength,AimLength,constRecPos,IsCheckAddtionalLength) != RET_OK)
			return NULL;
		/*Pos倒序,先读取尾部剩余长度tempoffset*/
		tempoffset = t_AimLoopBuffPtr->usBuffLength - t_AimLoopBuffPtr->usReadPos;
		/*如果目标长度 <= 尾部剩余长度,则按照Pos正序方式读取*/
		if(AimLength <= tempoffset)
		{
			tempoffset = t_AimLoopBuffPtr->usReadPos;
			
			#if BuffMode == PreciseMode
				t_AimLoopBuffPtr->usReadPos += AimLength;
			#elif	BuffMode == RoughMode
				t_AimLoopBuffPtr->usReadPos = constRecPos;
			#endif /*BuffMode == RoughMode*/		
			
			return memcpy(Buffdst,&t_AimLoopBuffPtr->ucBuff[tempoffset],AimLength);
		}
		/*Pos倒序方式读取*/
		/*1:读取尾部剩余*/
		memcpy(Buffdst,&t_AimLoopBuffPtr->ucBuff[t_AimLoopBuffPtr->usReadPos],tempoffset);		
		/*2::读取头部 目标长度 - 尾部长度 */
		memcpy(Buffdst + tempoffset,&t_AimLoopBuffPtr->ucBuff[0],AimLength - tempoffset);
		
		#if BuffMode == PreciseMode
			t_AimLoopBuffPtr->usReadPos = AimLength - tempoffset;
		#elif	BuffMode == RoughMode
			t_AimLoopBuffPtr->usReadPos = constRecPos;
		#endif /*BuffMode == RoughMode*/
		
		/*数据搬到dst地址所指的区域,并返回dst地址*/
		return Buffdst;		
	}
	return NULL;
}
/**
  * @brief  外部调用,接收数据
  * @note   
  * @param  *t_AimLoopBuffPtr:缓存块结构体的指针;data:接收到的每一个字节
  * @retval 
*/
void Putin_Buff(LoopBuff *t_AimLoopBuffPtr,unsigned char data)
{	
	t_AimLoopBuffPtr->ucBuff[t_AimLoopBuffPtr->usRecPos++] = data;
	if( t_AimLoopBuffPtr->usRecPos >= t_AimLoopBuffPtr->usBuffLength )
	{
		t_AimLoopBuffPtr->usRecPos = LimitedBuffHead;
	}
}
/**
  * @brief  外部调用,初始化接收块
  * @note   
  * @param  *t_AimLoopBuffPtr:缓存块结构体的指针;*ucBuffArrayPtr:块的内存地址;usBuffLength:块的长度
  * @retval RET_OK:成功;RET_ERR:失败
*/
return_value Initializaion_Loop_Buff(LoopBuff *t_AimLoopBuffPtr,unsigned char *ucBuffArrayPtr,unsigned short usBuffLength)
{
	if((usBuffLength > MaxBuffLength)||(ucBuffArrayPtr == NULL))
		return RET_ERR;
	t_AimLoopBuffPtr->ucBuff = ucBuffArrayPtr;/*地址赋值*/
	t_AimLoopBuffPtr->usBuffLength = usBuffLength;/*长度赋值*/	
	t_AimLoopBuffPtr->usRecPos = LimitedBuffHead;
	t_AimLoopBuffPtr->usReadPos = LimitedBuffHead;
	t_AimLoopBuffPtr->usRetryCount = MaxReTryCount;
	t_AimLoopBuffPtr->ucIsReadBusy = 0;
	return RET_OK;	
}

/*receive example*/
//void USART1_IRQHandler(void)                	
//{
//	if(USART_GetITStatus(USART1,USART_IT_RXNE)== SET)
//	{
//		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
//		Putin_Buff(&uartbuff,USART_ReceiveData(USART1));
//	}
//}

/*read example*/
//void Read_Buff(void)
//{ 
//	unsigned char tempbuff[10];	
//	printf("the data is %02x",Takeout_Buff(&uartbuff,tempbuff,4));
//}
/*
*********************2018.1.23*****************************

LoopRecBuff,接收环形缓冲



****2018.1.23 V0.01****
Pos正序:表示RecPos>ReadPos 
Pos倒序:表示RecPos<ReadPos

模式区别:主要是完成读取后ReadPos的位置选择。

PreciseMode:ReadPos 按照 AimLength 长度偏移,常用于数据帧分段接收。
RoughMode:ReadPos 按照 RecPos 的位置偏移。此模式可能需要再修改,使得功能更加明确。

错误处理:
1,新增数据长度 小于 AimLength,每次Pop_Buff(),内部usRetryCount倒计数,返回NULL,
当usRetryCount计数结束,同步ReadPos和RecPos。

****2018.1.26 V0.02****
新增: enum BuffConsType;

修改:
	 Check_RetryCount_IsOver(),添加BuffConsType IsCheckAddtionalLength形参,内部相应改动,对额外长度也做检测
	 Pop_Buff(),添加BuffConsType IsCheckAddtionalLength形参,内部相应改动,调用时可以选择是否检测额外长度

	 函数名改变:functions' names have changed
	 Pop_Buff() 改为-> Takeout_Buff()
	 Push_Buff() 改为-> Putin_Buff()

****2018.2.2 V0.03****
删除:enum BuffStatus;

新增:
	"SYS_ENUM.h"文件,
	Initializaion_Loop_Buff(),实现接收块的初始化;

修改:
	启用unsigned short usBuffLength,	
	Putin_Buff(),中长度改变,
	unsigned char   ucBuff[MaxBuffLength] 改为-> unsigned char*  ucBuff;

********************Usage********************************

  
LoopBuff *t_loopBuffPtr = NULL;
unsigned char *ucbuffaddressPtr = NULL;
unsigned short usBuffLength = "you need the size of the buff";
t_loopBuffPtr 		  = malloc(sizeof(LoopBuff));
ucbuffaddressPtr	  = malloc(usBuffLength);


if(Initializaion_Loop_Buff(t_loopBuffPtr,ucbuffaddressPtr,usBuffLength) == RET_OK)
	return "you can use this buff";
else 
	return "the initialization is failing";


******************Usage_End******************************

*/ 
#ifndef __LOOPRECBUFF_h
#define __LOOPRECBUFF_h

#include "SYS_ENUM.h"

/*******************************************************
MIT License

Copyright (c) 2018 w64228013

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*******************************************************/


#define MaxBuffLength 							256
#define MaxTempBuffLength 						128
#define MaxReTryCount  							15+1
#define LimitedBuffTail  						(MaxBuffLength - 1)
#define LimitedBuffHead   						0	

#define PreciseMode  							0
#define RoughMode		 							1
#define BuffMode  	 							PreciseMode	 

#define HAS_MALLOC								0
/************************************************************************************/
typedef struct 
{
	//unsigned char   ucBuff[MaxBuffLength];
	unsigned char*  ucBuff;								/*缓存指针*/
	unsigned short  usBuffLength;						/*缓存区域长度*/
	unsigned short  usRecPos;							/*接收位置*/
	unsigned short  usReadPos;							/*读取位置*/
	unsigned short  usRetryCount;						/*数据块重试次数*/
	unsigned char   ucIsReadBusy;						/*缓存块是否读取繁忙,为可能的多线程预留字节*/
}LoopBuff;

/*
typedef enum 
{
	StatusErr = 0,
	StatusOk = 1,
	
}BuffStatus;
*/

typedef enum 
{
	CheckAddtionalLength = 0,
	NotCheckAddtionalLength = 1,
	
}BuffConsType;

/*if you dont use malloc or others ,you should extern first*/
extern unsigned char ucBuffArray[MaxBuffLength];

extern LoopBuff uartbuff;
extern unsigned char* Takeout_Buff(LoopBuff *AimLoopBuff,unsigned char *Buffdst,unsigned short AimLength,BuffConsType IsCheckAddtionalLength);
extern void Putin_Buff(LoopBuff *AimLoopBuff,unsigned char data);
extern return_value Initializaion_Loop_Buff(LoopBuff *t_AimLoopBuffPtr,unsigned char *ucBuffArrayPtr,unsigned short usBuffLength);

#endif

/*
*********************2018.1.31*****************************
	所有程序通用的枚举变量

****2018.1.31 V0.01****

	应用文件:LoopRecBuff,
			 DeviceManger,
*/




typedef enum return_enum
{
	RET_OK = 0,
	RET_ERR,
}return_value;
如果使用有问题或者不足的地方,望有高手能够指点留言,感谢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值