67、自定义通信帧协议解析

帧格式:方便自定义长度多种帧标识传输

格式规定

帧标识A 类型 备注
A<=0x80 短帧 数据长度1字节
A>0x80 长帧 数据长度2字节

短帧:帧标识 帧标识取反 帧用户数据字节数 用户数据…用户数据
长帧:帧标识 帧标识取反 帧用户数据字节数(高8位) 帧用户数据字节数(低8位) 用户数据…用户数据
注意:
帧标识符应尽量避免使用0x00/0xFF,因为出现概率过高,容易误识别
若需提高准确度,则可以使用此文档的协议通信帧协议解析和发送_裸机

源码版本V2.0

使用方法

#include "stdio.h"
#include "stdint.h"
#include "math.h"
#include "frame_driver.h"

#define dDATA_SIZE 65537
int main()
{
	//自定义短帧内容
	uint8_t data[dDATA_SIZE] = { 0x01,0x00,0x03,0x01,0x00,\
	0x01,dIdentify_Invert(0x01),0x01,0x0A,\
	0x02,0x03,0x01,
	0x01, dIdentify_Invert(0x01),0x05,0x01,0x02,0x03,0x04,0x05,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x01, dIdentify_Invert(0x01),0x02,0x01,0x02,\
		0x01, 0x00, 0x03, 0x01, 0x00, \

	0x01, dIdentify_Invert(0x01),0x03,0x01,0x02,0x03,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x02, dIdentify_Invert(0x02), 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x03, dIdentify_Invert(0x03), 0x02, 0x01, 0x02, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x04, dIdentify_Invert(0x04), 0x03, 0x01, 0x02, 0x03, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x05, dIdentify_Invert(0x05), 0x03, 0x01, 0x02, 0x03, \
	0x81, dIdentify_Invert(0x81), dDataLength_MSB(2), dDataLength_LSB(2),0x0A,0x0B\
	};
	uint8_t data2[dDATA_SIZE];
	uint32_t i = 0, j = 0, num = 0;

	i = 0;
	data2[i++] = 0x81;//定义长帧内容
	data2[i++] = dIdentify_Invert(0x81);
	data2[i++] = dDataLength_MSB(dDATA_SIZE - 4);
	data2[i++] = dDataLength_LSB(dDATA_SIZE - 4);
	for (j = 0; j < dDATA_SIZE - 4; j++)data2[i++] = j % 0x0FF;

	frame_handler frame;
	if (frame_init(&frame, 5, dDATA_SIZE) < 0)return 0;创建5个帧资源,最大帧长度为dDATA_SIZE
	if (frame_identify_add(&frame, 0x01) < 0)return 0;//添加标识符0x01帧
	if (frame_identify_add(&frame, 0x02) < 0)return 0;
	if (frame_identify_add(&frame, 0x03) < 0)return 0;
	if (frame_identify_add(&frame, 0x04) < 0)return 0;
	if (frame_identify_add(&frame, 0x81) < 0)return 0;
	frame_identify_add(&frame, 0x05);//超过帧资源添加0x05标识符帧失败

	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出
	}

	for (i = 0; i < dDATA_SIZE; i++)//查找短帧
	{
		if (frame_find(&frame, data[i]) < 0)continue;
		frame_data_printf(frame.data_rx);
	}

	//中途放弃之前的查找
	//for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	//{
	//	if (i == 4)frame_find_clear(&frame);//清空查找器
	//	if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
	//	frame_data_printf(frame.data_rx);//有效帧打印输出
	//}

	frame_DeInit(&frame);//销毁帧资源

	
	uint8_t *pdata = NULL, send[6] = {0};
	pdata = frame_format_generate(0x0A, 2, send);//生成帧格式:0x0A 0xF5 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 5; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}

	pdata = frame_format_generate(0x1A, 2, send);//生成帧格式:0x0A 0xE5 0x00 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 6; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}
	return 0;
}


在这里插入图片描述

在这里插入图片描述
注意:

	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出,数据只能在此轮使用,下轮会进行内存覆盖,其他地方需要使用可以复制走
	}

frame_find(&frame, data2[i])查找到数据后必须当轮使用,下一次查找会进行内存覆盖,导致数据丢失,若他地方需要使用可以复制走

源文件

frame_driver.h

#ifndef _frame_driver_H_
#define _frame_driver_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"

#include "stdio.h"
#define dFrame_LOG(...) printf(__VA_ARGS__) //日志输出

#define dIdentify_Invert(id) ((~id) & 0xFF)//标识符取反
#define dDataLength_MSB(len) ((len>>8)&0xFF)//截取数据长度高8位
#define dDataLength_LSB(len) (len&0xFF)//截取数据长度低8位
#define dDataLength_Merge(MSB,LSB) (((((uint16_t )MSB) << 8)|(uint16_t )LSB) & 0xFFFF)//合并得到长帧的数据长度

typedef struct
{
	uint8_t number;//帧种类数
	uint8_t pos;//帧标识集可用位置
	uint8_t *pbuf;//所有帧标识
}Frame_Identify_StructDef;//帧标识集

typedef struct
{
	uint32_t size; //帧缓冲区字节数
	uint8_t *pbuf;//缓冲区
	uint32_t pos;//位置点
}Frame_Buffer_StructDef;//缓冲区

typedef enum
{
	eFrame_DataState_Find = 0,//查找中
	eFrame_DataState_Receive,//接收数据
	eFrame_DataState_Complete//接收完毕
}Frame_DataState_EnumDef;//帧接收状态

typedef struct
{
	Frame_DataState_EnumDef state;//帧接收状态
	uint8_t identify;//接收的帧标识
	uint32_t size;//用户数据字节数
	uint8_t *pbuf;//帧用户数据缓冲区;注:不含帧头、数据字节数
}Frame_Data_StructDef;

typedef struct
{
	//内部变量区域:请勿修改
	uint8_t state;//帧状态:0--不可用,!0--可用
	Frame_Identify_StructDef identify;//帧集合
	Frame_Buffer_StructDef rx;//接收缓冲区	

	//共享变量区域
	Frame_Data_StructDef data_rx;//接收的数据
}frame_handler;

extern int frame_init(frame_handler *p, uint8_t number, uint32_t rx_size);
extern void frame_DeInit(frame_handler *p);
extern int frame_identify_add(frame_handler *p, uint8_t identify);
extern int frame_find(frame_handler *p, uint8_t data);
extern int frame_find_clear(frame_handler *p);
extern void frame_data_printf(Frame_Data_StructDef data);
extern uint8_t *frame_format_generate(uint8_t identify, uint32_t size, uint8_t *pbuf);

#ifdef __cplusplus
}
#endif
#endif

frame_driver.c

/**********************************************************************
*file:任意帧收发
*author:残梦
*versions:V2.0
*date:2024.3.20
*note:
格式规定:
帧标识A	类型	备注
A<=0x80	短帧	数据长度1字节
A>0x80	长帧	数据长度2字节

短帧:帧标识 帧标识取反 帧用户数据字节数									用户数据...用户数据
长帧:帧标识 帧标识取反 帧用户数据字节数(高8位) 帧用户数据字节数(低8位)  用户数据...用户数据
注意:
帧标识符应尽量避免使用0x00/0xFF,因为出现概率过高,容易误识别

使用方法:

#include "stdio.h"
#include "stdint.h"
#include "math.h"
#include "frame_driver.h"

#define dDATA_SIZE 65537
int main()
{
	//自定义短帧内容
	uint8_t data[dDATA_SIZE] = { 0x01,0x00,0x03,0x01,0x00,\
	0x01,dIdentify_Invert(0x01),0x01,0x0A,\
	0x02,0x03,0x01,
	0x01, dIdentify_Invert(0x01),0x05,0x01,0x02,0x03,0x04,0x05,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x01, dIdentify_Invert(0x01),0x02,0x01,0x02,\
		0x01, 0x00, 0x03, 0x01, 0x00, \

	0x01, dIdentify_Invert(0x01),0x03,0x01,0x02,0x03,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x02, dIdentify_Invert(0x02), 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x03, dIdentify_Invert(0x03), 0x02, 0x01, 0x02, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x04, dIdentify_Invert(0x04), 0x03, 0x01, 0x02, 0x03, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x05, dIdentify_Invert(0x05), 0x03, 0x01, 0x02, 0x03, \
	0x81, dIdentify_Invert(0x81), dDataLength_MSB(2), dDataLength_LSB(2),0x0A,0x0B\
	};
	uint8_t data2[dDATA_SIZE];
	uint32_t i = 0, j = 0, num = 0;

	i = 0;
	data2[i++] = 0x81;//定义长帧内容
	data2[i++] = dIdentify_Invert(0x81);
	data2[i++] = dDataLength_MSB(dDATA_SIZE - 4);
	data2[i++] = dDataLength_LSB(dDATA_SIZE - 4);
	for (j = 0; j < dDATA_SIZE - 4; j++)data2[i++] = j % 0x0FF;

	frame_handler frame;
	if (frame_init(&frame, 5, dDATA_SIZE) < 0)return 0;创建5个帧资源,最大帧长度为dDATA_SIZE
	if (frame_identify_add(&frame, 0x01) < 0)return 0;//添加标识符0x01帧
	if (frame_identify_add(&frame, 0x02) < 0)return 0;
	if (frame_identify_add(&frame, 0x03) < 0)return 0;
	if (frame_identify_add(&frame, 0x04) < 0)return 0;
	if (frame_identify_add(&frame, 0x81) < 0)return 0;
	frame_identify_add(&frame, 0x05);//超过帧资源添加0x05标识符帧失败

	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出
	}

	for (i = 0; i < dDATA_SIZE; i++)//查找短帧
	{
		if (frame_find(&frame, data[i]) < 0)continue;
		frame_data_printf(frame.data_rx);
	}

	//中途放弃之前的查找
	//for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	//{
	//	if (i == 4)frame_find_clear(&frame);//清空查找器
	//	if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
	//	frame_data_printf(frame.data_rx);//有效帧打印输出
	//}

	frame_DeInit(&frame);//销毁帧资源


	uint8_t *pdata = NULL, send[6] = {0};
	pdata = frame_format_generate(0x0A, 2, send);//生成帧格式:0x0A 0xF5 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 5; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}

	pdata = frame_format_generate(0x1A, 2, send);//生成帧格式:0x0A 0xE5 0x00 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 6; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}
	return 0;
}

**********************************************************************/
#include "frame_driver.h"
#include "stdlib.h"
#include "string.h"

