生活随笔
收集整理的這篇文章主要介紹了
数据循环缓冲区算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業重金招聘Python工程師標準>>>
使用方法:
創建循環緩沖區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;elsetemp++;}/*將指針賦值給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);elsecb->head=tail_pos+PTL_HT_LENGTH;return CB_OK;}}/*數據讀取位置后移*/if(temp_pos==cb->blen-1)temp_pos=0;elsetemp_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);}
}
轉載于:https://my.oschina.net/u/2345008/blog/892817
總結
以上是生活随笔為你收集整理的数据循环缓冲区算法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。