• Linux串口断帧和连帧处理


    报文格式:

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

    断帧和连帧处理:

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

    1. #include
    2. #include
    3. #include
    4. //最大缓存区
    5. #define MAX_BUFFER_SIZE 4096
    6. //帧格式
    7. typedef struct {
    8. unsigned char start;
    9. unsigned short length;
    10. unsigned char data[MAX_BUFFER_SIZE/4];
    11. unsigned char checksum;
    12. unsigned char end;
    13. } Frame;
    14. //定义缓存区和缓存区当前索引
    15. unsigned char buffer[MAX_BUFFER_SIZE];
    16. int bufferIndex = 0;
    17. //打印hex数据
    18. void print_mesg(char *head, unsigned char *data, int len)
    19. {
    20. printf("%s", head);
    21. for(int i=0; i
    22. {
    23. printf("%02X ",data[i]);
    24. }
    25. printf("\n");
    26. }
    27. /**
    28. * 返回单字节校验和
    29. */
    30. unsigned char GetCheckSum(unsigned char *data, uint32_t data_size)
    31. {
    32. int i = 0;
    33. uint32_t temp = 0;
    34. uint8_t sum = 0;
    35. for(i = 0;i
    36. {
    37. temp += *(data+i);
    38. }
    39. sum = temp&0xff;
    40. return sum;
    41. }
    42. //接收数据处理
    43. void processFrame(Frame frame) {
    44. // 在这里处理接收到的帧数据
    45. // 可以根据具体需求对数据进行解密、校验等操作
    46. // 例如,可以打印数据体内容
    47. print_mesg("Received data:", frame.data, frame.length);
    48. }
    49. //接收数据放到缓存区
    50. void addToBuffer(unsigned char *data, int data_len) {
    51. // 将帧数据添加到缓存区
    52. if((bufferIndex+data_len) > MAX_BUFFER_SIZE)
    53. {
    54. bufferIndex = 0;
    55. memset(buffer, 0, MAX_BUFFER_SIZE);
    56. return;
    57. }
    58. memcpy(&buffer[bufferIndex],data, data_len);
    59. bufferIndex += data_len;
    60. }
    61. //解析帧
    62. void parseFrame(unsigned char* data, int length) {
    63. printf("length=%d\n",length);
    64. print_mesg("Received:", data, length);
    65. Frame frame;
    66. memset(&frame, 0, sizeof(Frame));
    67. addToBuffer(data, length);
    68. int dataIndex = 0;
    69. while (bufferIndex > 5) {
    70. if (buffer[dataIndex] != 0x02) {
    71. // 数据起始标志错误,丢弃当前帧
    72. dataIndex++;
    73. continue;
    74. }
    75. printf("dataIndex=%d\n",dataIndex);
    76. if (bufferIndex - dataIndex < 5) {
    77. // 数据长度不足,无法解析帧
    78. break;
    79. }
    80. frame.start = buffer[dataIndex];
    81. frame.length = (buffer[dataIndex + 1] << 8) | buffer[dataIndex + 2];
    82. if (bufferIndex - dataIndex < frame.length + 5) {
    83. // 数据长度不足,无法解析帧
    84. break;
    85. }
    86. memcpy(frame.data, buffer + dataIndex + 3, frame.length);
    87. frame.checksum = buffer[dataIndex + frame.length + 3];
    88. frame.end = buffer[dataIndex + frame.length + 4];
    89. // 检查校验和
    90. unsigned char checksum = GetCheckSum(&buffer[dataIndex+1], frame.length+2);
    91. printf("checksum:%02X\n",checksum);
    92. printf("frame.checksum:%02X\n",frame.checksum);
    93. printf("frame.end:%02X\n",frame.end);
    94. print_mesg("data:", frame.data, frame.length);
    95. if (checksum != frame.checksum || frame.end != 0x03) {
    96. // 校验和或控制字符错误,丢弃帧
    97. dataIndex++;
    98. continue;
    99. }
    100. processFrame(frame);
    101. dataIndex += frame.length + 5;
    102. bufferIndex -= dataIndex;
    103. memmove(buffer,buffer+dataIndex,bufferIndex);
    104. dataIndex=0;
    105. }
    106. }
    107. //是否断帧
    108. #define BROKEN_FRAME 1
    109. int main() {
    110. //0xFF为干扰字符
    111. 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};
    112. //0xFF为干扰字符
    113. 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};
    114. int receivedLength1 = sizeof(receivedData1) / sizeof(receivedData1[0]);
    115. int receivedLength2 = sizeof(receivedData2) / sizeof(receivedData2[0]);
    116. #if BROKEN_FRAME //断帧处理
    117. parseFrame(receivedData1, receivedLength1-10);
    118. parseFrame(receivedData1+receivedLength1-10, 5);
    119. parseFrame(receivedData1+receivedLength1-5, 5);
    120. #else //连帧处理
    121. parseFrame(receivedData2, receivedLength2);
    122. #endif
    123. return 0;
    124. }

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

    Linux串口断帧处理-CSDN博客

  • 相关阅读:
    RealSense D435 的开发日记(pyrealsense小实战项目)
    WPS 换行后缩进、加粗等自定义样式的清除
    JavaScript 进阶03
    php 日期
    渗透测试-文件上传/下载/包含
    如何保障需求质量(下):你应该做到的
    【创建型模式】抽象工厂模式
    Spring Security 中重要对象汇总
    期货开户需要具备⼀定的条件
    嵌入式4-24
  • 原文地址:https://blog.csdn.net/lu_linux/article/details/134269954