static int frame_identify_find(Frame_Identify_StructDef identify, uint8_t id);

/****************************************
@function:匹配帧标识符集合
@param:identify--标识符集合
	id--待匹配的标识符
@return:-1--失败,0--成功
@note:
****************************************/
static int frame_identify_find(Frame_Identify_StructDef identify, uint8_t id)
{
	uint8_t i = 0;

	for (i = 0; i < identify.pos; i++)
	{
		if (identify.pbuf[i] == id)return 0;
	}
	return -1;
}

/****************************************
@function:帧资源初始化
@param:p--帧句柄
	number--帧种类数,范围[1,255]
	rx_size--帧接收缓冲区字节数,等于最大帧长度,范围[4,uint32_t]
@return:
	0--成功
	-1:参数错误
	-2:内存分配失败
@note:
****************************************/
int frame_init(frame_handler *p, uint8_t number, uint32_t rx_size)
{
	if ((p == NULL) || (number == 0) || (rx_size < 4))return -1;
	p->state = 0;
	p->identify.pbuf = (uint8_t *)malloc(number);
	if (p->identify.pbuf == NULL)
	{
		dFrame_LOG("Error[%s-line:%d]:memory allocation failure\n", __func__, __LINE__);
		return -2;
	}
	p->identify.number = number;
	p->identify.pos = 0;

	p->rx.pbuf = (uint8_t *)malloc(rx_size);
	if (p->rx.pbuf == NULL)
	{
		frame_DeInit(p);
		dFrame_LOG("Error[%s-line:%d]:memory allocation failure\n", __func__, __LINE__);
		return -2;
	}
	p->rx.size = rx_size;
	p->rx.pos = 0;

	p->data_rx.state = eFrame_DataState_Find;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;

	p->state = 1;
	return 0;
}

/****************************************
@function:帧资源销毁
@param:p--帧句柄
@return:void
@note:
****************************************/
void frame_DeInit(frame_handler *p)
{
	if (p == NULL)return;
	p->state = 0;
	if (p->identify.pbuf != NULL)free(p->identify.pbuf);
	p->identify.pbuf = NULL;
	p->identify.number = 0;
	p->identify.pos = 0;
	if (p->rx.pbuf != NULL)free(p->rx.pbuf);
	p->rx.pbuf = NULL;
	p->rx.size = 0;
	p->rx.pos = 0;

	p->data_rx.state = eFrame_DataState_Find;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;
}

/****************************************
@function:添加待查找的帧标识
@param:p--帧句柄
	identify--帧标识
		格式规定:
		帧标识	类型	备注
		A<=0x80	短帧	数据长度1字节
		A>0x80	长帧	数据长度2字节

		短帧:帧标识 帧标识取反 数据字节数 数据...数据
		长帧:帧标识 帧标识取反 数据字节数(高8位) 数据字节数(低8位) 数据...数据
@return:
	0:成功
	-1--参数错误
	-2:添加失败
@note:添加重复帧标识无效
****************************************/
int frame_identify_add(frame_handler *p, uint8_t identify)
{
	uint8_t i = 0;
	if (p == NULL)return -1;
	if (p->state == 0)return -1;
	if (p->identify.pos >= p->identify.number)return -2;
	while (i < p->identify.pos)
	{
		if (p->identify.pbuf[i++] == identify)return -2;
	}
	p->identify.pbuf[p->identify.pos++] = identify;
	return 0;
}

/****************************************
@function:数据接收并匹配帧集合
@param:p--帧句柄
	data--新数据
@return:
	0:识别到帧数据,数据信息查看p->data_rx结构体
	-1:参数异常|帧未初始化
	-2:帧查找中
	-3:数据接收中
	-4:接收缓冲区空间不足,原因:初始化的帧资源大小低于帧总长度
@note:
****************************************/
int frame_find(frame_handler *p, uint8_t data)
{
	uint32_t i = 0;
	uint16_t len = 0;

	if (p == NULL)return -1;
	if (p->state == 0)return -1;
	if (p->identify.pos == 0)return -1;//没有待识别的帧标识 
	switch (p->data_rx.state)
	{
	case eFrame_DataState_Find:
	{
		p->rx.pbuf[p->rx.pos++] = data;
		if (p->rx.pos < 4)return -2;

		len = (p->rx.pbuf[0] <= 0x80) ? p->rx.pbuf[2] : dDataLength_Merge(p->rx.pbuf[2], p->rx.pbuf[3]);
		if ((p->rx.pbuf[0] != dIdentify_Invert(p->rx.pbuf[1])) || (len == 0))//帧标识不对|数据长度为0
		{
			//数据移除1字节
			for (i = 1; i < p->rx.pos; i++)p->rx.pbuf[i - 1] = p->rx.pbuf[i];
			p->rx.pos--;
			return -2;
		}
		if (frame_identify_find(p->identify, p->rx.pbuf[0]) < 0)
		{
			//数据移除1字节
			for (i = 1; i < p->rx.pos; i++)p->rx.pbuf[i - 1] = p->rx.pbuf[i];
			p->rx.pos--;
			return -2;
		}

		p->data_rx.identify = p->rx.pbuf[0];
		p->data_rx.size = len;
		p->data_rx.pbuf = (p->data_rx.identify > 0x80) ? (&(p->rx.pbuf[4])) : (&(p->rx.pbuf[3]));
		if ((p->data_rx.identify > 0x80) || (p->data_rx.size > 1))//长帧 或 短帧数据长度为1
		{
			p->data_rx.state = eFrame_DataState_Receive;
			return -3;
		}

		//数据接收完毕:短帧数据长度1
		p->data_rx.state = eFrame_DataState_Complete;
		return 0;
	}
	case eFrame_DataState_Receive:
	{
		if (p->rx.pos >= p->rx.size)
		{
			dFrame_LOG("Error[%s-line:%d]:Insufficient receive buffer space\n", __func__, __LINE__);
			return -4;
		}
		p->rx.pbuf[p->rx.pos++] = data;
		len = (p->data_rx.identify > 0x80) ? (p->rx.pos - 4) : (p->rx.pos - 3);
		if (len < p->data_rx.size)return -3;//继续接收
		p->data_rx.state = eFrame_DataState_Complete;
		return 0;
	}
	case eFrame_DataState_Complete:
	{
		p->rx.pos = 0;
		p->rx.pbuf[p->rx.pos++] = data;
		p->data_rx.identify = 0;
		p->data_rx.size = 0;
		p->data_rx.pbuf = NULL;
		p->data_rx.state = eFrame_DataState_Find;
		return -2;
	}
	}
	return -1;
}

/****************************************
@function:帧查找器清空
@param:p--帧句柄
@return:void
@note:
****************************************/
int frame_find_clear(frame_handler *p)
{
	if (p == NULL)return -1;
	if (p->state == 0)return -1;

	p->rx.pos = 0;
	p->data_rx.state = eFrame_DataState_Find;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;
	return 0;
}

/****************************************
@function:帧接收信息打印
@param:data--接收到的帧数据
@return:void
@note:
****************************************/
void frame_data_printf(Frame_Data_StructDef data)
{
	uint32_t i = 0;

	dFrame_LOG("Identify=0x%0X size=%d", data.identify, data.size);
	for (i = 0; i < data.size; i++)
	{
		if (i == 0)dFrame_LOG(" data{0x%0x", data.pbuf[i]);
		else dFrame_LOG(",0x%0x", data.pbuf[i]);
	}
	if (i != 0)dFrame_LOG("}\n");
	else dFrame_LOG("\n");
}

/****************************************
@function:生成帧格式
@param:identify--帧标识符
	size--帧用户数据字节数,不能为0
	pbuf--帧缓冲区,生成的帧数据放置在此缓冲区,起始位置pbuf[0]
@return:
	NULL:生成失败,参数错误
	!NULL:帧用户数据起始地址
@note:
	注意生成的帧总长度为:
	短帧(identify <= 0x80):(size+3)字节
	长帧(identify > 0x80):(size+4)字节
	此函数会清0缓冲区
****************************************/
uint8_t *frame_format_generate(uint8_t identify, uint32_t size, uint8_t *pbuf)
{
	if ((pbuf == NULL) || (size < 1))return NULL;
	memset(pbuf, 0, (size + ((identify > 0x80) ? 4 : 3)));
	pbuf[0] = identify;
	pbuf[1] = dIdentify_Invert(identify);
	if (identify > 0x80)
	{
		pbuf[2] = dDataLength_MSB(size);
		pbuf[3] = dDataLength_LSB(size);
		return &pbuf[4];
	}
	pbuf[2] = size;
	return &pbuf[3];
}

网盘下载:
链接:https://pan.baidu.com/s/1XY_L-kSYUsLiJisx0Q1Y0A
提取码:6v9k

源码版本V2.1

更新查找函数,使用方法不变,帧数据为空时返回错误码-5
frame_driver.h

#ifndef _frame_driver_H_
#define _frame_driver_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"

#include "stdio.h"
#define dFrame_LOG(...) printf(__VA_ARGS__) //日志输出

#define dIdentify_Invert(id) ((~(id)) & 0xFF)//标识符取反
#define dDataLength_MSB(len) (((len)>>8)&0xFF)//截取数据长度高8位
#define dDataLength_LSB(len) ((len)&0xFF)//截取数据长度低8位
#define dDataLength_Merge(MSB,LSB) (((((uint16_t )(MSB)) << 8)|(uint16_t )(LSB)) & 0xFFFF)//合并得到长帧的数据长度
#define dFrame_FormatSize(id) (((id) > 0x80)?4:3)//帧格式大小
#define dFrame_Length_Get(id,DataLength) ((uint16_t )dFrame_FormatSize(id) + DataLength)//获取帧长度:id-标识符,DataLength-用户数据长度

typedef struct
{
	uint8_t number;//帧种类数
	uint8_t pos;//帧标识集可用位置
	uint8_t *pbuf;//所有帧标识
}Frame_Identify_StructDef;//帧标识集

typedef struct
{
	uint32_t size; //帧缓冲区字节数
	uint8_t *pbuf;//缓冲区
	uint32_t pos;//位置点
}Frame_Buffer_StructDef;//缓冲区

typedef enum
{
	eFrame_State_ID = 0,//核对ID
	eFrame_State_Bytes,//核对帧字节数
	eFrame_State_Receive,//接收数据
}Frame_State_EnumDef;//帧接收状态

