从串行设备读取字节(并理解它们??)
我正在绞尽脑汁地试图找出如何从串行设备读取字节,检查校验和,然后将它们转换为我实际可以读取的内容。
我有一个设备“应该”向我发送各种消息,每条消息都以字节 $83 开始,以字节 $84 结束。倒数第二个字节应该是校验和,由将所有其他值异或并比较生成。
返回的实际值应该是字母数字,但我无法了解数据的正反面。我是 C++ 新手 - 我确信这没有帮助。
我读过几本关于串行编程的指南,但我迷失了。
任何人都可以帮助我、链接我或向我展示如何从串行设备读取字节、监视 $83 和 $84,然后理解之间的数据吗?
以下是每条消息的格式:
$FF byte Destination Address
$10 byte Message Length 16 Bytes
$37 byte Message Type
$00 byte Message subtype
BankAngle int -179 to +180
PitchAngle int -90 to +90
YawAngle int -179 to +180
Slip sint -50 to +50
GForce fps 0 to 6G
MISC byte Mode bits
Heading word 0 to 359
N/A not used
Voltage byte input voltage
这一切都来自 MGL SP-4 AHRS,为了便于使用,我的目标是 Linux 系统,特别是 Ubuntu。我使用GCC编译器和Eclipse CDT进行开发。
我迷路的地方 我可以将数据读入缓冲区,但之后我对 C++ 的了解不够,无法理解它,因为它不是 ASCII。我有兴趣学习我需要知道的东西,但我不知道我需要知道什么。
我有 Perl/Java 背景。
I'm pulling my hair out trying to figure out how to read bytes off a serial device, check a checksum, and then convert them into something that I can actually read.
I have a device which "should" be sending me various messages, each started with the byte $83 and ended with the byte $84. The second to last byte is supposedly a checksum, generated by XORign all the other values together and comparing.
The actual values coming back should be alphanumeric, but I can't make heads or tail of the data. I'm newish to C++ - I'm sure that's not helping.
I've read several guides on serial programming, but I'm lost.
Can anyone help me, link me, or show me how to read bytes off a serial device, watch for $83 and $84, and then make sense of the data in between?
Here is the format of each message:
$FF byte Destination Address
$10 byte Message Length 16 Bytes
$37 byte Message Type
$00 byte Message subtype
BankAngle int -179 to +180
PitchAngle int -90 to +90
YawAngle int -179 to +180
Slip sint -50 to +50
GForce fps 0 to 6G
MISC byte Mode bits
Heading word 0 to 359
N/A not used
Voltage byte input voltage
This is all coming off an MGL SP-4 AHRS, and for ease of use I am targeting a Linux system, specifically Ubuntu. I am using the GCC compiler end the Eclipse CDT for development.
Where I'm lost
I can read the data into a buffer, but then I'm not versed enough in C++ to make sense of it after that, since it's not ASCII. I'm interested in learning what I need to know, but I don't know what I need to know.
I have a Perl / Java background.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
实现这一点将完全取决于您的目标操作系统和平台。由于您提到的设备在一般用例中安装在飞机内部,因此我假设您的目标不是 Windows 平台,而更可能是 Linux 或嵌入式系统。有许多资源可用于在此类平台上执行串行 I/O(例如:串行编程方法)。此外,根据设备安装手册中的建议(位于页面中间的此处),您应该“查阅 SP-4 OEM 手册以了解消息格式和消息类型选择。”我怀疑您将从该文档中获得最相关和最有用的信息。您可能需要检查制造商是否为您的平台提供 API,因为这将消除您实现实际通信例程的需要。
就理解数据而言,一旦您可以从串行接口读取字节,您就可以利用
struct
和union
来制作更方便程序员访问您的数据。对于您提供的粗略消息大纲,类似这样的内容可能是合适的:这样,如果您要声明 struct myMessage serialData;,您可以将消息读入
serialData.raw
,然后方便地访问其成员(例如serialData.message.DestinationAddress
)。编辑:为了响应您的编辑,我将提供一个示例来说明如何理解您的数据。此示例假设您只需要担心一种消息类型,但它可以轻松扩展到其他类型。
现在,假设这些整数类型实际上仅对数据传输有用,您需要将这些位转换为“可用数据”。假设这些字段之一实际上是一个编码的浮点数。一种常见的方案是选择位权重(有时也称为分辨率)。我不知道这是否直接适用于您的设备,或者它是否是真实值,但为了讨论起见,我们假设
YawAngle
字段的分辨率为0.00014 度/位
。例如,要将消息 (serialData.message.YawAngle
) 中的值从uint32_t
值转换为double
,您可以这样做:……就是这样。 OEM 手册应该告诉您数据是如何编码的,并且您应该能够从中找出如何对其进行解码。
现在,假设您有两种消息类型需要处理。我已经向您展示了这一消息,以及一条理论上的
CRITICAL_BITS
消息。要使用我列出的方案添加该类型,您首先需要定义CRITICAL_BITS
结构(可能如下所示):...然后将其添加到
struct myMessage
> 定义如下:...然后您可以像其他字段一样访问
SomeCriticalData
。您可以通过阅读
struct
s。请记住,struct myMessage
类型的实例一次仅包含一组有意义的数据。更简单地说,如果serialData
包含CRITICAL_MESSAGE_TYPE
数据,则serialData.ritic_message
中的数据有效,但serialData.message
code> 不是——即使该语言不会阻止您在请求时访问该数据。编辑:再举一个例子;要使用您指定的算法计算消息的校验和,您可能需要这样的东西(假设您已经知道消息完全在缓冲区内):
您可能需要针对不存在的字节调整该函数包括在内,检查以确保
data != NULL
等,但它应该可以帮助您入门。Accomplishing this is going to be wholly dependent on the Operating System and platform that you target. Since the device you mention is mounted internally to an aircraft in the general use-case, I will assume you are not targeting a Windows platform, but more likely a Linux or embedded system. There are a number of resources available for performing serial I/O on such platforms (for example: the Serial Programming HOW-TO) that you should look at. Additionally, as suggested in the device's Installation Manual (available here about halfway down the page), you should "Consult the SP-4 OEM manual for message formats and message type selection." I suspect you will obtain the most relevant and useful information from that document. You may want to check if the manufacturer provides an API for your platform, as that would negate the need for you to implement the actual communication routine.
As far as making sense of the data, once you can read bytes from your serial interface, you can leverage
struct
s andunion
s to make accessing your data more programmer-friendly. For the rough message outline you provided, something like this might be appropriate:This way, if you were to declare
struct myMessage serialData;
, you can read your message intoserialData.raw
, and then conveniently access its members (e.g.serialData.message.DestinationAddress
).Edit: In response to your edit, I'll provide an example of how to make sense of your data. This example supposes there is only one message type you have to worry about, but it can be easily extended to other types.
Now, supposing that these integral types are really only useful for data transmission, you need to translate these bits into "usable data". Say one of these fields is actually an encoded floating-point number. One common scheme is to select a bit-weight (sometimes also called resolution). I don't know if this is directly applicable to your device, or if it is what the real values are, but let's say for the sake of discussion, that the
YawAngle
field had a resolution of0.00014 degrees/bit
. To translate the value in your message (serialData.message.YawAngle
) from itsuint32_t
value to adouble
, for example, you might do this:...and that's about it. The OEM manual should tell you how the data is encoded, and you should be able to work out how to decode it from there.
Now, let's say you've got two message types to handle. The one I've already shown you, and a theoretical
CRITICAL_BITS
message. To add that type using the scheme I've laid out, you would first define theCRITICAL_BITS
structure (perhaps as follows):...and then add it to the
struct myMessage
definition like so:...then you can access the
SomeCriticalData
just like the other fields.You can find a little more information on how this works by reading about
struct
s. Bear in mind, that instances of thestruct myMessage
type will only ever contain one set of meaningful data at a time. Put more simply, ifserialData
containsCRITICAL_MESSAGE_TYPE
data, then the data inserialData.critical_message
is valid, butserialData.message
is not --even though the language does not prevent you from accessing that data if you request it.Edit: One more example; to calculate the checksum of a message, using the algorithm you've specified, you would probably want something like this (assuming you already know the message is completely within the buffer):
You might need to adjust that function for bytes that aren't included, check to make sure that
data != NULL
, etc. but it should get you started.