我正在编写一个从Linux上的串口读取数据的程序。 数据由具有以下帧格式的其他设备发送:
|start | Command | Data | CRC | End |
|0x02 | 0x41 | (0-127 octets) | | 0x03|
----------------------------------------------------
数据字段包含127个八位字节,如图所示,八位字节1,2包含一种数据类型;八位位组3,4包含另一个数据。我需要获取这些数据
我知道如何在Linux中从串口写入和读取数据,但只是编写和读取一个简单的字符串(如“ABD”)
我的问题是我不知道如何解析上面格式化的数据框,以便我可以:
这里是从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;
}
有没有人请一些想法?
答案 0 :(得分:5)
result
是一个char
的数组,宽度为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|
--------------------
所以你想把8位的比特7:0放在octet_1_2
的7:0位:
octet_1_2 = data_field[1];
然后你想取八位字节2的7:0位并将它们放在octet_1_2
的15:8位。你可以通过向左移八位字节8位,并将结果OR
变为octet_1_2
来实现这一点:
octet_1_2 |= data_field[2] << 8;
这两行可以像我上面那样合并为一行。
答案 1 :(得分:0)
在C中读取格式化数据的最好方法是读取结构。 鉴于您拥有的帧格式,我将执行以下操作。
typedef struct special_data
{
char first_data[2];
char second data[2];
} special_data_t;
union data_u
{
special_data_t my_special_data;
char whole_data[128];
};
typedef struct data_frame
{
unsigned char start;
unsigned char cmd;
union data_u data;
unsigned char crc;
unsigned char end;
} data_frame_t;
void func_read(int fd)
{
data_frame_t my_data;
if (read(fd, &my_data, sizeof(my_data)) != -1)
{
// Do something
}
return;
}
这样您就可以通过结构字段访问所需的数据。第一个结构和联合只是帮助在框架的数据字段中访问所需的字节。