只需要输入帧头、帧长度、校验起始字节、结束字节、定义帧字段结构体,解析一帧数据。linux,keil开发通用!!!!
ParseProtocol.h
#ifndef _BSB_HEADER
#define _BSB_HEADER
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define ERRORLOG(msg) \
do \
{ \
printf("%s:%s:%d\n", __FILE__, __func__, __LINE__); \
perror(msg); \
} while (0);
/*
function: 实现动态数组存储协议帧解析协议
author: mass
day:2024-11-19
*/
#define FRAME_HEADER 0x90EB // 帧头
#define FRAME_SIZE 145 // 每帧数据的大小
#define CHECK_BEGIN 0 //校验区起始字节
#define CHECK_END 89 //校验区结束字节,即校验4-78字节
#define CHECK_SUM_BEGIN 90 //校验字段起始字节(无符号16位校验和)
#define INITIAL_CAPACITY 256 // 初始容量,不能为0
// 动态数组结构
typedef struct
{
char *buffer; // 指向动态分配的数组
size_t size; // 数组中当前元素的数量
size_t capacity; // 数组的总容量
} DynamicArray;
void initArray(DynamicArray *a);
void freeArray(DynamicArray *a);
void ensureCapacity(DynamicArray *a, size_t additionalSize);
void addData(DynamicArray *a, const char *data, size_t dataSize);
void removeFrame(DynamicArray *a, size_t frameSize);
int check_sum(char *buf);
/********************************bsb******************************************************************/
typedef signed char bsb_int8_t;
typedef unsigned char bsb_uint8_t;
typedef short bsb_int16_t;
typedef unsigned short bsb_uint16_t;
typedef int bsb_int32_t;
typedef unsigned int bsb_uint32_t;
typedef long long bsb_int64_t;
typedef unsigned long long bsb_uint64_t;
/* Private data structure */
typedef struct bsb
{
unsigned char *buf;
unsigned char *ptr;
unsigned char *end;
} BSB;
// 注意:这里使用unsigned char指向char类型的buff存、取数据时并不会出错,因为bit位值没变。
// 例:
// 无论怎么强转,内存中的位数据保持不会改变,x有无符号均可以,初始化的buf同样道理
// unsigned int a=-8;
// printf("%u\n",a);//4294967288
// int b=(unsigned int)-8;
// printf("%d\n",b);//-8
// 初始化
#define BSB_INIT(b, buffer, size) \
do \
{ \
(b).buf = (unsigned char *)buffer; \
(b).ptr = (unsigned char *)buffer; \
int s = (int)size; \
if ((buffer == NULL) || (s < 0)) \
(b).end = 0; \
else \
(b).end = (unsigned char *)buffer + size; \
} while (0)
// 错误处理
#define BSB_SET_ERROR(b) ((b).end = NULL)
// 已写/取的buf长度
#define BSB_LENGTH(b) ((b).ptr - (b).buf)
// 剩余长度
#define BSB_REMAINING(b) ((b).end ? (b).end - (b).ptr : 0)
#define BSB_WORK_PTR(b) ((b).ptr)
/************************************************从bsb.buf取字节********************************************/
#define BSB_IMPORT_u08(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 1 <= (b).end) \
{ \
x = *(((b).ptr)++); \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_IMPORT_u16(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 2 <= (b).end) \
{ \
x = ((bsb_uint16_t)((b).ptr)[0]) << 8 | ((bsb_uint16_t)((b).ptr)[1]); \
(b).ptr += 2; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_IMPORT_u24(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 3 <= (b).end) \
{ \
x = ((bsb_uint32_t)((b).ptr)[0]) << 16 | ((bsb_uint32_t)((b).ptr)[1]) << 8 | \
((bsb_uint32_t)((b).ptr)[2]); \
(b).ptr += 3; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_IMPORT_u32(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 4 <= (b).end) \
{ \
x = ((bsb_uint32_t)((b).ptr)[0]) << 24 | ((bsb_uint32_t)((b).ptr)[1]) << 16 | \
((bsb_uint32_t)((b).ptr)[2]) << 8 | ((bsb_uint32_t)((b).ptr)[3]); \
(b).ptr += 4; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_IMPORT_u64(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 8 <= (b).end) \
{ \
x = ((bsb_uint64_t)((b).ptr)[0]) << 56 | ((bsb_uint64_t)((b).ptr)[1]) << 48 | \
((bsb_uint64_t)((b).ptr)[2]) << 40 | ((bsb_uint64_t)((b).ptr)[3]) << 32 | \
((bsb_uint64_t)((b).ptr)[4]) << 24 | ((bsb_uint64_t)((b).ptr)[5]) << 16 | \
((bsb_uint64_t)((b).ptr)[6]) << 8 | ((bsb_uint64_t)((b).ptr)[7]); \
(b).ptr += 8; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
// 取size字节到x(buff)中
#define BSB_IMPORT_byte(b, x, size) \
do \
{ \
if ((b).ptr + size <= (b).end) \
{ \
memcpy(x, b.ptr, size); \
(b).ptr += size; \
} \
else \
{ \
BSB_SET_ERROR(b); \
} \
} while (0)
// 前者基础上, 若buf越界,结尾赋值0
#define BSB_IMPORT_zbyte(b, x, size) \
do \
{ \
if ((b).ptr + size <= (b).end) \
{ \
memcpy(x, b.ptr, size); \
(x)[size] = 0; \
(b).ptr += size; \
} \
else \
{ \
BSB_SET_ERROR(b); \
(x)[0] = 0; \
} \
} while (0)
/********************************************以小端字节序取字节*********************************************/
#define BSB_LIMPORT_u08(b, x) BSB_IMPORT_u08(b, x)
#define BSB_LIMPORT_u16(b, x) \
do \
{ \
if ((b).ptr + 2 <= (b).end) \
{ \
x = ((bsb_uint16_t)((b).ptr)[1]) << 8 | ((bsb_uint16_t)((b).ptr)[0]); \
(b).ptr += 2; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_LIMPORT_u24(b, x) \
do \
{ \
if ((b).ptr + 3 <= (b).end) \
{ \
x = ((bsb_uint32_t)((b).ptr)[2]) << 16 | ((bsb_uint32_t)((b).ptr)[1]) << 8 | \
((bsb_uint32_t)((b).ptr)[0]); \
(b).ptr += 3; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_LIMPORT_u32(b, x) \
do \
{ \
if ((b).ptr + 4 <= (b).end) \
{ \
x = ((bsb_uint32_t)((b).ptr)[3]) << 24 | ((bsb_uint32_t)((b).ptr)[2]) << 16 | \
((bsb_uint32_t)((b).ptr)[1]) << 8 | ((bsb_uint32_t)((b).ptr)[0]); \
(b).ptr += 4; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_LIMPORT_u64(b, x) \
do \
{ \
if ((b).ptr + 8 <= (b).end) \
{ \
x = ((bsb_uint64_t)((b).ptr)[7]) << 56 | ((bsb_uint64_t)((b).ptr)[6]) << 48 | \
((bsb_uint64_t)((b).ptr)[5]) << 40 | ((bsb_uint64_t)((b).ptr)[4]) << 32 | \
((bsb_uint64_t)((b).ptr)[3]) << 24 | ((bsb_uint64_t)((b).ptr)[2]) << 16 | \
((bsb_uint64_t)((b).ptr)[1]) << 8 | ((bsb_uint64_t)((b).ptr)[0]); \
(b).ptr += 8; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
/************************************************向bsb.buf中写入字节********************************************/
// 给定一个空buff,向buff中写,b.buf为写好的
#define BSB_EXPORT_u08(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 1 <= (b).end) \
{ \
*(((b).ptr)++) = (char)x; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_EXPORT_u16(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 2 <= (b).end) \
{ \
bsb_uint16_t t = (bsb_uint16_t)x; \
*(((b).ptr)++) = (t & 0xff00) >> 8; \
*(((b).ptr)++) = (t & 0x00ff); \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_EXPORT_u24(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 3 <= (b).end) \
{ \
bsb_uint32_t t = x; \
*(((b).ptr)++) = (t & 0x00ff0000) >> 16; \
*(((b).ptr)++) = (t & 0x0000ff00) >> 8; \
*(((b).ptr)++) = (t & 0x000000ff); \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_EXPORT_u32(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 4 <= (b).end) \
{ \
bsb_uint32_t t = x; \
*(((b).ptr)++) = (t & 0xff000000) >> 24; \
*(((b).ptr)++) = (t & 0x00ff0000) >> 16; \
*(((b).ptr)++) = (t & 0x0000ff00) >> 8; \
*(((b).ptr)++) = (t & 0x000000ff); \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_EXPORT_u40(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 5 <= (b).end) \
{ \
bsb_uint64_t t = x; \
*(((b).ptr)++) = (t & 0xff00000000) >> 32; \
*(((b).ptr)++) = (t & 0x00ff000000) >> 24; \
*(((b).ptr)++) = (t & 0x0000ff0000) >> 16; \
*(((b).ptr)++) = (t & 0x000000ff00) >> 8; \
*(((b).ptr)++) = (t & 0x00000000ff); \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_EXPORT_u64(b, x) \
do \
{ \
if ((b).ptr && (b).ptr + 8 <= (b).end) \
{ \
bsb_uint64_t t = x; \
*(((b).ptr)++) = (t & 0xff00000000000000) >> 56; \
*(((b).ptr)++) = (t & 0x00ff000000000000) >> 48; \
*(((b).ptr)++) = (t & 0x0000ff0000000000) >> 40; \
*(((b).ptr)++) = (t & 0x000000ff00000000) >> 32; \
*(((b).ptr)++) = (t & 0x00000000ff000000) >> 24; \
*(((b).ptr)++) = (t & 0x0000000000ff0000) >> 16; \
*(((b).ptr)++) = (t & 0x000000000000ff00) >> 8; \
*(((b).ptr)++) = (t & 0x00000000000000ff); \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
// 从x中写入size字节到bsb.buf中
#define BSB_EXPORT_ptr(b, x, size) \
do \
{ \
if ((x || size == 0) && (b).ptr + size <= (b).end && \
(b).ptr + size >= (b).buf) \
{ \
memcpy((b).ptr, x, size); \
(b).ptr += size; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
// 前者基础上增加防止写越界
#define BSB_EXPORT_ptr_some(b, x, size) \
do \
{ \
if ((b).ptr + size <= (b).end) \
{ \
memcpy((b).ptr, x, size); \
(b).ptr += size; \
} \
else if (((b).end != NULL)) \
{ \
memcpy((b).ptr, x, BSB_REMAINING(b)); \
(b).ptr += BSB_REMAINING(b); \
} \
} while (0)
// 写字符串
// 例:printf("%d\n",sizeof "hello11");8 写入8-1字节
#define BSB_EXPORT_cstr(b, x) \
do \
{ \
const int size = sizeof x - 1; \
if ((b).ptr + size <= (b).end) \
{ \
memcpy((b).ptr, x, size); \
(b).ptr += size; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
// 格式化写入字节 C9以上标准
// snprintf返回实际写入到字符串中的字符数(不包括空字符'\0')
#if defined(C9X)
#define BSB_EXPORT_sprintf(b, ...) \
do \
{ \
if ((b).end != 0) \
{ \
int l = snprintf((unsigned char *)(b).ptr, (b).end - (b).ptr, __VA_ARGS__); \
if (l <= (b).end - (b).ptr) \
{ \
(b).ptr += l; \
} \
else \
{ \
BSB_SET_ERROR(b); \
} \
} \
} while (0)
#else
// 格式化写字节
/*eg:
//BSB_EXPORT_sprintf(bsb, "hello%s,%d:%d:", "world",100,200);
//printf("%s\n", bsb.buf);
//helloworld,100:200:
*/
#define BSB_EXPORT_sprintf(b, args...) \
do \
{ \
if ((b).end != 0) \
{ \
int l = snprintf((unsigned char *)(b).ptr, (b).end - (b).ptr, ##args); \
if (l <= (b).end - (b).ptr) \
{ \
(b).ptr += l; \
} \
else \
{ \
BSB_SET_ERROR(b); \
} \
} \
} while (0)
#endif
// 写ipv4/ipv6地址
// 例:
// struct in6_addr addr6;
// inet_pton(AF_INET6, "2001:0db8:85a3:0000:0000:8a2e:0370:7334", &addr6);
// BSB_EXPORT_inet_ntop(bsb, AF_INET6, &addr6);
#define BSB_EXPORT_inet_ntop(b, f, s) \
do \
{ \
if ((b).end != 0) \
{ \
const unsigned char *r = inet_ntop(f, s, (unsigned char *)(b).ptr, (b).end - (b).ptr); \
if (r) \
{ \
(b).ptr += strlen(r); \
} \
else \
{ \
BSB_SET_ERROR(b); \
} \
} \
} while (0)
/************************************以小端字节序写入***************************/
#define BSB_LEXPORT_u08(b, x) BSB_EXPORT_u08(b, x)
#define BSB_LEXPORT_u16(b, x) \
do \
{ \
if ((b).ptr + 2 <= (b).end) \
{ \
bsb_uint16_t t = (bsb_uint16_t)x; \
*(((b).ptr)++) = (t & 0x00ff); \
*(((b).ptr)++) = (t & 0xff00) >> 8; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_LEXPORT_u32(b, x) \
do \
{ \
if ((b).ptr + 4 <= (b).end) \
{ \
bsb_uint32_t t = x; \
*(((b).ptr)++) = (t & 0x000000ff); \
*(((b).ptr)++) = (t & 0x0000ff00) >> 8; \
*(((b).ptr)++) = (t & 0x00ff0000) >> 16; \
*(((b).ptr)++) = (t & 0xff000000) >> 24; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
#define BSB_LEXPORT_u64(b, x) \
do \
{ \
if ((b).ptr + 8 <= (b).end) \
{ \
bsb_uint64_t t = x; \
*(((b).ptr)++) = (t & 0x00000000000000ff); \
*(((b).ptr)++) = (t & 0x000000000000ff00) >> 8; \
*(((b).ptr)++) = (t & 0x0000000000ff0000) >> 16; \
*(((b).ptr)++) = (t & 0x00000000ff000000) >> 24; \
*(((b).ptr)++) = (t & 0x000000ff00000000) >> 32; \
*(((b).ptr)++) = (t & 0x0000ff0000000000) >> 40; \
*(((b).ptr)++) = (t & 0x00ff000000000000) >> 56; \
*(((b).ptr)++) = (t & 0xff00000000000000) >> 64; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
/***********************************************************************************************/
// b.ptr前进size字节
#define BSB_EXPORT_skip(b, size) \
do \
{ \
if ((b).ptr + size <= (b).end && (b).ptr + size >= (b).buf) \
{ \
(b).ptr += size; \
if ((b).ptr < (b).buf) \
(b).end = 0; \
} \
else \
BSB_SET_ERROR(b); \
} while (0)
// 后退size字节
#define BSB_EXPORT_rewind(b, size) \
do \
{ \
if ((b).ptr - size <= (b).end && (b).ptr - size >= (b).buf) \
{ \
(b).ptr -= size; \
if ((b).ptr < (b).buf) \
(b).end = 0; \
} \
else \
{ \
BSB_SET_ERROR(b); \
} \
} while (0)
#define BSB_IMPORT_skip BSB_EXPORT_skip
#define BSB_LIMPORT_skip BSB_EXPORT_skip
#define BSB_IMPORT_rewind BSB_EXPORT_rewind
#define BSB_LIMPORT_rewind BSB_EXPORT_rewind
// 浮点型数据读写
#define BSB_IMPORT_double_or_float BSB_IMPORT_byte // 取
#define BSB_EXPORT_double_or_float BSB_EXPORT_ptr // 写
/***********************************************************************************************/
// 指定的内存区域中查找指定字符的第一个匹配位置
// void *memchr(const void *s, int c, size_t n);
/*eg:
BSB bsb1,bsb2;
int pos1,pos2;
char buffer1[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
char buffer2[6] = "hello";
BSB_INIT(bsb1, buffer1, sizeof(buffer1));
BSB_INIT(bsb2, buffer2, sizeof(buffer2));
char ch1 = 0x33;
char ch2 = 'e';
BSB_memchr(bsb1, ch1, pos1);
BSB_memchr(bsb2, ch2, pos2);
printf("position: %d %d\n", pos1,pos2);//2 1
*/
#define BSB_memchr(b, ch, pos) \
do \
{ \
if (((b).end == NULL)) \
{ \
pos = 0; \
break; \
} \
unsigned char *s = memchr((unsigned char *)b.ptr, ch, BSB_REMAINING(b)); \
if (s) \
pos = (unsigned char *)s - (unsigned char *)b.ptr; \
else \
pos = 0; \
} while (0)
// memcmp
// 如果两个内存区域内容相等,则返回0。
// 如果第一个不相等的字节在s1中的值小于s2中的值,则返回一个负值。
// 如果第一个不相等的字节在s1中的值大于s2中的值,则返回一个正值。
// 比较一个str和BSB结构体中的一段内存区域
#define BSB_memcmp(str, b, len) \
((b).ptr + len <= (b).end ? memcmp(str, b.ptr, len) : -1)
// 查看b.ptr指针位置的值,如果当前指针位置不超过结尾位置,则返回当前指针位置的值,否则返回-1。
#define BSB_PEEK(b) ((b).ptr + 1 <= (b).end ? *b.ptr : -1)
#endif
ParseProtocol.c
包含一种接收协议帧方式
#include "ParseProtocol.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
// #include <asm/termbits.h>//自定义波特率头文件
// 需要将<asm/termbits.h>中的struct termios注释掉
#include <time.h>
#define BUFFER_SIZE 1024
// 自定义波特率设置,
// int set_custom_baudrate(const char fd, int baudrate)
// {
// struct termios2 tio;
// // 获取当前串口配置
// if (ioctl(fd, TCGETS2, &tio) != 0)
// {
// perror("ioctl TCGETS2");
// close(fd);
// return -1;
// }
// // 设置自定义波特率
// tio.c_cflag &= ~CBAUD;
// tio.c_cflag |= BOTHER; // 使用自定义波特率标志
// tio.c_ispeed = baudrate; // 设置输入波特率
// tio.c_ospeed = baudrate; // 设置输出波特率
// // 应用新的串口配置
// if (ioctl(fd, TCSETS2, &tio) != 0)
// {
// perror("ioctl TCSETS2");
// close(fd);
// return -1;
// }
// printf("set custom baudrate done! \n");
// return 0;
// }
int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio, oldtio;
if (tcgetattr(fd, &oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero(&newtio, sizeof(newtio));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag = ~CSIZE;
switch (nBits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch (nEvent)
{
case 'O': // 奇校验
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E': // 偶校验
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag = ~PARODD;
break;
case 'N': // 无校验
newtio.c_cflag = ~PARENB;
break;
}
switch (nSpeed)
{
case 300:
cfsetispeed(&newtio, B300);
cfsetospeed(&newtio, B300);
break;
case 600:
cfsetispeed(&newtio, B600);
cfsetospeed(&newtio, B600);
break;
case 1200:
cfsetispeed(&newtio, B1200);
cfsetospeed(&newtio, B1200);
break;
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 19200:
cfsetispeed(&newtio, B19200);
cfsetospeed(&newtio, B19200);
break;
case 38400:
cfsetispeed(&newtio, B38400);
cfsetospeed(&newtio, B38400);
break;
case 57600:
cfsetispeed(&newtio, B57600);
cfsetospeed(&newtio, B57600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
return -2;
break;
}
if (nStop == 1)
{
newtio.c_cflag &= ~CSTOPB;
}
else if (nStop == 2)
{
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(fd, TCIFLUSH);
if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
{
perror("com set error");
return -1;
}
printf("uart inint done!\n");
return 1;
}
// 校验和
int check_sum(char *buf)
{
unsigned short sum = 0;
for (size_t i = CHECK_BEGIN; i <= CHECK_END; i++)
{
sum += buf[i];
}
if (*(unsigned short *)&buf[CHECK_SUM_BEGIN] == sum)
{
return 1;
}
// int sum = 0;
// for (size_t i = CHECK_BEGIN; i <= CHECK_END; i++)
// {
// sum += buf[i];
// }
// printf("%d;%d\n",sum,buf[CHECK_SUM_BEGIN]);
// if (buf[CHECK_SUM_BEGIN] == sum&0x000000ff)
// {
// return 1;
// }
else
{
return 0;
}
}
// 初始化动态数组
void initArray(DynamicArray *a)
{
a->buffer = (char *)malloc(INITIAL_CAPACITY * sizeof(char));
if (a->buffer == NULL)
{
ERRORLOG("malloc error\n");
}
a->size = 0;
a->capacity = INITIAL_CAPACITY;
}
// 释放动态数组
void freeArray(DynamicArray *a)
{
free(a->buffer);
a->buffer = NULL;
a->size = 0;
a->capacity = 0;
}
// 根据缓存数据大小动态扩容数组
// 案例:当串口阻塞时一次性接收数据大于缓存数据的缓冲区大小(>INITIAL_CAPACITY)若不动态扩容,则数据溢出
void ensureCapacity(DynamicArray *a, size_t additionalSize)
{
size_t newCapacity = a->capacity;
while (newCapacity < a->size + additionalSize)
{
newCapacity *= 2;
}
// 这里即使realloc内存小于原来内存,即使用realloc缩容,由于原来内存未释放,仍可以接着用
char *newBuffer = (char *)realloc(a->buffer, newCapacity);
if (newBuffer == NULL)
{
ERRORLOG("Memory realloc error\n");
}
a->buffer = newBuffer;
a->capacity = newCapacity; // 接着使用原来内存大小或新扩容的内存大小
}
// 添加数据到动态数组
void addData(DynamicArray *a, const char *data, size_t dataSize)
{
ensureCapacity(a, dataSize);
memcpy(a->buffer + a->size, data, dataSize);
// printf("a->size1:%ld,dataSize:%ld\n",a->size,dataSize);
a->size += dataSize;
// printf("a->size2:%ld\n",a->size);
}
// 从动态数组中移除一帧数据
void removeFrame(DynamicArray *a, size_t frameSize)
{
if (frameSize > a->size)
{
ERRORLOG("remove frame size is larger than array size\n");
}
memmove(a->buffer, a->buffer + frameSize, a->size - frameSize);
// printf("a->size:%ld\n",a->size);
a->size -= frameSize;
// printf("a->size -:%ld\n",a->size);
}
/*****************方式1解析代码****************************/
#if 1
int main()
{
char *serial_device = "/dev/ttyUSB0";
int baudrate = 115200;
char *output_file_name = "test.txt";
int serial_fd = open(serial_device, O_RDWR | O_NOCTTY | O_NDELAY);
if (serial_fd == -1)
{
perror("Unable to open serial port");
return 1;
}
int setret = 0;
setret = set_opt(serial_fd, baudrate, 8, 'N', 1);
if (setret == -1)
{
close(serial_fd);
perror("set baudrate error\n");
}
// 打开输出文件
FILE *output_file = fopen(output_file_name, "w");
if (!output_file)
{
perror("Unable to open output file");
close(serial_fd);
return 1;
}
fd_set read_fds;
DynamicArray array;
initArray(&array);
char readBuffer[BUFFER_SIZE] = {0}; // 用于每次存储读取的数据
int fre=0;//帧计数,测试
int total=0;//接收总字节数,测试
while (1)
{
FD_ZERO(&read_fds);
FD_SET(serial_fd, &read_fds);
// 使用 select 等待数据
int activity = select(serial_fd + 1, &read_fds, NULL, NULL, NULL);
if (activity < 0)
{
perror("select error");
break;
}
if (FD_ISSET(serial_fd, &read_fds))
{
int bytes_read = read(serial_fd, readBuffer, sizeof(readBuffer));
if (bytes_read > 0)
{
total+=bytes_read;
addData(&array, readBuffer, bytes_read);
memset(readBuffer,0,sizeof(readBuffer));
}
}
while (array.size >= FRAME_SIZE)
{
// 检查数组开头是否为帧头
//if (*(unsigned short *)array.buffer==FRAME_HEADER&&check_sum(array.buffer))
if (*(unsigned short *)array.buffer==FRAME_HEADER)
{
//测试
// BSB bsb;
// BSB_INIT(bsb,array.buffer,FRAME_HEADER);
// BSB_EXPORT_skip(bsb,7);
// unsigned int time=0;
// BSB_LIMPORT_u32(bsb,time);
//fprintf(output_file,"%u\n",time);
/*这里找到一帧完整的数据,进行解析*/
// for (size_t i = 0; i < 7; i++)
// {
// printf("%02X ", array.buffer[i]);
// }
// printf("\n");
fre++;
// 移除这一帧数据
removeFrame(&array, FRAME_SIZE);
}
else
{
// 不是帧头,移除第一个字节(继续从下一个字节开始判断)
removeFrame(&array, 1);
}
}
//printf("array.size: %ld,fre: %d,total: %d\n",array.size,fre,total);
}
//fclose(output_file);
close(serial_fd);
freeArray(&array);
return 0;
}
#endif
/*****************方式二解析代码****************************/
#if 1
// 帧字段
typedef struct
{
unsigned short head;
unsigned short type;
unsigned char Fre_len;
unsigned int Cnt;
unsigned short GPS_week;
double GPS_Seconds;
double Imu_lon;
double Imu_lat;
float Imu_h;
float Att_h;
float Att_p;
float Att_r;
float Vel_e;
float Vel_n;
float Vel_u;
float Meter;
float Deviation;
float BiasX;
float BiasY;
unsigned short check_sum;
unsigned short tail;
} Fre;
int main()
{
char *serial_device = "/dev/ttyUSB0";
int baudrate = 115200;
char *output_file_name = "test.txt";
int serial_fd = open(serial_device, O_RDWR | O_NOCTTY | O_NDELAY);
if (serial_fd == -1)
{
perror("Unable to open serial port");
return 1;
}
int setret = 0;
setret = set_opt(serial_fd, baudrate, 8, 'N', 1);
if (setret == -1)
{
close(serial_fd);
perror("set baudrate error\n");
}
// 打开输出文件
FILE *output_file = fopen(output_file_name, "w");
if (!output_file)
{
perror("Unable to open output file");
close(serial_fd);
return 1;
}
fd_set read_fds;
char data_buf[1024] = {0};
int logcount = 0;
int writeflag = 0;
BSB bsb;
BSB_INIT(bsb, data_buf, sizeof(data_buf));
char readBuffer[BUFFER_SIZE] = {0}; // 用于每次存储读取的数据
while (1)
{
FD_ZERO(&read_fds);
FD_SET(serial_fd, &read_fds);
// 使用 select 等待数据
int activity = select(serial_fd + 1, &read_fds, NULL, NULL, NULL);
if (activity < 0)
{
perror("select error");
break;
}
if (FD_ISSET(serial_fd, &read_fds))
{
int bytes_read = read(serial_fd, readBuffer, sizeof(readBuffer));
if (bytes_read > 0)
{
// 缓存收到的数据,缓存结束清除缓冲区
BSB_EXPORT_ptr_some(bsb, readBuffer, bytes_read);
memset(readBuffer, 0, sizeof(readBuffer));
if (BSB_LENGTH(bsb) >= 2 * FRAME_SIZE) // 至少有一帧数据
{
int bsb_in_len = BSB_LENGTH(bsb);
int i = 0;
// 找到收到buff中的第一帧数据
for (i = 0; i < bsb_in_len; i++)
{
if ((unsigned short)(bsb.buf[i + 1] << 8 | bsb.buf[i]) == (unsigned short)FRAME_HEADER)
// if (bsb.buf[i + 1] == 0xAD && bsb.buf[i] == 0x7E)
{
memmove(data_buf, &data_buf[i], bsb_in_len - i);
BSB_EXPORT_rewind(bsb, i);
break;
}
}
// 获取长度
int bas_in_len_for = BSB_LENGTH(bsb);
int fre_count = 0; // 记录解析完整帧的字节数。
char *p = bsb.buf;
// 解析缓存的数据 每次解析一整帧,不够一帧不解析
for (bas_in_len_for; bas_in_len_for >= FRAME_SIZE; bas_in_len_for -= FRAME_SIZE)
{
// 一帧一帧校验,即一帧一帧解析
// if (*((unsigned short *)p) == FRAME_HEADER && check_sum(p))
if (check_sum(p))
{
// 打印一帧
for (size_t i = 0; i < FRAME_SIZE; i++)
{
printf("%02X ", (unsigned char)p[i]);
}
printf("\n");
p += FRAME_SIZE;
}
fre_count += FRAME_SIZE;
}
// 循环退出时缓存的剩余不到一帧数据,缓存该半帧数据
if ((BSB_LENGTH(bsb) - fre_count) != 0)
{
int haf_ofset = 0;
haf_ofset = (BSB_LENGTH(bsb) - fre_count);
memmove(data_buf, &bsb.buf[fre_count], haf_ofset);
}
BSB_EXPORT_rewind(bsb, fre_count);
}
}
}
// printf("array.size: %ld,fre: %d,total: %d\n",array.size,fre,total);
}
fclose(output_file);
close(serial_fd);
return 0;
}
#endif
发送协议帧
#define SEND_FRE_LEN 32
#define SEND_DATA_LEN 26
char send_buf[32] = {0};
void send_fre(unsigned int *cut, double Imu_lon, double Imu_lat, float Imu_h, unsigned char vFlag, unsigned char errSta)
{
BSB bsb;
BSB_INIT(bsb, send_buf, SEND_FRE_LEN);
BSB_EXPORT_u16(bsb, 0x5A54);
BSB_EXPORT_u16(bsb, 0x3C3A);
BSB_EXPORT_u08(bsb, SEND_DATA_LEN);
// 加到一定值重新累加
if (*cut == 65535)
{
*cut = 0;
}
BSB_EXPORT_u32(bsb, *cut);
// 经纬高
// BSB_EXPORT_u64(bsb,Imu_lon);
// BSB_EXPORT_u64(bsb,Imu_lat);
// BSB_EXPORT_u32(bsb,Imu_h);
BSB_EXPORT_ptr(bsb, &Imu_lon, 8);
BSB_EXPORT_ptr(bsb, &Imu_lat, 8);
BSB_EXPORT_ptr(bsb, &Imu_h, 8);
// 有效标志
BSB_EXPORT_u08(bsb, vFlag);
// 定位误差
BSB_EXPORT_u08(bsb, errSta);
// 校验和
unsigned short sum = 0;
for (int i = 0; i < SEND_DATA_LEN; i++)
{
sum += send_buf[i];
}
BSB_EXPORT_u16(bsb, sum);
// 帧尾
BSB_EXPORT_u16(bsb, 0x5AFE);
memset(send_buf, 0, sizeof(send_buf));
*cut++;
}
注意:对于浮点型
double ddd=(int)aaa;//ddd不等于-13.14555
int bbb=aaa; //bbb不等于-13.14555
前面BSB中由于下面操作会影响浮点型数据解析和存储,所以对于浮点型存取不适用u32、u64的宏
最无脑方式:
//对于浮点型:
// float a=13.14f;
// BSB_IMPORT_double_or_float(bsb,&a,sizeof(a));//存
// BSB_IMPORT_double_or_float(bsb,&a,sizeof(a));//取
//已知通信双方大小端一样时,无论什么类型数据,存取直接无脑BSB_IMPORT_byte、BSB_EXPORT_ptr
// BSB bsb;
// BSB_INIT(bsb, send_buf, FRAME_SIZE);
// BSB_EXPORT_ptr(bsb, &fre.head, sizeof(fre.head)); // 2 bytes for unsigned short
// BSB_EXPORT_ptr(bsb, &fre.Fre_len, sizeof(fre.Fre_len)); // 1 byte for unsigned char
// BSB_EXPORT_ptr(bsb, &fre.Cnt, sizeof(fre.Cnt)); // 4 bytes for unsigned int
// BSB_EXPORT_ptr(bsb, &fre.GPS_week, sizeof(fre.GPS_week)); // 2 bytes for unsigned short
// BSB_EXPORT_ptr(bsb, &fre.GPS_Seconds, sizeof(fre.GPS_Seconds)); // 8 bytes for double
// BSB_EXPORT_ptr(bsb, &fre.Imu_lon, sizeof(fre.Imu_lon)); // 8 bytes for double
// BSB_EXPORT_ptr(bsb, &fre.Imu_lat, sizeof(fre.Imu_lat)); // 8 bytes for double
// BSB_EXPORT_ptr(bsb, &fre.Imu_h, sizeof(fre.Imu_h)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.Att_h, sizeof(fre.Att_h)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.Att_p, sizeof(fre.Att_p)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.Att_r, sizeof(fre.Att_r)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.Vel_e, sizeof(fre.Vel_e)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.Vel_n, sizeof(fre.Vel_n)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.Vel_u, sizeof(fre.Vel_u)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.Meter, sizeof(fre.Meter)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.Deviation, sizeof(fre.Deviation)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.BiasX, sizeof(fre.BiasX)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.BiasY, sizeof(fre.BiasY)); // 4 bytes for float
// BSB_EXPORT_ptr(bsb, &fre.check_sum, sizeof(fre.check_sum)); // 2 bytes for unsigned short
// BSB bsb;
// BSB_INIT(bsb, array.buffer, FRAME_SIZE);
// BSB_IMPORT_byte(bsb, &fre->head, sizeof(fre->head)); // 2 bytes for unsigned short
// BSB_IMPORT_byte(bsb, &fre->Fre_len, sizeof(fre->Fre_len)); // 1 byte for unsigned char
// BSB_IMPORT_byte(bsb, &fre->Cnt, sizeof(fre->Cnt)); // 4 bytes for unsigned int
// BSB_IMPORT_byte(bsb, &fre->GPS_week, sizeof(fre->GPS_week)); // 2 bytes for unsigned short
// BSB_IMPORT_byte(bsb, &fre->GPS_Seconds, sizeof(fre->GPS_Seconds)); // 8 bytes for double
// BSB_IMPORT_byte(bsb, &fre->Imu_lon, sizeof(fre->Imu_lon)); // 8 bytes for double
// BSB_IMPORT_byte(bsb, &fre->Imu_lat, sizeof(fre->Imu_lat)); // 8 bytes for double
// BSB_IMPORT_byte(bsb, &fre->Imu_h, sizeof(fre->Imu_h)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->Att_h, sizeof(fre->Att_h)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->Att_p, sizeof(fre->Att_p)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->Att_r, sizeof(fre->Att_r)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->Vel_e, sizeof(fre->Vel_e)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->Vel_n, sizeof(fre->Vel_n)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->Vel_u, sizeof(fre->Vel_u)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->Meter, sizeof(fre->Meter)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->Deviation, sizeof(fre->Deviation)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->BiasX, sizeof(fre->BiasX)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->BiasY, sizeof(fre->BiasY)); // 4 bytes for float
// BSB_IMPORT_byte(bsb, &fre->check_sum, sizeof(fre->check_sum)); // 2 bytes for unsigned short