使用boost c++读取串口,我应该如何解码数据?
Using boost c++ to read a serial port, how should I decode the data?
我正在尝试创建一个从串行端口读取数据的简单应用程序。我有数据的结构,如下:
Byte Function Format Example Hex
0 Header ASCII Char I 49
1 Header ASCII Char W 57
2 Header ASCII Char A 41
3 Header ASCII Char P 50
4 Header ASCII Char I 49
5 Header ASCII Char x 78
6 Version uint8_t 1 1
7 Pan int32_t 0A
8 Pan int32_t 0B
9 Pan int32_t 0C
10 Pan int32_t 168496141 0D
11 Tilt int32_t 0A
12 Tilt int32_t 0B
13 Tilt int32_t 0C
14 Tilt int32_t 168496141 0D
15 Roll int32_t 0A
16 Roll int32_t 0B
17 Roll int32_t 0C
18 Roll int32_t 168496141 0D
19 Jog A int32_t 0A
20 Jog A int32_t 0B
21 Jog A int32_t 0C
22 Jog A int32_t 168496141 0D
23 Jog B int32_t 0A
24 Jog B int32_t 0B
25 Jog B int32_t 0C
26 Jog B int32_t 168496141 0D
27 Focus uint16_t 0A
28 Focus uint16_t 2571 0B
29 Iris uint16_t 0A
30 Iris uint16_t 2571 0B
31 Zoom uint16_t 0A
32 Zoom uint16_t 2571 0B
33 To One uint8_t (blip) 10 0A
34 Reverse uint8_t (blip) 10 0A
35 Pause uint8_t (blip) 10 0A
36 Forward uint8_t (blip) 10 0A
37 Reserved
38 Reserved
39 Reserved
40 Reserved
41 Reserved
42 Reserved
43 Reserved
44 Reserved
45 Checksum CheckSum8 Modulo 256
46 Footer ASCII Char ; 3B
47 Footer ASCII Char ! 21
48 Footer ASCII Char ; 3B
数据为:UART:921600 Baud,8N2,Big-Endian
我是这样打开端口,读取数据的:
#include <iostream>
#include <boost/asio.hpp>
using namespace std;
using namespace boost;
int main(int argc, char* argv[])
{
asio::io_service io;
asio::serial_port port(io);
port.open("COM14");
port.set_option(asio::serial_port_base::baud_rate(921600));
char c;
std::string rsp;
while (c != ';')
{
asio::read(port, asio::buffer(&c, 1));
rsp += c;
}
std::cout << rsp << std::endl;
port.close();
std::cin.get();
}
这给了我字符串:
IWVPx :ã {;
显然我做错了,我想是因为我正在读取数据 char
。
读取串口数据并转换为可读数据的正确方法是什么?
您可以使用提供的结构来解析数据。您看到的空格很可能是由于二进制数据的 ASCII 解释造成的。这是二进制数据的线索是作者指定了字节位置。以下是我将如何解析这些数据。
首先,创建一个与您要解析的数据相匹配的结构:
struct Data
{
char header[5];
uint8_t ver;
int32_t pan;
int32_t tilt;
int32_t roll;
int32_t joga;
int32_t jogb;
uint16_t focus;
uint16_t iris;
uint16_t zoom;
uint8_t toOne;
uint8_t reverse;
uint8_t pause;
uint8_t forward;
uint8_t reserved[8];
uint8_t checksum;
char footer[3];
}__attribute__((packed));
接下来,读入所有数据。有很多仪器远远超出了描述如何实际解析这些数据的范围,所以我将把它排除在外。在这里,我指的是确保您具有正确的数据包对齐、获取第二个分号、检查数据缓冲区的大小是否与预期结构的大小相同的方法。其中一些仅在发送的数据包是自动发送而不是请求时才起作用。
填充缓冲区后,确保它与数据结构的大小相同,非常简单:
Data data;
memcpy( &data, buffer, sizeof(data) );
然后可以像访问结构的一部分一样访问数据。请注意,此解决方案假定字节序在机器之间是一致的。如果不是,您可能必须执行一些字节反转。
最终结果可能如下所示:
int main(int argc, char* argv[])
{
asio::io_service io;
asio::serial_port port(io);
port.open("COM14");
port.set_option(asio::serial_port_base::baud_rate(921600));
uint8_t obuf[256]; // arbitrary size, larger than largest expected buffer
// perform packet alignment here
asio::read(port, asio::buffer(obuf, sizeof(Data)));
Data d = {};
memcpy( &d, obuf, sizeof(d) );
// if your endianness is different than the data sent, fix it here.
std::cin.get();
}
我正在尝试创建一个从串行端口读取数据的简单应用程序。我有数据的结构,如下:
Byte Function Format Example Hex
0 Header ASCII Char I 49
1 Header ASCII Char W 57
2 Header ASCII Char A 41
3 Header ASCII Char P 50
4 Header ASCII Char I 49
5 Header ASCII Char x 78
6 Version uint8_t 1 1
7 Pan int32_t 0A
8 Pan int32_t 0B
9 Pan int32_t 0C
10 Pan int32_t 168496141 0D
11 Tilt int32_t 0A
12 Tilt int32_t 0B
13 Tilt int32_t 0C
14 Tilt int32_t 168496141 0D
15 Roll int32_t 0A
16 Roll int32_t 0B
17 Roll int32_t 0C
18 Roll int32_t 168496141 0D
19 Jog A int32_t 0A
20 Jog A int32_t 0B
21 Jog A int32_t 0C
22 Jog A int32_t 168496141 0D
23 Jog B int32_t 0A
24 Jog B int32_t 0B
25 Jog B int32_t 0C
26 Jog B int32_t 168496141 0D
27 Focus uint16_t 0A
28 Focus uint16_t 2571 0B
29 Iris uint16_t 0A
30 Iris uint16_t 2571 0B
31 Zoom uint16_t 0A
32 Zoom uint16_t 2571 0B
33 To One uint8_t (blip) 10 0A
34 Reverse uint8_t (blip) 10 0A
35 Pause uint8_t (blip) 10 0A
36 Forward uint8_t (blip) 10 0A
37 Reserved
38 Reserved
39 Reserved
40 Reserved
41 Reserved
42 Reserved
43 Reserved
44 Reserved
45 Checksum CheckSum8 Modulo 256
46 Footer ASCII Char ; 3B
47 Footer ASCII Char ! 21
48 Footer ASCII Char ; 3B
数据为:UART:921600 Baud,8N2,Big-Endian
我是这样打开端口,读取数据的:
#include <iostream>
#include <boost/asio.hpp>
using namespace std;
using namespace boost;
int main(int argc, char* argv[])
{
asio::io_service io;
asio::serial_port port(io);
port.open("COM14");
port.set_option(asio::serial_port_base::baud_rate(921600));
char c;
std::string rsp;
while (c != ';')
{
asio::read(port, asio::buffer(&c, 1));
rsp += c;
}
std::cout << rsp << std::endl;
port.close();
std::cin.get();
}
这给了我字符串:
IWVPx :ã {;
显然我做错了,我想是因为我正在读取数据 char
。
读取串口数据并转换为可读数据的正确方法是什么?
您可以使用提供的结构来解析数据。您看到的空格很可能是由于二进制数据的 ASCII 解释造成的。这是二进制数据的线索是作者指定了字节位置。以下是我将如何解析这些数据。
首先,创建一个与您要解析的数据相匹配的结构:
struct Data
{
char header[5];
uint8_t ver;
int32_t pan;
int32_t tilt;
int32_t roll;
int32_t joga;
int32_t jogb;
uint16_t focus;
uint16_t iris;
uint16_t zoom;
uint8_t toOne;
uint8_t reverse;
uint8_t pause;
uint8_t forward;
uint8_t reserved[8];
uint8_t checksum;
char footer[3];
}__attribute__((packed));
接下来,读入所有数据。有很多仪器远远超出了描述如何实际解析这些数据的范围,所以我将把它排除在外。在这里,我指的是确保您具有正确的数据包对齐、获取第二个分号、检查数据缓冲区的大小是否与预期结构的大小相同的方法。其中一些仅在发送的数据包是自动发送而不是请求时才起作用。
填充缓冲区后,确保它与数据结构的大小相同,非常简单:
Data data;
memcpy( &data, buffer, sizeof(data) );
然后可以像访问结构的一部分一样访问数据。请注意,此解决方案假定字节序在机器之间是一致的。如果不是,您可能必须执行一些字节反转。
最终结果可能如下所示:
int main(int argc, char* argv[])
{
asio::io_service io;
asio::serial_port port(io);
port.open("COM14");
port.set_option(asio::serial_port_base::baud_rate(921600));
uint8_t obuf[256]; // arbitrary size, larger than largest expected buffer
// perform packet alignment here
asio::read(port, asio::buffer(obuf, sizeof(Data)));
Data d = {};
memcpy( &d, obuf, sizeof(d) );
// if your endianness is different than the data sent, fix it here.
std::cin.get();
}