typedef struct
{
	Frame_State_EnumDef state;//帧接收状态
	uint8_t identify;//接收的帧标识
	uint32_t size;//用户数据字节数
	uint8_t *pbuf;//帧用户数据缓冲区;注:不含帧头、数据字节数
}Frame_Data_StructDef;

typedef struct
{
	//内部变量区域:请勿修改
	uint8_t state;//帧状态:0--不可用,!0--可用
	Frame_Identify_StructDef identify;//帧集合
	Frame_Buffer_StructDef rx;//接收缓冲区

	//共享变量区域
	Frame_Data_StructDef data_rx;//接收的数据
}frame_handler;

extern int frame_init(frame_handler *p, uint8_t number, uint32_t rx_size);
extern void frame_DeInit(frame_handler *p);
extern int frame_identify_add(frame_handler *p, uint8_t identify);
extern int frame_find(frame_handler *p, uint8_t data);
extern int frame_find_clear(frame_handler *p);
extern void frame_data_printf(Frame_Data_StructDef data);
extern uint8_t *frame_format_generate(uint8_t identify, uint32_t size, uint8_t *pbuf);

#ifdef __cplusplus
}
#endif
#endif

frame_driver.c

/**********************************************************************
*file:任意帧收发
*author:残梦
*versions:V2.1
*date:2024.3.20
*note:
格式规定:
帧标识A	类型	备注
A<=0x80	短帧	数据长度1字节
A>0x80	长帧	数据长度2字节

短帧:帧标识 帧标识取反 帧用户数据字节数									用户数据...用户数据
长帧:帧标识 帧标识取反 帧用户数据字节数(高8位) 帧用户数据字节数(低8位)  用户数据...用户数据
注意:
帧标识符应尽量避免使用0x00/0xFF,因为出现概率过高,容易误识别

使用方法:

#include "stdio.h"
#include "stdint.h"
#include "math.h"
#include "frame_driver.h"

#define dDATA_SIZE 65537
int main()
{
	//自定义短帧内容
	uint8_t data[dDATA_SIZE] = { 0x01,0x00,0x03,0x01,0x00,\
	0x01,dIdentify_Invert(0x01),0x01,0x0A,\
	0x02,0x03,0x01,
	0x01, dIdentify_Invert(0x01),0x05,0x01,0x02,0x03,0x04,0x05,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x01, dIdentify_Invert(0x01),0x02,0x01,0x02,\
		0x01, 0x00, 0x03, 0x01, 0x00, \

	0x01, dIdentify_Invert(0x01),0x03,0x01,0x02,0x03,\
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x02, dIdentify_Invert(0x02), 0x05, 0x01, 0x02, 0x03, 0x04, 0x05, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x03, dIdentify_Invert(0x03), 0x02, 0x01, 0x02, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x04, dIdentify_Invert(0x04), 0x03, 0x01, 0x02, 0x03, \
		0x01, 0x00, 0x03, 0x01, 0x00, \
	0x05, dIdentify_Invert(0x05), 0x03, 0x01, 0x02, 0x03, \
	0x81, dIdentify_Invert(0x81), dDataLength_MSB(2), dDataLength_LSB(2),0x0A,0x0B\
	};
	uint8_t data2[dDATA_SIZE];
	uint32_t i = 0, j = 0, num = 0;

	i = 0;
	data2[i++] = 0x81;//定义长帧内容
	data2[i++] = dIdentify_Invert(0x81);
	data2[i++] = dDataLength_MSB(dDATA_SIZE - 4);
	data2[i++] = dDataLength_LSB(dDATA_SIZE - 4);
	for (j = 0; j < dDATA_SIZE - 4; j++)data2[i++] = j % 0x0FF;

	frame_handler frame;
	if (frame_init(&frame, 5, dDATA_SIZE) < 0)return 0;创建5个帧资源,最大帧长度为dDATA_SIZE
	if (frame_identify_add(&frame, 0x01) < 0)return 0;//添加标识符0x01帧
	if (frame_identify_add(&frame, 0x02) < 0)return 0;
	if (frame_identify_add(&frame, 0x03) < 0)return 0;
	if (frame_identify_add(&frame, 0x04) < 0)return 0;
	if (frame_identify_add(&frame, 0x81) < 0)return 0;
	frame_identify_add(&frame, 0x05);//超过帧资源添加0x05标识符帧失败

	for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	{
		if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
		frame_data_printf(frame.data_rx);//有效帧打印输出
	}

	for (i = 0; i < dDATA_SIZE; i++)//查找短帧
	{
		if (frame_find(&frame, data[i]) < 0)continue;
		frame_data_printf(frame.data_rx);
	}

	//中途放弃之前的查找
	//for (i = 0; i < dDATA_SIZE; i++)//查找长帧
	//{
	//	if (i == 4)frame_find_clear(&frame);//清空查找器
	//	if (frame_find(&frame, data2[i]) < 0)continue;//帧识别
	//	frame_data_printf(frame.data_rx);//有效帧打印输出
	//}

	frame_DeInit(&frame);//销毁帧资源


	uint8_t *pdata = NULL, send[6] = {0};
	pdata = frame_format_generate(0x0A, 2, send);//生成帧格式:0x0A 0xF5 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 5; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}

	pdata = frame_format_generate(0x1A, 2, send);//生成帧格式:0x0A 0xE5 0x00 0x02 0x00 0x00
	if (pdata == NULL)printf("生成失败\n");
	else
	{
		for (i = 0; i < 6; i++)printf("0x%0X,", send[i]);
		printf("\n");
	}
	return 0;
}

示例2:
#define BufferSize 4076
void main()
{
    uint8_t buf[] = {\
0x81,0x7E,0x03,0xFC,0x00,0x04,0x00,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x80,0x3F,0xF1,0x66,0x80,0x3F,0xE2,0xCD,0x80,0x3F,0xD0,0x34,0x81,0x3F,0xBB,0x9B,0x81,0x3F,0xA2,0x02,0x82,0x3F,0x84,0x69,0x82,0x3F,0x60,0xD0,0x82,0x3F,0x34,0x37,0x83,0x3F,0x00,0x9E,0x83,0x3F,0xC3,0x04,0x84,0x3F,0x7B,0x6B,0x84,0x3F,0x28,0xD2,0x84,0x3F,0xC8,0x38,0x85,0x3F,0x5B,0x9F,0x85,0x3F,0xDF,0x05,0x86,0x3F,0x54,0x6C,0x86,0x3F,0xB8,0xD2,0x86,0x3F,0x0A,0x39,0x87,0x3F,0x4A,0x9F,0x87,0x3F,0x76,0x05,0x88,0x3F,0x8D,0x6B,0x88,0x3F,0x8E,0xD1,0x88,0x3F,0x79,0x37,0x89,0x3F,0x4C,0x9D,0x89,0x3F,0x06,0x03,0x8A,0x3F,0xA6,0x68,0x8A,0x3F,0x2B,0xCE,0x8A,0x3F,0x94,0x33,0x8B,0x3F,0xE0,0x98,0x8B,0x3F,0x0E,0xFE,0x8B,0x3F,0x1D,0x63,0x8C,0x3F,0x0C,0xC8,0x8C,0x3F,0xDA,0x2C,0x8D,0x3F,0x86,0x91,0x8D,0x3F,0x0F,0xF6,0x8D,0x3F,0x74,0x5A,0x8E,0x3F,0xB3,0xBE,0x8E,0x3F,0xCD,0x22,0x8F,0x3F,0xBF,0x86,0x8F,0x3F,0x89,0xEA,0x8F,0x3F,0x2A,0x4E,0x90,0x3F,0xA1,0xB1,0x90,0x3F,0xEC,0x14,0x91,0x3F,0x0B,0x78,0x91,0x3F,0xFD,0xDA,0x91,0x3F,0xC1,0x3D,0x92,0x3F,0x56,0xA0,0x92,0x3F,0xBB,0x02,0x93,0x3F,0xEE,0x64,0x93,0x3F,0xEF,0xC6,0x93,0x3F,0xBD,0x28,0x94,0x3F,0x57,0x8A,0x94,0x3F,0xBC,0xEB,0x94,0x3F,0xEA,0x4C,0x95,0x3F,0xE2,0xAD,0x95,0x3F,0xA1,0x0E,0x96,0x3F,0x27,0x6F,0x96,0x3F,0x74,0xCF,0x96,0x3F,0x85,0x2F,0x97,0x3F,0x5A,0x8F,0x97,0x3F,0xF3,0xEE,0x97,0x3F,0x4D,0x4E,0x98,0x3F,0x68,0xAD,0x98,0x3F,0x44,0x0C,0x99,0x3F,0xDF,0x6A,0x99,0x3F,0x38,0xC9,0x99,0x3F,0x4E,0x27,0x9A,0x3F,0x21,0x85,0x9A,0x3F,0xAF,0xE2,0x9A,0x3F,0xF8,0x3F,0x9B,0x3F,0xFA,0x9C,0x9B,0x3F,0xB4,0xF9,0x9B,0x3F,0x27,0x56,0x9C,0x3F,0x4F,0xB2,0x9C,0x3F,0x2E,0x0E,0x9D,0x3F,0xC2,0x69,0x9D,0x3F,0x09,0xC5,0x9D,0x3F,0x03,0x20,0x9E,0x3F,0xB0,0x7A,0x9E,0x3F,0x0D,0xD5,0x9E,0x3F,0x1B,0x2F,0x9F,0x3F,0xD8,0x88,0x9F,0x3F,0x44,0xE2,0x9F,0x3F,0x5D,0x3B,0xA0,0x3F,0x22,0x94,0xA0,0x3F,0x94,0xEC,0xA0,0x3F,0xB0,0x44,0xA1,0x3F,0x76,0x9C,0xA1,0x3F,0xE5,0xF3,0xA1,0x3F,0xFC,0x4A,0xA2,0x3F,0xBB,0xA1,0xA2,0x3F,0x20,0xF8,0xA2,0x3F,0x2A,0x4E,0xA3,0x3F,0xDA,0xA3,0xA3,0x3F,0x2D,0xF9,0xA3,0x3F,0x22,0x4E,0xA4,0x3F,0xBA,0xA2,0xA4,0x3F,0xF3,0xF6,0xA4,0x3F,0xCD,0x4A,0xA5,0x3F,0x46,0x9E,0xA5,0x3F,0x5E,0xF1,0xA5,0x3F,0x13,0x44,0xA6,0x3F,0x66,0x96,0xA6,0x3F,0x54,0xE8,0xA6,0x3F,0xDE,0x39,0xA7,0x3F,0x03,0x8B,0xA7,0x3F,0xC1,0xDB,0xA7,0x3F,0x18,0x2C,0xA8,0x3F,0x08,0x7C,0xA8,0x3F,0x8E,0xCB,0xA8,0x3F,0xAB,0x1A,0xA9,0x3F,0x5D,0x69,0xA9,0x3F,0xA5,0xB7,0xA9,0x3F,0x80,0x05,0xAA,0x3F,0xEF,0x52,0xAA,0x3F,0xF0,0x9F,0xAA,0x3F,0x83,0xEC,0xAA,0x3F,0xA7,0x38,0xAB,0x3F,0x5B,0x84,0xAB,0x3F,0x9F,0xCF,0xAB,0x3F,0x71,0x1A,0xAC,0x3F,0xD1,0x64,0xAC,0x3F,0xBE,0xAE,0xAC,0x3F,0x38,0xF8,0xAC,0x3F,0x3D,0x41,0xAD,0x3F,0xCD,0x89,0xAD,0x3F,0xE7,0xD1,0xAD,0x3F,0x8B,0x19,0xAE,0x3F,0xB7,0x60,0xAE,0x3F,0x6C,0xA7,0xAE,0x3F,0xA8,0xED,0xAE,0x3F,0x6A,0x33,0xAF,0x3F,0xB2,0x78,0xAF,0x3F,0x80,0xBD,0xAF,0x3F,0xD2,0x01,0xB0,0x3F,0xA8,0x45,0xB0,0x3F,0x00,0x89,0xB0,0x3F,0xDC,0xCB,0xB0,0x3F,0x39,0x0E,0xB1,0x3F,0x17,0x50,0xB1,0x3F,0x75,0x91,0xB1,0x3F,0x54,0xD2,0xB1,0x3F,0xB1,0x12,0xB2,0x3F,0x8D,0x52,0xB2,0x3F,0xE6,0x91,0xB2,0x3F,0xBD,0xD0,0xB2,0x3F,0x10,0x0F,0xB3,0x3F,0xE0,0x4C,0xB3,0x3F,0x2A,0x8A,0xB3,0x3F,0xEF,0xC6,0xB3,0x3F,0x2E,0x03,0xB4,0x3F,0xE7,0x3E,0xB4,0x3F,0x18,0x7A,0xB4,0x3F,0xC2,0xB4,0xB4,0x3F,0xE3,0xEE,0xB4,0x3F,0x7C,0x28,0xB5,0x3F,0x8A,0x61,0xB5,0x3F,0x0F,0x9A,0xB5,0x3F,0x09,0xD2,0xB5,0x3F,0x78,0x09,0xB6,0x3F,0x5B,0x40,0xB6,0x3F,0xB2,0x76,0xB6,0x3F,0x7B,0xAC,0xB6,0x3F,0xB7,0xE1,0xB6,0x3F,0x66,0x16,0xB7,0x3F,0x85,0x4A,0xB7,0x3F,0x16,0x7E,0xB7,0x3F,0x17,0xB1,0xB7,0x3F,0x88,0xE3,0xB7,0x3F,0x69,0x15,0xB8,0x3F,0xB8,0x46,0xB8,0x3F,0x76,0x77,0xB8,0x3F,0xA1,0xA7,0xB8,0x3F,0x3A,0xD7,0xB8,0x3F,0x40,0x06,0xB9,0x3F,0xB3,0x34,0xB9,0x3F,0x91,0x62,0xB9,0x3F,0xDB,0x8F,0xB9,0x3F,0x90,0xBC,0xB9,0x3F,0xB0,0xE8,0xB9,0x3F,0x3A,0x14,0xBA,0x3F,0x2D,0x3F,0xBA,0x3F,0x8A,0x69,0xBA,0x3F,0x50,0x93,0xBA,0x3F,0x7E,0xBC,0xBA,0x3F,0x14,0xE5,0xBA,0x3F,0x12,0x0D,0xBB,0x3F,0x77,0x34,0xBB,0x3F,0x43,0x5B,0xBB,0x3F,0x75,0x81,0xBB,0x3F,0x0E,0xA7,0xBB,0x3F,0x0C,0xCC,0xBB,0x3F,0x6F,0xF0,0xBB,0x3F,0x37,0x14,0xBC,0x3F,0x64,0x37,0xBC,0x3F,0xF5,0x59,0xBC,0x3F,0xEA,0x7B,0xBC,0x3F,0x42,0x9D,0xBC,0x3F,0xFE,0xBD,0xBC,0x3F,0x1C,0xDE,0xBC,0x3F,0x9D,0xFD,0xBC,0x3F,0x80,0x1C,0xBD,0x3F,0xC5,0x3A,0xBD,0x3F,0x6C,0x58,0xBD,0x3F,0x74,0x75,0xBD,0x3F,0xDC,0x91,0xBD,0x3F,0xA6,0xAD,0xBD,0x3F,0xD0,0xC8,0xBD,0x3F,0x5A,0xE3,0xBD,0x3F,0x44,0xFD,0xBD,0x3F,0x8E,0x16,0xBE,0x3F,0x37,0x2F,0xBE,0x3F,0x3F,0x47,0xBE,0x3F,0xA6,0x5E,0xBE,0x3F,0x6C,0x75,0xBE,0x3F,0x90,0x8B,0xBE,0x3F,0x12,0xA1,0xBE,0x3F,0xF2,0xB5,0xBE,0x3F,0x30,0xCA,0xBE,0x3F,0xCB,0xDD,0xBE,0x3F,0xC4,0xF0,0xBE,0x3F,0x1A,0x03,0xBF,0x3F,0xCD,0x14,0xBF,0x3F,0xDD,0x25,0xBF,0x3F,0x49,0x36,0xBF,0x3F,0x12,0x46,0xBF,0x3F,0x37,0x55,0xBF,0x3F,0xB8,0x63,0xBF,0x3F,0x96,0x71,0xBF,0x3F,0xCF,0x7E,0xBF,0x3F,0x63,0x8B,0xBF,0x3F,0x54,0x97,0xBF,0x3F,0xA0,0xA2,0xBF,0x3F,0x47,0xAD,0xBF,0x3F,0x4A,0xB7,0xBF,0x3F,0xA7,0xC0,0xBF,0x3F,0x60,0xC9,0xBF,0x3F,0x74,0xD1,0xBF,0x3F,0xE2,0xD8,0xBF,0x3F,0xAB,0xDF,0xBF,0x3F,0xD0,0xE5,0xBF,0x3F,0x4E,0xEB,0xBF,0x3F,0x28,0xF0,0xBF,0x3F,0x5C,0xF4,0xBF,0x3F,0xEA,0xF7,0xBF,0x3F,0xD3,0xFA,0xBF,0x3F,0x17,0xFD,0xBF,0x3F,0xB5,0xFE,0xBF,0x3F,0xAD,0xFF,0xBF,0x3F,0x00,0x00,0xC0,0x3F,0xAD,0xFF,0xBF,0x3F,0xB5,0xFE,0xBF,0x3F,0x81,0x7E,0x03,0xFC,0x00,0x04,0x00,0x00,0xFD,0x00,0xFD,0x00,0x17,0xFD,0xBF,0x3F,0xD3,0xFA,0xBF,0x3F,0xEA,0xF7,0xBF,0x3F,0x5C,0xF4,0xBF,0x3F,0x28,0xF0,0xBF,0x3F,0x4E,0xEB,0xBF,0x3F,0xD0,0xE5,0xBF,0x3F,0xAC,0xDF,0xBF,0x3F,0xE2,0xD8,0xBF,0x3F,0x74,0xD1,0xBF,0x3F,0x60,0xC9,0xBF,0x3F,0xA7,0xC0,0xBF,0x3F,0x4A,0xB7,0xBF,0x3F,0x47,0xAD,0xBF,0x3F,0xA0,0xA2,0xBF,0x3F,0x54,0x97,0xBF,0x3F,0x63,0x8B,0xBF,0x3F,0xCF,0x7E,0xBF,0x3F,0x96,0x71,0xBF,0x3F,0xB8,0x63,0xBF,0x3F,0x37,0x55,0xBF,0x3F,0x12,0x46,0xBF,0x3F,0x49,0x36,0xBF,0x3F,0xDD,0x25,0xBF,0x3F,0xCD,0x14,0xBF,0x3F,0x1A,0x03,0xBF,0x3F,0xC4,0xF0,0xBE,0x3F,0xCB,0xDD,0xBE,0x3F,0x30,0xCA,0xBE,0x3F,0xF2,0xB5,0xBE,0x3F,0x12,0xA1,0xBE,0x3F,0x90,0x8B,0xBE,0x3F,0x6C,0x75,0xBE,0x3F,0xA6,0x5E,0xBE,0x3F,0x3F,0x47,0xBE,0x3F,0x37,0x2F,0xBE,0x3F,0x8E,0x16,0xBE,0x3F,0x44,0xFD,0xBD,0x3F,0x5A,0xE3,0xBD,0x3F,0xD0,0xC8,0xBD,0x3F,0xA6,0xAD,0xBD,0x3F,0xDD,0x91,0xBD,0x3F,0x74,0x75,0xBD,0x3F,0x6C,0x58,0xBD,0x3F,0xC5,0x3A,0xBD,0x3F,0x80,0x1C,0xBD,0x3F,0x9D,0xFD,0xBC,0x3F,0x1C,0xDE,0xBC,0x3F,0xFE,0xBD,0xBC,0x3F,0x42,0x9D,0xBC,0x3F,0xEA,0x7B,0xBC,0x3F,0xF5,0x59,0xBC,0x3F,0x64,0x37,0xBC,0x3F,0x37,0x14,0xBC,0x3F,0x6F,0xF0,0xBB,0x3F,0x0C,0xCC,0xBB,0x3F,0x0E,0xA7,0xBB,0x3F,0x75,0x81,0xBB,0x3F,0x43,0x5B,0xBB,0x3F,0x77,0x34,0xBB,0x3F,0x12,0x0D,0xBB,0x3F,0x14,0xE5,0xBA,0x3F,0x7E,0xBC,0xBA,0x3F,0x50,0x93,0xBA,0x3F,0x8A,0x69,0xBA,0x3F,0x2D,0x3F,0xBA,0x3F,0x3A,0x14,0xBA,0x3F,0xB0,0xE8,0xB9,0x3F,0x90,0xBC,0xB9,0x3F,0xDB,0x8F,0xB9,0x3F,0x91,0x62,0xB9,0x3F,0xB3,0x34,0xB9,0x3F,0x40,0x06,0xB9,0x3F,0x3A,0xD7,0xB8,0x3F,0xA1,0xA7,0xB8,0x3F,0x76,0x77,0xB8,0x3F,0xB8,0x46,0xB8,0x3F,0x69,0x15,0xB8,0x3F,0x88,0xE3,0xB7,0x3F,0x17,0xB1,0xB7,0x3F,0x16,0x7E,0xB7,0x3F,0x86,0x4A,0xB7,0x3F,0x66,0x16,0xB7,0x3F,0xB8,0xE1,0xB6,0x3F,0x7B,0xAC,0xB6,0x3F,0xB2,0x76,0xB6,0x3F,0x5B,0x40,0xB6,0x3F,0x78,0x09,0xB6,0x3F,0x09,0xD2,0xB5,0x3F,0x0F,0x9A,0xB5,0x3F,0x8B,0x61,0xB5,0x3F,0x7C,0x28,0xB5,0x3F,0xE3,0xEE,0xB4,0x3F,0xC2,0xB4,0xB4,0x3F,0x19,0x7A,0xB4,0x3F,0xE7,0x3E,0xB4,0x3F,0x2E,0x03,0xB4,0x3F,0xEF,0xC6,0xB3,0x3F,0x2A,0x8A,0xB3,0x3F,0xE0,0x4C,0xB3,0x3F,0x11,0x0F,0xB3,0x3F,0xBD,0xD0,0xB2,0x3F,0xE6,0x91,0xB2,0x3F,0x8D,0x52,0xB2,0x3F,0xB1,0x12,0xB2,0x3F,0x54,0xD2,0xB1,0x3F,0x75,0x91,0xB1,0x3F,0x17,0x50,0xB1,0x3F,0x39,0x0E,0xB1,0x3F,0xDC,0xCB,0xB0,0x3F,0x01,0x89,0xB0,0x3F,0xA8,0x45,0xB0,0x3F,0xD2,0x01,0xB0,0x3F,0x80,0xBD,0xAF,0x3F,0xB3,0x78,0xAF,0x3F,0x6A,0x33,0xAF,0x3F,0xA8,0xED,0xAE,0x3F,0x6C,0xA7,0xAE,0x3F,0xB8,0x60,0xAE,0x3F,0x8B,0x19,0xAE,0x3F,0xE7,0xD1,0xAD,0x3F,0xCD,0x89,0xAD,0x3F,0x3D,0x41,0xAD,0x3F,0x38,0xF8,0xAC,0x3F,0xBE,0xAE,0xAC,0x3F,0xD1,0x64,0xAC,0x3F,0x71,0x1A,0xAC,0x3F,0x9F,0xCF,0xAB,0x3F,0x5B,0x84,0xAB,0x3F,0xA7,0x38,0xAB,0x3F,0x83,0xEC,0xAA,0x3F,0xF0,0x9F,0xAA,0x3F,0xEF,0x52,0xAA,0x3F,0x80,0x05,0xAA,0x3F,0xA5,0xB7,0xA9,0x3F,0x5E,0x69,0xA9,0x3F,0xAB,0x1A,0xA9,0x3F,0x8E,0xCB,0xA8,0x3F,0x08,0x7C,0xA8,0x3F,0x19,0x2C,0xA8,0x3F,0xC1,0xDB,0xA7,0x3F,0x03,0x8B,0xA7,0x3F,0xDF,0x39,0xA7,0x3F,0x55,0xE8,0xA6,0x3F,0x66,0x96,0xA6,0x3F,0x13,0x44,0xA6,0x3F,0x5E,0xF1,0xA5,0x3F,0x46,0x9E,0xA5,0x3F,0xCD,0x4A,0xA5,0x3F,0xF4,0xF6,0xA4,0x3F,0xBB,0xA2,0xA4,0x3F,0x23,0x4E,0xA4,0x3F,0x2D,0xF9,0xA3,0x3F,0xDA,0xA3,0xA3,0x3F,0x2B,0x4E,0xA3,0x3F,0x20,0xF8,0xA2,0x3F,0xBB,0xA1,0xA2,0x3F,0xFD,0x4A,0xA2,0x3F,0xE5,0xF3,0xA1,0x3F,0x76,0x9C,0xA1,0x3F,0xB0,0x44,0xA1,0x3F,0x94,0xEC,0xA0,0x3F,0x23,0x94,0xA0,0x3F,0x5D,0x3B,0xA0,0x3F,0x44,0xE2,0x9F,0x3F,0xD8,0x88,0x9F,0x3F,0x1B,0x2F,0x9F,0x3F,0x0E,0xD5,0x9E,0x3F,0xB0,0x7A,0x9E,0x3F,0x04,0x20,0x9E,0x3F,0x09,0xC5,0x9D,0x3F,0xC2,0x69,0x9D,0x3F,0x2E,0x0E,0x9D,0x3F,0x50,0xB2,0x9C,0x3F,0x27,0x56,0x9C,0x3F,0xB5,0xF9,0x9B,0x3F,0xFA,0x9C,0x9B,0x3F,0xF8,0x3F,0x9B,0x3F,0xAF,0xE2,0x9A,0x3F,0x21,0x85,0x9A,0x3F,0x4F,0x27,0x9A,0x3F,0x38,0xC9,0x99,0x3F,0xDF,0x6A,0x99,0x3F,0x44,0x0C,0x99,0x3F,0x69,0xAD,0x98,0x3F,0x4D,0x4E,0x98,0x3F,0xF3,0xEE,0x97,0x3F,0x5A,0x8F,0x97,0x3F,0x85,0x2F,0x97,0x3F,0x74,0xCF,0x96,0x3F,0x28,0x6F,0x96,0x3F,0xA1,0x0E,0x96,0x3F,0xE2,0xAD,0x95,0x3F,0xEB,0x4C,0x95,0x3F,0xBC,0xEB,0x94,0x3F,0x57,0x8A,0x94,0x3F,0xBD,0x28,0x94,0x3F,0xEF,0xC6,0x93,0x3F,0xEE,0x64,0x93,0x3F,0xBB,0x02,0x93,0x3F,0x56,0xA0,0x92,0x3F,0xC2,0x3D,0x92,0x3F,0xFE,0xDA,0x91,0x3F,0x0C,0x78,0x91,0x3F,0xEC,0x14,0x91,0x3F,0xA1,0xB1,0x90,0x3F,0x2A,0x4E,0x90,0x3F,0x89,0xEA,0x8F,0x3F,0xBF,0x86,0x8F,0x3F,0xCD,0x22,0x8F,0x3F,0xB3,0xBE,0x8E,0x3F,0x74,0x5A,0x8E,0x3F,0x0F,0xF6,0x8D,0x3F,0x86,0x91,0x8D,0x3F,0xDB,0x2C,0x8D,0x3F,0x0D,0xC8,0x8C,0x3F,0x1E,0x63,0x8C,0x3F,0x0E,0xFE,0x8B,0x3F,0xE0,0x98,0x8B,0x3F,0x94,0x33,0x8B,0x3F,0x2B,0xCE,0x8A,0x3F,0xA6,0x68,0x8A,0x3F,0x06,0x03,0x8A,0x3F,0x4C,0x9D,0x89,0x3F,0x79,0x37,0x89,0x3F,0x8F,0xD1,0x88,0x3F,0x8D,0x6B,0x88,0x3F,0x76,0x05,0x88,0x3F,0x4A,0x9F,0x87,0x3F,0x0A,0x39,0x87,0x3F,0xB8,0xD2,0x86,0x3F,0x54,0x6C,0x86,0x3F,0xDF,0x05,0x86,0x3F,0x5B,0x9F,0x85,0x3F,0xC8,0x38,0x85,0x3F,0x28,0xD2,0x84,0x3F,0x7B,0x6B,0x84,0x3F,0xC3,0x04,0x84,0x3F,0x00,0x9E,0x83,0x3F,0x34,0x37,0x83,0x3F,0x60,0xD0,0x82,0x3F,0x84,0x69,0x82,0x3F,0xA2,0x02,0x82,0x3F,0xBB,0x9B,0x81,0x3F,0xD0,0x34,0x81,0x3F,0xE2,0xCD,0x80,0x3F,0xF2,0x66,0x80,0x3F,0x00,0x00,0x80,0x3F,0x1E,0x32,0x7F,0x3F,0x3D,0x64,0x7E,0x3F,0x60,0x96,0x7D,0x3F,0x8A,0xC8,0x7C,0x3F,0xBC,0xFA,0x7B,0x3F,0x81,0x7E,0x03,0xFC,0x00,0x04,0x00,0x00,0xFD,0x00,0xFA,0x01,0xF8,0x2C,0x7B,0x3F,0x41,0x5F,0x7A,0x3F,0x99,0x91,0x79,0x3F,0x01,0xC4,0x78,0x3F,0x7B,0xF6,0x77,0x3F,0x0B,0x29,0x77,0x3F,0xB1,0x5B,0x76,0x3F,0x71,0x8E,0x75,0x3F,0x4B,0xC1,0x74,0x3F,0x43,0xF4,0x73,0x3F,0x59,0x27,0x73,0x3F,0x91,0x5A,0x72,0x3F,0xEC,0x8D,0x71,0x3F,0x6D,0xC1,0x70,0x3F,0x15,0xF5,0x6F,0x3F,0xE7,0x28,0x6F,0x3F,0xE4,0x5C,0x6E,0x3F,0x0E,0x91,0x6D,0x3F,0x69,0xC5,0x6C,0x3F,0xF5,0xF9,0x6B,0x3F,0xB5,0x2E,0x6B,0x3F,0xAB,0x63,0x6A,0x3F,0xD9,0x98,0x69,0x3F,0x40,0xCE,0x68,0x3F,0xE4,0x03,0x68,0x3F,0xC6,0x39,0x67,0x3F,0xE8,0x6F,0x66,0x3F,0x4C,0xA6,0x65,0x3F,0xF4,0xDC,0x64,0x3F,0xE2,0x13,0x64,0x3F,0x19,0x4B,0x63,0x3F,0x9A,0x82,0x62,0x3F,0x67,0xBA,0x61,0x3F,0x83,0xF2,0x60,0x3F,0xEE,0x2A,0x60,0x3F,0xAD,0x63,0x5F,0x3F,0xBF,0x9C,0x5E,0x3F,0x28,0xD6,0x5D,0x3F,0xEA,0x0F,0x5D,0x3F,0x05,0x4A,0x5C,0x3F,0x7E,0x84,0x5B,0x3F,0x54,0xBF,0x5A,0x3F,0x8B,0xFA,0x59,0x3F,0x24,0x36,0x59,0x3F,0x22,0x72,0x58,0x3F,0x86,0xAE,0x57,0x3F,0x52,0xEB,0x56,0x3F,0x89,0x28,0x56,0x3F,0x2C,0x66,0x55,0x3F,0x3D,0xA4,0x54,0x3F,0xBE,0xE2,0x53,0x3F,0xB1,0x21,0x53,0x3F,0x19,0x61,0x52,0x3F,0xF6,0xA0,0x51,0x3F,0x4C,0xE1,0x50,0x3F,0x1B,0x22,0x50,0x3F,0x67,0x63,0x4F,0x3F,0x30,0xA5,0x4E,0x3F,0x78,0xE7,0x4D,0x3F,0x42,0x2A,0x4D,0x3F,0x90,0x6D,0x4C,0x3F,0x64,0xB1,0x4B,0x3F,0xBE,0xF5,0x4A,0x3F,0xA2,0x3A,0x4A,0x3F,0x11,0x80,0x49,0x3F,0x0D,0xC6,0x48,0x3F,0x98,0x0C,0x48,0x3F,0xB3,0x53,0x47,0x3F,0x61,0x9B,0x46,0x3F,0xA4,0xE3,0x45,0x3F,0x7D,0x2C,0x45,0x3F,0xEE,0x75,0x44,0x3F,0xFA,0xBF,0x43,0x3F,0xA1,0x0A,0x43,0x3F,0xE6,0x55,0x42,0x3F,0xCA,0xA1,0x41,0x3F,0x50,0xEE,0x40,0x3F,0x79,0x3B,0x40,0x3F,0x47,0x89,0x3F,0x3F,0xBC,0xD7,0x3E,0x3F,0xD9,0x26,0x3E,0x3F,0xA1,0x76,0x3D,0x3F,0x14,0xC7,0x3C,0x3F,0x36,0x18,0x3C,0x3F,0x08,0x6A,0x3B,0x3F,0x8A,0xBC,0x3A,0x3F,0xC0,0x0F,0x3A,0x3F,0xAB,0x63,0x39,0x3F,0x4D,0xB8,0x38,0x3F,0xA7,0x0D,0x38,0x3F,0xBC,0x63,0x37,0x3F,0x8C,0xBA,0x36,0x3F,0x19,0x12,0x36,0x3F,0x66,0x6A,0x35,0x3F,0x74,0xC3,0x34,0x3F,0x45,0x1D,0x34,0x3F,0xDA,0x77,0x33,0x3F,0x35,0xD3,0x32,0x3F,0x57,0x2F,0x32,0x3F,0x43,0x8C,0x31,0x3F,0xFA,0xE9,0x30,0x3F,0x7E,0x48,0x30,0x3F,0xD0,0xA7,0x2F,0x3F,0xF1,0x07,0x2F,0x3F,0xE4,0x68,0x2E,0x3F,0xAB,0xCA,0x2D,0x3F,0x46,0x2D,0x2D,0x3F,0xB7,0x90,0x2C,0x3F,0x00,0xF5,0x2B,0x3F,0x22,0x5A,0x2B,0x3F,0x20,0xC0,0x2A,0x3F,0xFA,0x26,0x2A,0x3F,0xB2,0x8E,0x29,0x3F,0x4A,0xF7,0x28,0x3F,0xC3,0x60,0x28,0x3F,0x1F,0xCB,0x27,0x3F,0x5F,0x36,0x27,0x3F,0x84,0xA2,0x26,0x3F,0x91,0x0F,0x26,0x3F,0x87,0x7D,0x25,0x3F,0x67,0xEC,0x24,0x3F,0x32,0x5C,0x24,0x3F,0xEA,0xCC,0x23,0x3F,0x91,0x3E,0x23,0x3F,0x28,0xB1,0x22,0x3F,0xB1,0x24,0x22,0x3F,0x2C,0x99,0x21,0x3F,0x9B,0x0E,0x21,0x3F,0x01,0x85,0x20,0x3F,0x5D,0xFC,0x1F,0x3F,0xB1,0x74,0x1F,0x3F,0x00,0xEE,0x1E,0x3F,0x49,0x68,0x1E,0x3F,0x8F,0xE3,0x1D,0x3F,0xD3,0x5F,0x1D,0x3F,0x16,0xDD,0x1C,0x3F,0x59,0x5B,0x1C,0x3F,0x9F,0xDA,0x1B,0x3F,0xE7,0x5A,0x1B,0x3F,0x34,0xDC,0x1A,0x3F,0x86,0x5E,0x1A,0x3F,0xE0,0xE1,0x19,0x3F,0x41,0x66,0x19,0x3F,0xAC,0xEB,0x18,0x3F,0x22,0x72,0x18,0x3F,0xA4,0xF9,0x17,0x3F,0x32,0x82,0x17,0x3F,0xD0,0x0B,0x17,0x3F,0x7C,0x96,0x16,0x3F,0x3A,0x22,0x16,0x3F,0x09,0xAF,0x15,0x3F,0xEB,0x3C,0x15,0x3F,0xE2,0xCB,0x14,0x3F,0xEE,0x5B,0x14,0x3F,0x10,0xED,0x13,0x3F,0x4A,0x7F,0x13,0x3F,0x9D,0x12,0x13,0x3F,0x0A,0xA7,0x12,0x3F,0x91,0x3C,0x12,0x3F,0x35,0xD3,0x11,0x3F,0xF5,0x6A,0x11,0x3F,0xD4,0x03,0x11,0x3F,0xD2,0x9D,0x10,0x3F,0xF0,0x38,0x10,0x3F,0x2F,0xD5,0x0F,0x3F,0x90,0x72,0x0F,0x3F,0x15,0x11,0x0F,0x3F,0xBE,0xB0,0x0E,0x3F,0x8C,0x51,0x0E,0x3F,0x80,0xF3,0x0D,0x3F,0x9B,0x96,0x0D,0x3F,0xDE,0x3A,0x0D,0x3F,0x4A,0xE0,0x0C,0x3F,0xE0,0x86,0x0C,0x3F,0xA1,0x2E,0x0C,0x3F,0x8D,0xD7,0x0B,0x3F,0xA6,0x81,0x0B,0x3F,0xEC,0x2C,0x0B,0x3F,0x61,0xD9,0x0A,0x3F,0x04,0x87,0x0A,0x3F,0xD8,0x35,0x0A,0x3F,0xDC,0xE5,0x09,0x3F,0x12,0x97,0x09,0x3F,0x7A,0x49,0x09,0x3F,0x16,0xFD,0x08,0x3F,0xE5,0xB1,0x08,0x3F,0xE9,0x67,0x08,0x3F,0x22,0x1F,0x08,0x3F,0x92,0xD7,0x07,0x3F,0x38,0x91,0x07,0x3F,0x16,0x4C,0x07,0x3F,0x2D,0x08,0x07,0x3F,0x7C,0xC5,0x06,0x3F,0x05,0x84,0x06,0x3F,0xC8,0x43,0x06,0x3F,0xC6,0x04,0x06,0x3F,0x00,0xC7,0x05,0x3F,0x76,0x8A,0x05,0x3F,0x29,0x4F,0x05,0x3F,0x19,0x15,0x05,0x3F,0x47,0xDC,0x04,0x3F,0xB4,0xA4,0x04,0x3F,0x60,0x6E,0x04,0x3F,0x4C,0x39,0x04,0x3F,0x78,0x05,0x04,0x3F,0xE4,0xD2,0x03,0x3F,0x92,0xA1,0x03,0x3F,0x82,0x71,0x03,0x3F,0xB4,0x42,0x03,0x3F,0x29,0x15,0x03,0x3F,0xE1,0xE8,0x02,0x3F,0xDD,0xBD,0x02,0x3F,0x1C,0x94,0x02,0x3F,0xA0,0x6B,0x02,0x3F,0x69,0x44,0x02,0x3F,0x78,0x1E,0x02,0x3F,0xCC,0xF9,0x01,0x3F,0x66,0xD6,0x01,0x3F,0x47,0xB4,0x01,0x3F,0x6E,0x93,0x01,0x3F,0xDC,0x73,0x01,0x3F,0x92,0x55,0x01,0x3F,0x8F,0x38,0x01,0x3F,0xD5,0x1C,0x01,0x3F,0x63,0x02,0x01,0x3F,0x39,0xE9,0x00,0x3F,0x58,0xD1,0x00,0x3F,0xC1,0xBA,0x00,0x3F,0x72,0xA5,0x00,0x3F,0x6D,0x91,0x00,0x3F,0xB2,0x7E,0x00,0x3F,0x40,0x6D,0x00,0x3F,0x19,0x5D,0x00,0x3F,0x3C,0x4E,0x00,0x3F,0xA9,0x40,0x00,0x3F,0x61,0x34,0x00,0x3F,0x63,0x29,0x00,0x3F,0xB0,0x1F,0x00,0x3F,0x48,0x17,0x00,0x3F,0x2B,0x10,0x00,0x3F,0x59,0x0A,0x00,0x3F,0xD2,0x05,0x00,0x3F,0x96,0x02,0x00,0x3F,0xA6,0x00,0x00,0x3F,0x00,0x00,0x00,0x3F,0xA6,0x00,0x00,0x3F,0x96,0x02,0x00,0x3F,0xD2,0x05,0x00,0x3F,0x59,0x0A,0x00,0x3F,0x2B,0x10,0x00,0x3F,0x48,0x17,0x00,0x3F,0xB0,0x1F,0x00,0x3F,0x63,0x29,0x00,0x3F,0x81,0x7E,0x03,0xCC,0x00,0x04,0x00,0x00,0xF1,0x00,0xF7,0x02,0x61,0x34,0x00,0x3F,0xA9,0x40,0x00,0x3F,0x3C,0x4E,0x00,0x3F,0x19,0x5D,0x00,0x3F,0x40,0x6D,0x00,0x3F,0xB2,0x7E,0x00,0x3F,0x6D,0x91,0x00,0x3F,0x72,0xA5,0x00,0x3F,0xC0,0xBA,0x00,0x3F,0x58,0xD1,0x00,0x3F,0x39,0xE9,0x00,0x3F,0x63,0x02,0x01,0x3F,0xD5,0x1C,0x01,0x3F,0x8F,0x38,0x01,0x3F,0x92,0x55,0x01,0x3F,0xDC,0x73,0x01,0x3F,0x6E,0x93,0x01,0x3F,0x46,0xB4,0x01,0x3F,0x66,0xD6,0x01,0x3F,0xCC,0xF9,0x01,0x3F,0x78,0x1E,0x02,0x3F,0x69,0x44,0x02,0x3F,0xA0,0x6B,0x02,0x3F,0x1C,0x94,0x02,0x3F,0xDC,0xBD,0x02,0x3F,0xE1,0xE8,0x02,0x3F,0x29,0x15,0x03,0x3F,0xB4,0x42,0x03,0x3F,0x82,0x71,0x03,0x3F,0x92,0xA1,0x03,0x3F,0xE4,0xD2,0x03,0x3F,0x77,0x05,0x04,0x3F,0x4B,0x39,0x04,0x3F,0x60,0x6E,0x04,0x3F,0xB4,0xA4,0x04,0x3F,0x47,0xDC,0x04,0x3F,0x19,0x15,0x05,0x3F,0x28,0x4F,0x05,0x3F,0x75,0x8A,0x05,0x3F,0xFF,0xC6,0x05,0x3F,0xC6,0x04,0x06,0x3F,0xC7,0x43,0x06,0x3F,0x04,0x84,0x06,0x3F,0x7B,0xC5,0x06,0x3F,0x2C,0x08,0x07,0x3F,0x16,0x4C,0x07,0x3F,0x38,0x91,0x07,0x3F,0x91,0xD7,0x07,0x3F,0x22,0x1F,0x08,0x3F,0xE8,0x67,0x08,0x3F,0xE5,0xB1,0x08,0x3F,0x15,0xFD,0x08,0x3F,0x7A,0x49,0x09,0x3F,0x12,0x97,0x09,0x3F,0xDC,0xE5,0x09,0x3F,0xD7,0x35,0x0A,0x3F,0x04,0x87,0x0A,0x3F,0x60,0xD9,0x0A,0x3F,0xEC,0x2C,0x0B,0x3F,0xA5,0x81,0x0B,0x3F,0x8D,0xD7,0x0B,0x3F,0xA0,0x2E,0x0C,0x3F,0xE0,0x86,0x0C,0x3F,0x4A,0xE0,0x0C,0x3F,0xDD,0x3A,0x0D,0x3F,0x9A,0x96,0x0D,0x3F,0x7F,0xF3,0x0D,0x3F,0x8B,0x51,0x0E,0x3F,0xBD,0xB0,0x0E,0x3F,0x14,0x11,0x0F,0x3F,0x90,0x72,0x0F,0x3F,0x2E,0xD5,0x0F,0x3F,0xEF,0x38,0x10,0x3F,0xD1,0x9D,0x10,0x3F,0xD3,0x03,0x11,0x3F,0xF5,0x6A,0x11,0x3F,0x34,0xD3,0x11,0x3F,0x91,0x3C,0x12,0x3F,0x09,0xA7,0x12,0x3F,0x9C,0x12,0x13,0x3F,0x4A,0x7F,0x13,0x3F,0x10,0xED,0x13,0x3F,0xED,0x5B,0x14,0x3F,0xE1,0xCB,0x14,0x3F,0xEB,0x3C,0x15,0x3F,0x08,0xAF,0x15,0x3F,0x39,0x22,0x16,0x3F,0x7B,0x96,0x16,0x3F,0xCF,0x0B,0x17,0x3F,0x32,0x82,0x17,0x3F,0xA3,0xF9,0x17,0x3F,0x21,0x72,0x18,0x3F,0xAB,0xEB,0x18,0x3F,0x40,0x66,0x19,0x3F,0xDF,0xE1,0x19,0x3F,0x85,0x5E,0x1A,0x3F,0x33,0xDC,0x1A,0x3F,0xE6,0x5A,0x1B,0x3F,0x9E,0xDA,0x1B,0x3F,0x58,0x5B,0x1C,0x3F,0x15,0xDD,0x1C,0x3F,0xD2,0x5F,0x1D,0x3F,0x8E,0xE3,0x1D,0x3F,0x48,0x68,0x1E,0x3F,0xFF,0xED,0x1E,0x3F,0xB0,0x74,0x1F,0x3F,0x5C,0xFC,0x1F,0x3F,0x00,0x85,0x20,0x3F,0x9B,0x0E,0x21,0x3F,0x2B,0x99,0x21,0x3F,0xB0,0x24,0x22,0x3F,0x27,0xB1,0x22,0x3F,0x90,0x3E,0x23,0x3F,0xE9,0xCC,0x23,0x3F,0x31,0x5C,0x24,0x3F,0x66,0xEC,0x24,0x3F,0x86,0x7D,0x25,0x3F,0x90,0x0F,0x26,0x3F,0x83,0xA2,0x26,0x3F,0x5E,0x36,0x27,0x3F,0x1E,0xCB,0x27,0x3F,0xC2,0x60,0x28,0x3F,0x49,0xF7,0x28,0x3F,0xB1,0x8E,0x29,0x3F,0xF9,0x26,0x2A,0x3F,0x1F,0xC0,0x2A,0x3F,0x21,0x5A,0x2B,0x3F,0xFF,0xF4,0x2B,0x3F,0xB6,0x90,0x2C,0x3F,0x45,0x2D,0x2D,0x3F,0xAA,0xCA,0x2D,0x3F,0xE3,0x68,0x2E,0x3F,0xF0,0x07,0x2F,0x3F,0xCF,0xA7,0x2F,0x3F,0x7D,0x48,0x30,0x3F,0xF9,0xE9,0x30,0x3F,0x42,0x8C,0x31,0x3F,0x56,0x2F,0x32,0x3F,0x34,0xD3,0x32,0x3F,0xD9,0x77,0x33,0x3F,0x44,0x1D,0x34,0x3F,0x73,0xC3,0x34,0x3F,0x65,0x6A,0x35,0x3F,0x18,0x12,0x36,0x3F,0x8B,0xBA,0x36,0x3F,0xBA,0x63,0x37,0x3F,0xA6,0x0D,0x38,0x3F,0x4C,0xB8,0x38,0x3F,0xAA,0x63,0x39,0x3F,0xBF,0x0F,0x3A,0x3F,0x89,0xBC,0x3A,0x3F,0x06,0x6A,0x3B,0x3F,0x35,0x18,0x3C,0x3F,0x13,0xC7,0x3C,0x3F,0x9F,0x76,0x3D,0x3F,0xD8,0x26,0x3E,0x3F,0xBA,0xD7,0x3E,0x3F,0x46,0x89,0x3F,0x3F,0x78,0x3B,0x40,0x3F,0x4F,0xEE,0x40,0x3F,0xC9,0xA1,0x41,0x3F,0xE5,0x55,0x42,0x3F,0xA0,0x0A,0x43,0x3F,0xF8,0xBF,0x43,0x3F,0xED,0x75,0x44,0x3F,0x7C,0x2C,0x45,0x3F,0xA3,0xE3,0x45,0x3F,0x60,0x9B,0x46,0x3F,0xB2,0x53,0x47,0x3F,0x96,0x0C,0x48,0x3F,0x0C,0xC6,0x48,0x3F,0x10,0x80,0x49,0x3F,0xA1,0x3A,0x4A,0x3F,0xBD,0xF5,0x4A,0x3F,0x62,0xB1,0x4B,0x3F,0x8F,0x6D,0x4C,0x3F,0x41,0x2A,0x4D,0x3F,0x77,0xE7,0x4D,0x3F,0x2E,0xA5,0x4E,0x3F,0x65,0x63,0x4F,0x3F,0x1A,0x22,0x50,0x3F,0x4B,0xE1,0x50,0x3F,0xF5,0xA0,0x51,0x3F,0x18,0x61,0x52,0x3F,0xB0,0x21,0x53,0x3F,0xBD,0xE2,0x53,0x3F,0x3C,0xA4,0x54,0x3F,0x2B,0x66,0x55,0x3F,0x88,0x28,0x56,0x3F,0x51,0xEB,0x56,0x3F,0x85,0xAE,0x57,0x3F,0x21,0x72,0x58,0x3F,0x23,0x36,0x59,0x3F,0x8A,0xFA,0x59,0x3F,0x53,0xBF,0x5A,0x3F,0x7C,0x84,0x5B,0x3F,0x04,0x4A,0x5C,0x3F,0xE8,0x0F,0x5D,0x3F,0x27,0xD6,0x5D,0x3F,0xBE,0x9C,0x5E,0x3F,0xAB,0x63,0x5F,0x3F,0xED,0x2A,0x60,0x3F,0x81,0xF2,0x60,0x3F,0x66,0xBA,0x61,0x3F,0x99,0x82,0x62,0x3F,0x18,0x4B,0x63,0x3F,0xE1,0x13,0x64,0x3F,0xF3,0xDC,0x64,0x3F,0x4A,0xA6,0x65,0x3F,0xE6,0x6F,0x66,0x3F,0xC5,0x39,0x67,0x3F,0xE3,0x03,0x68,0x3F,0x3F,0xCE,0x68,0x3F,0xD7,0x98,0x69,0x3F,0xAA,0x63,0x6A,0x3F,0xB4,0x2E,0x6B,0x3F,0xF4,0xF9,0x6B,0x3F,0x68,0xC5,0x6C,0x3F,0x0D,0x91,0x6D,0x3F,0xE2,0x5C,0x6E,0x3F,0xE5,0x28,0x6F,0x3F,0x14,0xF5,0x6F,0x3F,0x6C,0xC1,0x70,0x3F,0xEB,0x8D,0x71,0x3F,0x90,0x5A,0x72,0x3F,0x58,0x27,0x73,0x3F,0x41,0xF4,0x73,0x3F,0x4A,0xC1,0x74,0x3F,0x6F,0x8E,0x75,0x3F,0xB0,0x5B,0x76,0x3F,0x0A,0x29,0x77,0x3F,0x7A,0xF6,0x77,0x3F,0xFF,0xC3,0x78,0x3F,0x97,0x91,0x79,0x3F,0x40,0x5F,0x7A,0x3F,0xF7,0x2C,0x7B,0x3F,0xBB,0xFA,0x7B,0x3F,0x89,0xC8,0x7C,0x3F,0x5F,0x96,0x7D,0x3F,0x3C,0x64,0x7E,0x3F,0x1C,0x32,0x7F,0x3F,
0x01,0xFE,0x0A,0x00,0x04,0x01,0x01,0x00,0x00,0x20,0x42,0xE8,0x00,
0x01,0xFE,0x03,0x00,0x04,0x02,
0x01,0xFE,0x03,0x00,0x02,0x01,
0x01,0xFE,0x00
};
    uint16_t i = 0,num = 0;
    frame_handler frame;

    if(frame_init(&frame,2,1024+4) < 0){printf("Failed to initialize...\n");return;}
    frame_identify_add(&frame,0x01);
    frame_identify_add(&frame,0x81);

    for(i = 0;i < BufferSize;i++)
    {
        if(frame_find(&frame,buf[i]) < 0)continue;
        frame_data_printf(frame.data_rx);
		num++;
		printf("\r\n\n\n");
    }
	printf("num=%d\r\n",num);
    frame_DeInit(&frame);
}

**********************************************************************/
#include "frame_driver.h"
#include "stdlib.h"
#include "string.h"

