使用方法:
- 创建循环缓冲区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#include #include #include #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;ilen<=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 head||pos>=cb->tail) return CB_READ_POS_ERR; } else { if(pos>=cb->tail&&pos head) return CB_READ_POS_ERR; } /*判断读长度是否大于pos位置到数据尾的数据长度*/ if(cb->tail>=pos) { if(len>(cb->tail-pos)) return CB_READ_NOENOUGH; } if(cb->tail (cb->blen-pos+cb->tail)) return CB_READ_NOENOUGH; } for(i=0;i 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 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 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); }}