解析并读取C中的数据帧?

提问

我正在编写一个程序,该程序从Linux上的串行端口读取数据.
数据由另一设备以以下帧格式发送:

|start | Command | Data               | CRC  | End |
|0x02  | 0x41    | (0-127 octets)     |      | 0x03|
----------------------------------------------------

如图所示,数据字段包含127个八位位组,而1,2位八位组则包含一种类型的数据.字节3,4包含另一个数据.我需要获取这些数据

我知道如何在Linux的串行端口中读写数据,但这只是读写简单的字符串(如“ ABD”)

我的问题是我不知道如何解析如上所述格式的数据帧,这样我可以:

>在“数据”字段中获取八位字节1,2中的数据
>在“数据”字段中获取八位位组3,4中的数据
>在CRC字段中获取值以检查数据的一致性

这里是在Linux的串行端口中读写简单字符串的示例代码示例:

int writeport(int fd, char *chars) {
    int len = strlen(chars);
    chars[len] = 0x0d; // stick a <CR> after the command
    chars[len+1] = 0x00; // terminate the string properly
    int n = write(fd, chars, strlen(chars));
    if (n < 0) {
        fputs("write failed!\n", stderr);
        return 0;
    }
    return 1;                                                                                                           
}

int readport(int fd, char *result) {
    int iIn = read(fd, result, 254);
    result[iIn-1] = 0x00;
    if (iIn < 0) {
        if (errno == EAGAIN) {
            printf("SERIAL EAGAIN ERROR\n");
            return 0;
        } else {
            printf("SERIAL read error %d %s\n", errno, strerror(errno));
            return 0;
        }
    }                    
    return 1;
}

有人请问一些想法吗?

最佳答案

结果是一个字符数组,其宽度为1个八位位组.

读取八位位组n使用:

char octet_n = result[n];

因此,您可以按照自己的意愿做:

// skip the start and command fields
char *data_field = result + 2; 

int octet_1_2 = data_field[1] | (data_field[2] << 8);
int octet_3_4 = data_field[3] | (data_field[4] << 8);

// crc is at byte 128 + 2 = 130
int crc = result[130];

编辑:此行的说明:

int octet_1_2 = data_field[1] | (data_field[2] << 8);

您想将两个连续的八位位组读取为一个16位字:

            1
       bits 5        8 7       0
            --------------------
octet_1_2 = | octet 2 | octet 1|
            --------------------

因此,您需要采用八位位组1的7:0位,并将它们放入八位位组_1_2的7:0位:

octet_1_2 = data_field[1];

然后,您要获取八位位组2的7:0位,并将它们放入八位位组_1_2的15:8位.您可以通过将八位位组2左移8位,然后将结果进行OR’ing到八位组_1_2来完成此操作:

octet_1_2 |= data_field[2] << 8;

这两条线可以像我上面那样合并为一条.