今天稍微完善了一下环形队列,可以实现定长变长存储了。对于其他队尾数据的处理方法,日后按需完善。
后面打算看看这个函数在串口中的表现
此代码有更新版本,最新版本
#include "Queue.h"
#define ELEMENT_SIZE_STORAGE_ROOM 2
/**
* @brief 初始化环形队列
* @param pCirQueue:环形队列结构体
* @param paramBuff:环形队列缓冲数组
* @param paramQueueSize:环形队列大小,单位字节
* @param paramElementSize:定长存储元素大小,单位字节。如果此项为0,则为变长存储。最大255
* @note 环形队列模式如果为定长存储,环形队列大小必须是元素大小的整数倍
* @return 环形队列状态码
*/
CirQueueStatusTypeDef CirQueue_Init(CirQueueTypeDef *pCirQueue, uint8_t *paramBuff,uint32_t paramQueueSize, uint8_t paramElementSize)
{
/*满足环形队列模式如果为定长存储,环形队列大小必须是元素大小的整数倍*/
if(paramElementSize !=0 && paramQueueSize % paramElementSize !=0)
{
return CirQueue_ERROR;
}
pCirQueue ->ElementSize = paramElementSize;
pCirQueue ->pBuff = paramBuff;
pCirQueue ->Size = paramQueueSize;
pCirQueue ->First = 0;
pCirQueue ->Last = 0;
pCirQueue ->TotalElementsSize = 0;
return CirQueue_OK;
}
/**
* @brief 向环形队列添加元素,一次入队一个元素
* @param pCirQueue:环形队列结构体
* @param pElements:数据源数组
* @param paramElementSize:元素大小,单位字节,最大值65535。定长存储模式下此项无效
* @return 环形队列状态码
*/
CirQueueStatusTypeDef CirQueue_Add(CirQueueTypeDef *pCirQueue, uint8_t *pElement, uint16_t paramElementSize)
{
uint32_t FirstCopySize = 0, SecondCopySize = 0; //两次传输数据的大小
uint16_t FirstCopyEmementSize = 0, SecondCopyEmementSize = 0; //两次传输元素的大小
uint32_t EndFreeSize = pCirQueue ->Size - pCirQueue ->First; //队列末尾剩余空间
uint32_t TotalCopySize = 0;
uint16_t i = 0;
/*检查是否是定长存储*/
if(pCirQueue ->ElementSize)
{
paramElementSize = pCirQueue ->ElementSize;
FirstCopySize = paramElementSize;
}
else
{
FirstCopySize = paramElementSize + ELEMENT_SIZE_STORAGE_ROOM;
}
/*判断是否将要在末尾分割数据*/
if(EndFreeSize < FirstCopySize)
{
/*需要进行数据分割*/
FirstCopyEmementSize = EndFreeSize - ELEMENT_SIZE_STORAGE_ROOM;
SecondCopyEmementSize = paramElementSize - FirstCopyEmementSize;
FirstCopySize = EndFreeSize;
SecondCopySize = SecondCopyEmementSize + ELEMENT_SIZE_STORAGE_ROOM;
}
else
FirstCopyEmementSize = paramElementSize;
/*检查是否将越界*/
TotalCopySize = FirstCopySize + SecondCopySize;
if(pCirQueue ->TotalElementsSize + TotalCopySize > pCirQueue ->Size)
return CirQueue_ERROR;
/*复制数据*/
if(!pCirQueue ->ElementSize)
{
pCirQueue ->pBuff[pCirQueue ->First++] = (uint8_t)(FirstCopyEmementSize); //储存元素大小
pCirQueue ->pBuff[pCirQueue ->First++] = (uint8_t)(((FirstCopyEmementSize) & 0xF0) >> 8);
}
for(i = 0; i < FirstCopyEmementSize; ++i)
{
pCirQueue ->pBuff[pCirQueue ->First++] = *pElement++;
}
/*头地址到末尾回0*/
if(pCirQueue ->First >= pCirQueue ->Size)
{
pCirQueue ->First = 0;
}
/*处理末尾剩下的数据*/
if(SecondCopySize)
{
//储存元素大小
if(!pCirQueue ->ElementSize)
{
pCirQueue ->pBuff[pCirQueue ->First++] = (uint8_t)(SecondCopyEmementSize);
pCirQueue ->pBuff[pCirQueue ->First++] = (uint8_t)(((SecondCopyEmementSize) & 0xF0) >> 8);
}
for(i = 0; i < SecondCopyEmementSize; ++i)
{
pCirQueue ->pBuff[pCirQueue ->First++] = *pElement++;
}
}
/*更新环形队列现存元素大小*/
pCirQueue ->TotalElementsSize += TotalCopySize;
return CirQueue_OK;
}
/**
* @brief 环形队列出队,一次出队一个元素
* @param pCirQueue:环形队列结构体
* @param pElement:出队元素存放地址
* @return 环形队列状态码
*/
CirQueueStatusTypeDef CirQueue_Remove(CirQueueTypeDef *pCirQueue, uint8_t *pElement)
{
uint16_t RemoveElementSize = 0, RemoveElementSize_L = 0, RemoveElementSize_H = 0, i = 0; //元素大小,元素大小低高位,i
/*无数据时报错*/
if(!pCirQueue ->TotalElementsSize)
{
return CirQueue_ERROR;
}
/*计算元素大小*/
if(pCirQueue ->ElementSize)
{
RemoveElementSize = pCirQueue ->ElementSize; //定长存储的计算
}
else
{
RemoveElementSize_L = pCirQueue ->pBuff[pCirQueue ->Last++]; //计算元素大小低位
RemoveElementSize_H = pCirQueue ->pBuff[pCirQueue ->Last++] << 8; //计算元素大小高位
RemoveElementSize = RemoveElementSize_L + RemoveElementSize_H;
}
/*复制数据*/
for(i = 0; i < RemoveElementSize; ++i)
{
*pElement++ = pCirQueue ->pBuff[pCirQueue ->Last++];
}
/*尾地址到末尾回0*/
if(pCirQueue ->Last >= pCirQueue ->Size)
{
pCirQueue ->Last = 0;
}
/*更新环形队列现存元素大小*/
pCirQueue ->TotalElementsSize -= RemoveElementSize + ELEMENT_SIZE_STORAGE_ROOM;
return CirQueue_OK;
}