从串行设备读取字节(并理解它们??)
Read Bytes off a Serial Device (and make sense of them??)
我正在竭尽全力,试图弄清楚如何从串行设备上读取字节,检查校验和,然后将它们转换成我可以实际读取的东西。
我有一个设备,它"应该"向我发送各种消息,每条消息以字节$83开始,以字节$84结束。倒数第二个字节应该是校验和,由XORign将所有其他值加在一起并进行比较生成。
返回的实际值应该是字母数字,但我不能确定数据的头或尾。我对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背景。
实现这一点将完全取决于您的目标操作系统和平台。由于您提到的设备在一般使用情况下安装在飞机内部,我认为您的目标不是Windows平台,更可能是Linux或嵌入式系统。有许多资源可用于在此类平台上执行串行I/O(例如:串行编程HOW-TO),您应该查看这些资源。此外,正如设备的安装手册中所建议的(可在页面的一半处获得),您应该"有关消息格式和消息类型选择,请参阅SP-4 OEM手册。"我怀疑您将从该文档中获得最相关和最有用的信息。您可能需要检查制造商是否为您的平台提供了API,因为这将否定您实现实际通信例程的需要。
就理解数据而言,一旦您可以从串行接口读取字节,您就可以利用struct
s和union
s,使访问数据对程序员更友好。对于您提供的粗略消息大纲,类似这样的内容可能是合适的:
struct _message
{
uint8_t DestinationAddress;
uint8_t MessageLength;
uint8_t MessageType;
uint8_t MessageSubtype;
int32_t BankAngle; //assuming an int is 32 bits
int32_t PitchAngle;
int32_t YawAngle;
sint_t Slip; //not sure what a 'sint' is
fps_t GForce; //likewise 'fps'
uint8_t MISC;
uint16_t Heading; //assuming a word is 16 bits
uint8_t Unused[UNUSED_BYTES]; //however many there are
uintt_t Voltage;
}
struct myMessage
{
union
{
char raw[MAX_MESSAGE_SIZE]; //sizeof(largest possible message)
struct _message message;
}
}
这样,如果您要声明struct myMessage serialData;
,您可以将消息读取到serialData.raw
中,然后方便地访问其成员(例如serialData.message.DestinationAddress
)。
编辑:针对您的编辑,我将提供一个如何理解您的数据的示例。这个例子假设只有一种消息类型需要担心,但它可以很容易地扩展到其他类型。
struct myMessage serialData;
memcpy(serialData.raw, serialDataBuffer, MAX_MESSAGE_SIZE); //copy data from your buffer
if(serialData.message.MessageType == SOME_MESSAGE_TYPE)
{
//you have usable data here.
printf("I am a SOME_MESSAGE!n");
}
现在,假设这些积分类型实际上只对数据传输有用,您需要将这些位转换为"可用数据"。假设其中一个字段实际上是一个编码的浮点数。一种常见的方案是选择比特权重(有时也称为分辨率)。我不知道这是否直接适用于您的设备,或者它是否是实际值,但为了讨论起见,我们假设YawAngle
字段的分辨率为0.00014 degrees/bit
。例如,要将消息(serialData.message.YawAngle
)中的值从其uint32_t
值转换为double
,可以执行以下操作:
double YawAngleValue = 0.00014 * serialData.message.YawAngle;
OEM手册应该告诉你数据是如何编码的,你应该能够从中找出如何解码。
现在,假设您有两种消息类型要处理。我已经给你看了一个,还有一个理论上的CRITICAL_BITS
消息。要使用我列出的方案添加该类型,您首先需要定义CRITICAL_BITS
结构(可能如下):
struct _critical_bits
{
uint8_t DestinationAddress;
uint8_t MessageLength;
uint8_t MessageType;
uint8_t MessageSubtype;
uint32_t SomeCriticalData;
}
然后将其添加到struct myMessage
定义中,如:
struct myMessage
{
union
{
char raw[MAX_MESSAGE_SIZE]; //sizeof(largest possible message)
struct _message message;
struct _critical_bits critical_message;
}
}
则可以像访问其他字段一样访问CCD_ 14。
if(serialData.message.MessageType == CRITICAL_MESSAGE_TYPE)
{
uint32_t critical_bits = serialData.critical_message.SomeCriticalData;
}
通过阅读struct
s,您可以找到更多关于它是如何工作的信息。请记住,struct myMessage
类型的实例一次只包含一组有意义的数据。更简单地说,如果serialData
包含CRITICAL_MESSAGE_TYPE
数据,那么serialData.critical_message
中的数据是有效的,但serialData.message
不是——即使语言不会阻止您在请求时访问该数据。
编辑:再举一个例子;要使用您指定的算法计算消息的校验和,您可能需要这样的东西(假设您已经知道消息完全在缓冲区内):
uint8_t calculate_checksum(struct myMessage *data)
{
uint8_t number_bytes = data->message.MessageLength;
uint8_t checksum = 0;
int i;
for(i=0; i<number_bytes; ++i)
{
//this performs a XOR with checksum and the byte
//in the message at offset i
checksum ^= data->raw[i];
}
return checksum;
}
您可能需要针对未包含的字节调整该函数,检查以确保data != NULL
等,但它应该会让您开始使用。
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 在java中读取c++字节的位字段
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- std::ifstream::read 不会读取所有 512 字节,并设置 EOF 和失败位
- QDataStream 读取和写入的字节数比 QFile::length() 报告要多
- 如何从保存在 Java 中C++的字节数组中读取数字?
- Async_read_until限制读取的字节大小(Boost::asio)
- 如果由不同的线程写入 8 字节,那么现代英特尔 x86 上的 8 字节读取是否保证理智?
- C++ - 将任何文件的字节读取到无符号字符数组中
- InternetReadFile 填充缓冲区,但返回零字节读取
- ReadFromFile C++具有未知字节读取大小
- 从字节 [] 读取字符串
- C 如何将字节读取为整数enderness独立
- x64 CPU上的原子16字节读取
- 具有重叠I/O的FILE_FLAG_NO_BUFFERING-字节读取为零
- std::数组和字节读取
- 如何发现字节读取是日语还是英语
- 内存的字节读取:"signed char *" vs "unsigned char *"
- TCP Recv使用select()返回1字节读取
- c++字节读取问题