static int frame_identify_find(Frame_Identify_StructDef identify, uint8_t id);

/****************************************
@function:匹配帧标识符集合
@param:identify--标识符集合
	id--待匹配的标识符
@return:-1--失败,0--成功
@note:
****************************************/
static int frame_identify_find(Frame_Identify_StructDef identify, uint8_t id)
{
	uint8_t i = 0;

	for (i = 0; i < identify.pos; i++)
	{
		if (identify.pbuf[i] == id)return 0;
	}
	return -1;
}

/****************************************
@function:帧资源初始化
@param:p--帧句柄
	number--帧种类数,范围[1,255]
	rx_size--帧接收缓冲区字节数,等于最大帧长度,范围[4,uint32_t]
@return:
	0--成功
	-1:参数错误
	-2:内存分配失败
@note:
****************************************/
int frame_init(frame_handler *p, uint8_t number, uint32_t rx_size)
{
	if ((p == NULL) || (number == 0) || (rx_size < 4))return -1;
	p->state = 0;
	p->identify.pbuf = (uint8_t *)malloc(number);
	if (p->identify.pbuf == NULL)
	{
		dFrame_LOG("Error[%s-line:%d]:memory allocation failure\n", __func__, __LINE__);
		return -2;
	}
	p->identify.number = number;
	p->identify.pos = 0;

	p->rx.pbuf = (uint8_t *)malloc(rx_size);
	if (p->rx.pbuf == NULL)
	{
		frame_DeInit(p);
		dFrame_LOG("Error[%s-line:%d]:memory allocation failure\n", __func__, __LINE__);
		return -2;
	}
	p->rx.size = rx_size;
	p->rx.pos = 0;

	p->data_rx.state = eFrame_State_ID;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;

	p->state = 1;
	return 0;
}

