Linux串口断帧和连帧处理

本文介绍了一个C++程序,用于解析报文格式,包括STX、数据长度、数据体、校验和和ETX,以及如何处理断帧和连帧。程序中提供了断帧测试和连帧测试功能,展示了如何通过宏BROKEN_FRAME控制测试方式。
摘要由CSDN通过智能技术生成

报文格式:

字段长度(字节)说明
STX        1开始控制字符 0x02
数据长度2传输时需要转换成INTEL序(高字节在前)数据体部分长度。最大允许值为:4096
数据体不定由数据长度决定
校验字节1校验字节是报文中除通信控制字符之外所有数据的校验和
ETX1结束控制字符 0x03

断帧和连帧处理:

通过宏BROKEN_FRAME可以控制断帧测试或是连帧测试 ,代码中有详细注释说明

#include <stdio.h>
#include <string.h>
#include <stdint.h>

//最大缓存区
#define MAX_BUFFER_SIZE 4096

//帧格式
typedef struct {
    unsigned char start;
    unsigned short length;
    unsigned char data[MAX_BUFFER_SIZE/4];
    unsigned char checksum;
    unsigned char end;
} Frame;

//定义缓存区和缓存区当前索引
unsigned char buffer[MAX_BUFFER_SIZE];
int bufferIndex = 0;

//打印hex数据
void print_mesg(char *head, unsigned char *data, int len)
{
        printf("%s", head);
        for(int i=0; i<len; i++)
        {
                printf("%02X ",data[i]);
        }
        printf("\n");
}

/**
 * 返回单字节校验和
 */
unsigned char GetCheckSum(unsigned char *data, uint32_t data_size)
{
        int i = 0;
        uint32_t temp = 0;
        uint8_t sum = 0;
        for(i = 0;i<data_size;i++)
        {
                temp += *(data+i);
        }
        sum = temp&0xff;
        return sum;
}

//接收数据处理
void processFrame(Frame frame) {
    // 在这里处理接收到的帧数据
    // 可以根据具体需求对数据进行解密、校验等操作
    // 例如,可以打印数据体内容
    print_mesg("Received data:", frame.data, frame.length);
}

//接收数据放到缓存区
void addToBuffer(unsigned char *data, int data_len) {
    // 将帧数据添加到缓存区
        if((bufferIndex+data_len) > MAX_BUFFER_SIZE)
        {
                bufferIndex = 0;
                memset(buffer, 0, MAX_BUFFER_SIZE);
                return;
        }
    memcpy(&buffer[bufferIndex],data, data_len);
    bufferIndex += data_len;
}

//解析帧
void parseFrame(unsigned char* data, int length) {
    printf("length=%d\n",length);
    print_mesg("Received:", data, length);
    Frame frame;
    memset(&frame, 0, sizeof(Frame));
    addToBuffer(data, length);

    int dataIndex = 0;
    while (bufferIndex > 5) {
        if (buffer[dataIndex] != 0x02) {
            // 数据起始标志错误,丢弃当前帧
                        dataIndex++;
                        continue;
        }
        printf("dataIndex=%d\n",dataIndex);

        if (bufferIndex - dataIndex < 5) {
            // 数据长度不足,无法解析帧
            break;
        }

        frame.start = buffer[dataIndex];
        frame.length = (buffer[dataIndex + 1] << 8) | buffer[dataIndex + 2];

        if (bufferIndex - dataIndex < frame.length + 5) {
            // 数据长度不足,无法解析帧
            break;
        }

        memcpy(frame.data, buffer + dataIndex + 3, frame.length);
        frame.checksum = buffer[dataIndex + frame.length + 3];
        frame.end = buffer[dataIndex + frame.length + 4];

        // 检查校验和
        unsigned char checksum = GetCheckSum(&buffer[dataIndex+1], frame.length+2);
                printf("checksum:%02X\n",checksum);
                printf("frame.checksum:%02X\n",frame.checksum);
                printf("frame.end:%02X\n",frame.end);
                print_mesg("data:", frame.data, frame.length);

        if (checksum != frame.checksum || frame.end != 0x03) {
            // 校验和或控制字符错误,丢弃帧
            dataIndex++;
            continue;
        }

        processFrame(frame);

        dataIndex += frame.length + 5;
        bufferIndex -= dataIndex;
        memmove(buffer,buffer+dataIndex,bufferIndex);
        dataIndex=0;
    }
}

//是否断帧
#define BROKEN_FRAME 1

int main() {
    //0xFF为干扰字符
    unsigned char receivedData1[] = {0xFF,0x02, 0x00, 0x13, 0x10, 0x02, 0x00, 0x01, 0x32, 0x30, 0x32, 0x33, 0x31, 0x31, 0x30, 0x32, 0x31, 0x39, 0x35, 0x38, 0x30, 0x33, 0x02, 0xED, 0x03};
    //0xFF为干扰字符
    unsigned char receivedData2[] = {0x02, 0x00, 0x13, 0x10, 0x02, 0x00, 0x01, 0x32, 0x30, 0x32, 0x33, 0x31, 0x31, 0x30, 0x32, 0x31, 0x39, 0x35, 0x38, 0x30, 0x33, 0x02, 0xED, 0x03, 0xFF, 0x02, 0x00, 0x13, 0x50, 0x01, 0x00, 0x01, 0x62, 0x77, 0x74, 0x32, 0x31, 0x30, 0x38, 0x38, 0x32, 0x30, 0x34, 0x30, 0x31, 0x01, 0x00, 0xad, 0x03, 0x02, 0x00, 0x13, 0x50, 0x01, 0x00, 0x01, 0x62, 0x77, 0x74, 0x32, 0x31, 0x30, 0x38, 0x38, 0x32, 0x30, 0x34, 0x30, 0x31, 0x01, 0x00, 0xad, 0x03};

    int receivedLength1 = sizeof(receivedData1) / sizeof(receivedData1[0]);
    int receivedLength2 = sizeof(receivedData2) / sizeof(receivedData2[0]);
#if BROKEN_FRAME  //断帧处理
    parseFrame(receivedData1, receivedLength1-10);
    parseFrame(receivedData1+receivedLength1-10, 5);
    parseFrame(receivedData1+receivedLength1-5, 5);
#else            //连帧处理
    parseFrame(receivedData2, receivedLength2);
#endif
    return 0;
}

如果不需要连帧处理,仅仅简单的断帧处理可参考下面博文

Linux串口断帧处理-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值