使用方法:
- 创建循环缓冲区create_cb
- 在获得数据的地方调用write_cb把数据写入缓冲区中
- 获得数据帧get_frame,获取符合数据协议帧头和帧尾的数据
/*
* cycle_buf_frame.h
*
* Created on: 2017年7月31日
* Author: C
*/
#ifndef MAIN_CYCLE_BUF_FRAME_H_
#define MAIN_CYCLE_BUF_FRAME_H_
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
#define CB_OK 0
#define CB_FULL 1
#define CB_MALLOC_FAIL 2
#define CB_DATA_ERR 3
#define CB_NO_VALID 4
#define CB_READ_NOENOUGH 5
#define CB_INVALID 6
#define CB_NO_FRAME 7
#define CB_LACK_SPACE 8
#define CB_READ_POS_ERR 9
#define CB_READ_ERR 10
#define MAX_CB_LEN 65534
/*定义数据头尾长度1个字节*/
#define PTL_HT_LENGTH 1
/*固定数据头,高字节在前*/
#define PTL_HEAD 'a'
/*固定数据尾,高字节在前*/
#define PTL_TAIL 'z'
typedef enum {
/*请求类型*/
REQUEST=0,
/*响应类型*/
RESPONESE=1,
/*无响应请求类型*/
NONE_RESPONESE=2,
}data_types;
typedef enum {
/*控灯命令*/
CMD_LED=0X0000,
}data_cmd;
typedef struct {
/*数据头,指向第一个数据所在的位置*/
u16 head;
/*数据类型:请求,响应,P2P。。。。*/
data_types types;
/*命令字*/
data_cmd cmd;
/*数据内容长度*/
u16 data_len;
/*数据内容*/
void *data;
/*CRC效验*/
u16 crc;
/*数据尾,指向下一个即将写入数据的位置*/
u16 tail;
}data_packge;
typedef struct {
/*数据头*/
u16 head;
/*数据尾*/
u16 tail;
/*数据长度*/
u16 len;
/*数据体长度即缓冲区长度*/
u16 blen;
/*数据体*/
u8* data;
}cycle_buffer;
u8 creat_cb(cycle_buffer* cb,u16 len);
u8 get_frame(cycle_buffer* cb,u8* data,u16* len);
u8 read_cb(cycle_buffer* cb,u16 pos,u8* data,u16 len);
u8 write_cb(cycle_buffer* cb,u8* wlen,u8* data,u16 len);
void cb_test(void);
#endif /* MAIN_CYCLE_BUF_FRAME_H_ */
/*
* cycle_buf_frame.c
*
* Created on: 2017年7月31日
* Author: C
*/
#include "cycle_buf_frame.h"
u8 creat_cb(cycle_buffer* cb,u16 len){
cb->data=malloc(len);
if(cb->data==NULL)
return CB_MALLOC_FAIL;
cb->head=0;
cb->head=0;
cb->tail=0;
cb->len=0;
cb->blen=len;
return CB_OK;
}
/****************************************************************************
//--函数名称:write_cb
//--函数功能:写数据到缓冲区
//--函数参数:cb 目标缓冲区
:wlen 已写入数数据长度
:data 将要写入的数据
:len 将要写入的数据长度
//--返回数据:返回写状态
****************************************************************************/
u8 write_cb(cycle_buffer* cb,u8* wlen,u8* data,u16 len){
u16 i;
/*写缓冲区*/
for(i=0;i<len;i++)
{
/*判断缓冲区的数据是否超出缓冲区长度*/
if(cb->len<=cb->blen)
{
cb->data[cb->tail]=data[i];
cb->len++;
cb->tail++;
/*判断是否已写到数据数组尾*/
if(cb->tail>=cb->blen)
{
cb->tail=0;
}
}
else
{
*wlen=i;
return CB_FULL;
}
}
*wlen=len;
return CB_OK;
}
/****************************************************************************
//--函数名称:read_cb
//--函数功能:从缓冲区中读取数据
//--函数参数:cb 目标缓冲区
:pos 开始读取的位置,相对于缓冲区基地址的位置
:data 读取数据保存位置
:len 读取数据长度
//--返回数据:返回读状态
****************************************************************************/
u8 read_cb(cycle_buffer* cb,u16 pos,u8* data,u16 len){
u16 i,temp=pos;
/*判断缓冲区是否未分配空间*/
if(cb->data==NULL)
return CB_INVALID;
/*判断pos位置是否处于head到尾之间*/
if(cb->tail>=cb->head)
{
if(pos<cb->head||pos>=cb->tail)
return CB_READ_POS_ERR;
}
else
{
if(pos>=cb->tail&&pos<cb->head)
return CB_READ_POS_ERR;
}
/*判断读长度是否大于pos位置到数据尾的数据长度*/
if(cb->tail>=pos)
{
if(len>(cb->tail-pos))
return CB_READ_NOENOUGH;
}
if(cb->tail<pos)
{
if(len>(cb->blen-pos+cb->tail))
return CB_READ_NOENOUGH;
}
for(i=0;i<len;i++)
{
data[i]=cb->data[temp];
if(temp>cb->blen-1)
temp=0;
else
temp++;
}
/*将指针赋值给data*/
//data=&cb->data[pos];
return CB_OK;
}
/****************************************************************************
//--函数名称:get_frame
//--函数功能:根据数据协议中的帧头和帧尾获取有效帧,并删除帧前的无效数据
//--函数参数:cb 目标缓冲区
len 读取到帧的长度
//--返回数据:返回读状态
****************************************************************************/
u8 get_frame(cycle_buffer* cb,u8* data,u16* len)
{
u16 i,head_pos,tail_pos,temp_pos=cb->head;
u8 temp_data[PTL_HT_LENGTH];
u8 find_head=0;
u32 temp_num=0;
signed char m;
for(i=0;i<cb->len-PTL_HT_LENGTH+1;i++)
{
/*读两个字节*/
if(CB_OK!=read_cb(cb,temp_pos,temp_data,PTL_HT_LENGTH))
return CB_READ_ERR;
/*把宏定义的数据头转换成字符数组*/
temp_num=0;
for(m=PTL_HT_LENGTH-1;m>=0;m--)
{
temp_num=temp_num+(temp_data[PTL_HT_LENGTH-1-m]<<(8*m));
}
/*判断是否为数据头*/
if(PTL_HEAD==temp_num)
{
/*记录数据头的位置/更新数据头位置*/
head_pos=temp_pos;
find_head++;
}
/*已找到数据头,再找数据尾*/
if(find_head>0)
{
/*判断是否为数据尾*/
if(PTL_TAIL==temp_num)
{
/*找到了数据头,也找到了数据尾*/
/*记录数据尾的位置*/
tail_pos=temp_pos;
/*计算帧数据长度*/
if(head_pos<tail_pos)
{
*len=tail_pos-head_pos+PTL_HT_LENGTH;
/*copy数据*/
memcpy(data,&cb->data[head_pos],*len);
}
else
{
*len=cb->blen-head_pos+tail_pos+PTL_HT_LENGTH;
/*copy数据*/
memcpy(data,&cb->data[head_pos],cb->blen-head_pos);
memcpy((data+cb->blen-head_pos),&cb->data[0],tail_pos+PTL_HT_LENGTH);
}
/*计算剩余数据长度*/
if(cb->head<=head_pos)
{
/*剩余数据=初始数据-头前无用数据-读走数据*/
cb->len=cb->len-(head_pos-cb->head)-*len;
}
else
{
/*剩余数据=初始数据-头前无用数据-读走数据*/
cb->len=cb->len-(cb->blen-cb->head+head_pos)-*len;
}
/*数据取出后,重置数据头位置*/
if(tail_pos+PTL_HT_LENGTH>=cb->blen)
cb->head=cb->blen-(tail_pos+PTL_HT_LENGTH);
else
cb->head=tail_pos+PTL_HT_LENGTH;
return CB_OK;
}
}
/*数据读取位置后移*/
if(temp_pos==cb->blen-1)
temp_pos=0;
else
temp_pos++;
}
/*读完整个缓冲区未获得完整帧*/
if(find_head>0)
{
/*重置缓冲区头*/
cb->head=head_pos;
/*计算剩余数据长度*/
cb->len=cb->len-(head_pos-cb->head);
}
else
{
/*重置整个缓冲区*/
cb->head=cb->tail=cb->len=0;
}
*len=0;
return CB_NO_FRAME;
}
void cb_test()
{
u8 wlen,data1[50],data[50]="rzrabceddzccab";
u16 len;
cycle_buffer cb;
creat_cb(&cb,50);
write_cb(&cb,&wlen,data,14);
while(1)
{
while(get_frame(&cb,data1,&len)==CB_OK)
{
printf("frame data len %d is:%.*s\n\n",len,len, data1);
Sleep(100);
}
write_cb(&cb,&wlen,data,14);
}
}