/****************************************
@function:帧资源销毁
@param:p--帧句柄
@return:void
@note:
****************************************/
void frame_DeInit(frame_handler *p)
{
	if (p == NULL)return;
	p->state = 0;
	if (p->identify.pbuf != NULL)free(p->identify.pbuf);
	p->identify.pbuf = NULL;
	p->identify.number = 0;
	p->identify.pos = 0;
	if (p->rx.pbuf != NULL)free(p->rx.pbuf);
	p->rx.pbuf = NULL;
	p->rx.size = 0;
	p->rx.pos = 0;

	p->data_rx.state = eFrame_State_ID;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;
}

/****************************************
@function:添加待查找的帧标识
@param:p--帧句柄
	identify--帧标识
		格式规定:
		帧标识	类型	备注
		A<=0x80	短帧	数据长度1字节
		A>0x80	长帧	数据长度2字节

		短帧:帧标识 帧标识取反 数据字节数 数据...数据
		长帧:帧标识 帧标识取反 数据字节数(高8位) 数据字节数(低8位) 数据...数据
@return:
	0:成功
	-1--参数错误
	-2:添加失败
@note:添加重复帧标识无效
****************************************/
int frame_identify_add(frame_handler *p, uint8_t identify)
{
	uint8_t i = 0;
	if (p == NULL)return -1;
	if (p->state == 0)return -1;
	if (p->identify.pos >= p->identify.number)return -2;
	while (i < p->identify.pos)
	{
		if (p->identify.pbuf[i++] == identify)return -2;
	}
	p->identify.pbuf[p->identify.pos++] = identify;
	return 0;
}

