问题描述
我正在编写一个从 Linux 上的串口读取数据的程序.数据由其他设备发送,帧格式如下:
I am writing a program that reads the data from the serial port on Linux.The data are sent by another device with the following frame format:
|start | Command | Data | CRC | End |
|0x02 | 0x41 | (0-127 octets) | | 0x03|
----------------------------------------------------
Data 字段包含 127 个八位字节,如图所示,八位字节 1,2 包含一种类型的数据;八位字节 3,4 包含另一个数据.我需要获取这些数据
The Data field contains 127 octets as shown and octet 1,2 contains one type of data; octet 3,4 contains another data. I need to get these data
我知道如何在 Linux 中向串行端口写入和读取数据,但它只是写入和读取一个简单的字符串(如ABD")
I know how to write and read data to and from a serial port in Linux, but it is just to write and read a simple string (like "ABD")
我的问题是我不知道如何解析上述格式的数据框,以便我可以:
My issue is that I do not know how to parse the data frame formatted as above so that I can:
- 在数据字段中获取 octet 1,2 中的数据
- 在数据字段中获取 octet 3,4 中的数据
- 获取 CRC 字段中的值以检查数据的一致性
这里是在 Linux 中从串行端口读取和写入简单字符串的示例片段代码:
Here the sample snip code that read and write a simple string from and to a serial port in 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!
", 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
");
return 0;
} else {
printf("SERIAL read error %d %s
", errno, strerror(errno));
return 0;
}
}
return 1;
}
请问有人有什么想法吗?
Does anyone please have some ideas?
推荐答案
result
是一个 char
数组,其宽度为 1 个八位字节.
result
is an array of char
s, which are 1 octet wide.
读取八位字节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 位字:
You want to read two consecutive octets into one 16-bit word:
1
bits 5 8 7 0
--------------------
octet_1_2 = | octet 2 | octet 1|
--------------------
所以你想取八位字节 1 的 7:0 位并将它们放入 octet_1_2
的位 7:0 中:
So you want to take bits 7:0 of octet 1 and put them in bits 7:0 of octet_1_2
:
octet_1_2 = data_field[1];
然后你想取出八位字节 2 的位 7:0 并将它们放入 octet_1_2
的位 15:8.为此,您可以将八位字节 2 向左移动 8 位,然后将结果 OR
'ing 到 octet_1_2
:
Then you want to take bits 7:0 of octet 2 and put them in bits 15:8 of octet_1_2
. You do this by shifting octet 2 8 bits to the left, and OR
'ing the result into octet_1_2
:
octet_1_2 |= data_field[2] << 8;
这两行可以像我上面那样合并成一条.
These two lines can be merged into one as I did above.
这篇关于在 C 中解析和读取数据帧?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!