2012-01-27 11 views
0

シリアルデバイスからバイトを読み込み、チェックサムをチェックし、それから私が何かに変換する方法を理解しようとしています。実際に読むことができます。シリアルデバイスからバイトを読み取って(そしてそれを理解していますか?)

私はさまざまなメッセージを送信する必要があります。それぞれのメッセージは、$ 83バイトで始まり、$ 84で終わります。 2番目のバイトから最後のバイトは、おそらくチェックサムであり、他のすべての値を一緒にXORして比較し、比較します。

戻ってくる実際の値は英数字でなければなりませんが、データの頭や尾を作ることはできません。私は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のを標的としています。私は開発のためにEclipse CDTを終了するGCCコンパイラを使用しています。私は、バッファにデータを読み取ることができますが、それはASCIIではないので、その後、私は、その後それの意味を理解するためにC++に十分精通していないよ を失ったんだ

。私が知る必要があることを学ぶことに興味がありますが、私は何を知る必要があるのか​​分かりません。

私はPerl/Javaのバックグラウンドを持っています。

+2

この質問に対する答えとして、誰かがあなたにバイトストリームの "合意"を示すコードを表示できたら、私は驚くでしょう。 – unwind

+0

これでシリアルプロトコルは何ですか?両側にどのようなコードがありますか(TX/RX)? – L7ColWinters

+1

あなたはどのコンパイラとOSを使用していますか?あなたのデバイスが接続されていることを確認し、シリアルターミナルエミュレータを使用して期待されるデータを送信しましたか? – tinman

答えて

3

これを達成するには、ターゲットとするオペレーティングシステムとプラットフォームに完全に依存することになります。あなたが言及しているデバイスは一般的なユースケースでは航空機の内部に搭載されているので、Windowsプラットフォームをターゲットにしていないと想定しますが、Linuxまたは組み込みシステムをターゲットにしている可能性があります。このようなプラットフォーム(たとえば:Serial Programming HOW-TO)でシリアルI/Oを実行するために利用可能なリソースがいくつかあります。また、装置のインストールマニュアル(hereのページの途中にあります)のように、「」メッセージフォーマットとメッセージタイプの選択については、SP-4 OEMマニュアルを参照してください。「最も関連性が高く有用ですその文書からの情報。メーカーが実際の通信ルーチンを実装する必要性を否定するため、製造元がプラットフォームにAPIを提供しているかどうかを確認したい場合があります。あなたは、シリアルインターフェースからバイトを読み取ることができたら、あなたはより多くのプログラマに優しいあなたのデータにアクセスするためにstruct sおよびunion秒を活用できる限りデータの感覚を作るとして

、。あなたが提供する大まかなメッセージ概要については、このようなものが適している場合があります:

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)、そのメンバーにアクセス。

編集:編集に応じて、データを理解する方法の例を示します。この例では、心配する必要のあるメッセージタイプは1つしかないと想定していますが、他のタイプに簡単に拡張できます。

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"); 
} 

さて、これらの整数型は、データ伝送のために本当に唯一有用であることを想定し、あなたは、「使用可能なデータ」にこれらのビットを変換する必要があります。これらのフィールドの1つが実際に符号化された浮動小数点数であるとします。 1つの一般的な方式は、ビットウェイト(時に解像度とも呼ばれる)を選択することです。これがあなたのデバイスに直接当てはまるのか、それとも実際の値であるのか分かりませんが、説明のためにフィールドの解像度が0.00014 degrees/bitであるとしましょう。

double YawAngleValue = 0.00014 * serialData.message.YawAngle; 

を...そして、それはそれについてです:doubleへのuint32_t値からメッセージ(serialData.message.YawAngle)の値を変換するには、たとえば、あなたはこれを行う可能性があります。 OEMのマニュアルでは、データがどのようにエンコードされているかを教えてください。また、そこからデコードする方法を理解する必要があります。

ここで、処理するメッセージタイプが2つあるとします。私がすでにあなたに紹介したものと、理論的にはCRITICAL_BITSというメッセージです。

struct _critical_bits 
{ 
    uint8_t DestinationAddress; 
    uint8_t MessageLength; 
    uint8_t MessageType; 
    uint8_t MessageSubtype; 
    uint32_t SomeCriticalData; 
} 

を...そしてそのようstruct myMessage定義に追加:私がレイアウトされてきた方式を使用して、そのタイプを追加するには、まず(以下のおそらくのように)CRITICAL_BITS構造を定義し

struct myMessage 
{ 
    union 
    { 
     char raw[MAX_MESSAGE_SIZE]; //sizeof(largest possible message) 
     struct _message message; 
     struct _critical_bits critical_message; 
    } 
} 

...他のフィールドと同様にSomeCriticalDataにアクセスできます。

if(serialData.message.MessageType == CRITICAL_MESSAGE_TYPE) 
{ 
    uint32_t critical_bits = serialData.critical_message.SomeCriticalData; 
} 

詳細については、structsを参照してください。念頭に置いて、struct myMessageタイプのインスタンスには、一度に意味のあるデータが1セットしか含まれません。より簡単に言えば、にCRITICAL_MESSAGE_TYPEのデータが含まれている場合は、serialData.critical_messageのデータが有効ですが、serialData.messageのデータは要求してもそのデータにアクセスできません。

編集:さらに1つの例;

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などを確認してくださいが、それはあなたを開始する必要があります。

関連する問題