/****************************************
@function:数据接收并匹配帧集合
@param:p--帧句柄
	data--新数据
@return:
	0:识别到帧数据,数据信息查看p->data_rx结构体
	-1:参数异常|帧未初始化
	-2:检索ID阶段
	-3:检索帧数据字节数阶段
	-4:数据接收阶段
	-5:帧数据为0字节(空帧)
	-6:接收缓冲区空间不足,原因:初始化的帧资源大小低于帧总长度
@note:
****************************************/
int frame_find(frame_handler *p, uint8_t data)
{
	uint16_t len = 0;
	if (p == NULL)return -1;
	if (p->state == 0)return -1;
	if (p->identify.pos == 0)return -1;//没有待识别的帧标识 

	if(p->rx.pos >= p->rx.size)//超过接收帧创建长度
	{
		p->rx.pos = 0;
		p->data_rx.state = eFrame_State_ID;
		return -6;
	}
	p->rx.pbuf[p->rx.pos++] = data;

	switch (p->data_rx.state)
	{
		case eFrame_State_ID:
		{
			if(p->rx.pos < 2)return -2;
			if ((p->rx.pbuf[p->rx.pos - 2] != dIdentify_Invert(p->rx.pbuf[p->rx.pos - 1]))\
				|| (frame_identify_find(p->identify,p->rx.pbuf[p->rx.pos - 2]) != 0)
			)//帧标识不对
			{
				//数据移除1字节
				memmove((void *)(&(p->rx.pbuf[p->rx.pos - 2])),(void *)(&(p->rx.pbuf[p->rx.pos - 1])),1);
				p->rx.pos--;
				return -2;
			}

			p->data_rx.state = eFrame_State_Bytes;
			return -3;
		}
		case eFrame_State_Bytes:
		{
			if(p->rx.pbuf[0] <= 0x80)//短帧
			{
				if(p->rx.pbuf[p->rx.pos - 1] == 0)//帧数据字节数为0
				{
					p->rx.pos = 0;
					p->data_rx.state = eFrame_State_ID;
					return -5;
				}

				p->data_rx.identify = p->rx.pbuf[0];
				p->data_rx.size = p->rx.pbuf[p->rx.pos - 1];
				p->data_rx.pbuf = &(p->rx.pbuf[p->rx.pos]);
				p->data_rx.state = eFrame_State_Receive;
				return -4;
			}

			//长帧
			if(p->rx.pos < 4)return -3;
			len = dDataLength_Merge(p->rx.pbuf[p->rx.pos - 2], p->rx.pbuf[p->rx.pos - 1]);
			if(len == 0)//帧数据字节数为0
			{
				p->rx.pos = 0;
				p->data_rx.state = eFrame_State_ID;
				return -5;
			}

			p->data_rx.identify = p->rx.pbuf[0];
			p->data_rx.size = len;
			p->data_rx.pbuf = &(p->rx.pbuf[p->rx.pos]);
			p->data_rx.state = eFrame_State_Receive;
			return -4;
		}
		case eFrame_State_Receive:
		{
			len = (p->data_rx.identify > 0x80) ? (p->rx.pos - 4) : (p->rx.pos - 3);
			if(len < p->data_rx.size)return -4;

			p->rx.pos = 0;
			p->data_rx.state = eFrame_State_ID;
			return 0;
		}
	}
	return -1;
}

