如果在开发中碰到需要解析大量数据且存在粘包现象的情况下:
数据帧格式:0xAA(包头) + 0xXX(命令) + 0xXX(长度) + 数据部分 + 0xXX(CRC)
下列函数可以从一串数据中提取一帧数据:
提供帧同步能力(遇到中断帧或新帧头重新同步);
高效接收并丢弃非法帧(溢出清空、错误帧重起)。
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#define MAX_FRAME_LENGTH 1024
#define FRAME_HEADER 0xAA
uint8_t buffer[MAX_FRAME_LENGTH];
int bufferLen = 0;
bool foundStart = false;
int expectedLength = -1;
void ProcessReceivedData(uint8_t* frame, int len); // 处理数据帧函数,需你实现
void ProcessIncomingBytes(uint8_t* data, int length)
{
for (int i = 0; i < length; i++)
{
uint8_t b = data[i];
if (!foundStart)
{
if (b == FRAME_HEADER)
{
bufferLen = 0;
buffer[bufferLen++] = b;
foundStart = true;
expectedLength = -1;
}
continue;
}
buffer[bufferLen++] = b;
// 解析长度字段(第 3 个字节)
if (bufferLen == 3 && expectedLength == -1)
{
uint8_t dataLen = buffer[2];
expectedLength = 1 + 1 + 1 + dataLen + 1; // 帧头 + 命令 + 长度 + 数据 + CRC
}
// 如果再次遇到 0xAA,可能是新一帧开始
if (b == FRAME_HEADER && bufferLen > 1)
{
bufferLen--; // 移除当前 0xAA
if (expectedLength > 0 && bufferLen == expectedLength)
{
ProcessReceivedData(buffer, bufferLen);
}
buffer[0] = FRAME_HEADER;
bufferLen = 1;
expectedLength = -1;
continue;
}
// 收到完整帧
if (expectedLength > 0 && bufferLen == expectedLength)
{
ProcessReceivedData(buffer, bufferLen);
bufferLen = 0;
foundStart = false;
expectedLength = -1;
}
// 错误保护:溢出处理
if (bufferLen > MAX_FRAME_LENGTH)
{
bufferLen = 0;
foundStart = false;
expectedLength = -1;
}
}
}