构建驱动模块6--STM32 缓冲队列
缓冲区常常用于临时保存数据,特别是在通讯过程中,先把数据接收下后,后期等待任务空闲在进行处理,这样避免接收数据中处理数据而造成数据丢失。缓冲队列里经常使用为环形缓冲队列,环形队列是一个头尾相接的队列,一般定义当入队操作为缓冲写操作,而出队则定义为缓冲读。当一个数据或者一组消息来到时,进行入队操作;当需要解析消息时才有出队操作。针对该思想编写一个最简单缓冲队列模块。其代码如下:
缓冲队列实现代码
typedef struct
{
MsgCell *msgCell;
ht_uint32_t wPos;
ht_uint32_t rPos;
ht_uint32_t Count;
}cmMsg_t;
/**********************************************************************************************************
*
* 函数名:cmMsgCreate
* 功 能:
* 参 数:
* 返回值:
* 版 本:
*
**********************************************************************************************************/
void* cmMsgCreate(ht_uint32_t wantSize)
{
cmMsg_t *prt=NULL;
prt=(cmMsg_t *)cmMalloc(sizeof(cmMsg_t)) ;
prt->msgCell=(MsgCell *)cmMalloc(sizeof(MsgCell)*wantSize) ;
prt->rPos=0;
prt->wPos=0;
prt->Count=wantSize;
return (void*)prt;
}
/**********************************************************************************************************
*
* 函数名:cmMsgWrite
* 功 能:
* 参 数:
* 返回值:
* 版 本:
*
**********************************************************************************************************/
ht_int32_t cmMsgWrite(void * handle,MsgCell msg)
{
ht_uint32_t iPos,i;
cmMsg_t *prt=(cmMsg_t*)handle;
iPos=(prt->wPos+1)%prt->Count;
if(( iPos!=prt->rPos)&&(msg.MsgLen<=256))//最大长度不超过256字节
{
prt->msgCell[prt->wPos].MsgLen=msg.MsgLen;
prt->msgCell[prt->wPos].prtMsg=(ht_uint8_t *)cmMalloc(msg.MsgLen) ;
for(i=0;i<prt->msgCell[prt->wPos].MsgLen;i++)
{
prt->msgCell[prt->wPos].prtMsg[i]=msg.prtMsg[i];
}
prt->wPos=iPos;
return 1;
}
else
{
return 0;
}
}
/**********************************************************************************************************
*
* 函数名:cmMsgRead
* 功 能:
* 参 数:
* 返回值:
* 版 本:
*
**********************************************************************************************************/
ht_int32_t cmMsgRead(void * handle,MsgCell *msg )
{
ht_uint32_t i;
cmMsg_t *prt=(cmMsg_t*)handle;
if( prt->wPos!=prt->rPos)
{
msg->MsgLen=prt->msgCell[prt->rPos].MsgLen;
for(i=0;i<prt->msgCell[prt->rPos].MsgLen;i++)
{
msg->prtMsg[i]=prt->msgCell[prt->rPos].prtMsg[i];
cmFree(prt->msgCell[prt->rPos].prtMsg);
}
prt->rPos=(prt->rPos+1)%prt->Count;
return 1;
}
return 0;
}
本程序设计了三个函数,分别是创建队列、写队列和读队列,创建队列通过动态分配内存,写队列分配写资源,读队列释放资源,一般最好是固定长度,如果内存足够的话最好不要通过动态分配;当然真正的环形队列,比这个要复杂的多,如空队列、满队判断,队列消息匹配等等操作并没在此实现。还有在进行数据copy时,最好不要通过以下方式赋值,这样效率并不高,最好应memcpy之类的系统函数,因为这些函数毕竟经过优化的。
for(i=0;i<prt->msgCell[prt->wPos].MsgLen;i++)
{
prt->msgCell[prt->wPos].prtMsg[i]=msg.prtMsg[i];
}