/****************************************
@function:帧查找器清空
@param:p--帧句柄
@return:void
@note:
****************************************/
int frame_find_clear(frame_handler *p)
{
	if (p == NULL)return -1;
	if (p->state == 0)return -1;

	p->rx.pos = 0;
	p->data_rx.state = eFrame_State_ID;
	p->data_rx.identify = 0;
	p->data_rx.size = 0;
	p->data_rx.pbuf = NULL;
	return 0;
}

/****************************************
@function:帧接收信息打印
@param:data--接收到的帧数据
@return:void
@note:
****************************************/
void frame_data_printf(Frame_Data_StructDef data)
{
	uint32_t i = 0;

	dFrame_LOG("Identify=0x%0X size=%d", data.identify, data.size);
	for (i = 0; i < data.size; i++)
	{
		if (i == 0)dFrame_LOG(" data{0x%0x", data.pbuf[i]);
		else dFrame_LOG(",0x%0x", data.pbuf[i]);
	}
	if (i != 0)dFrame_LOG("}\n");
	else dFrame_LOG("\n");
}

/****************************************
@function:生成帧格式
@param:identify--帧标识符
	size--帧用户数据字节数,不能为0
	pbuf--帧缓冲区,生成的帧数据放置在此缓冲区,起始位置pbuf[0]
@return:
	NULL:生成失败,参数错误
	!NULL:帧用户数据起始地址
@note:
	注意生成的帧总长度为:
	短帧(identify <= 0x80):(size+3)字节
	长帧(identify > 0x80):(size+4)字节
	此函数会清0缓冲区
****************************************/
uint8_t *frame_format_generate(uint8_t identify, uint32_t size, uint8_t *pbuf)
{
	if ((pbuf == NULL) || (size < 1))return NULL;
	memset(pbuf, 0, (size + ((identify > 0x80) ? 4 : 3)));
	pbuf[0] = identify;
	pbuf[1] = dIdentify_Invert(identify);
	if (identify > 0x80)
	{
		pbuf[2] = dDataLength_MSB(size);
		pbuf[3] = dDataLength_LSB(size);
		return &pbuf[4];
	}
	pbuf[2] = size;
	return (&pbuf[3]);
}

在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值