32ビット長を4バイトに変換してから元に戻します-CANバス

したがって、これを2日間試みた後、頭を動かすことができません。

それで私はCANバスを使って加速度計データと時間データを転送しています(71分未満の場合はmicros()関数はunsigned longになる可能性のあるデータを出力します)が、データをバイトとして送信する必要があります。 16ビットintを2バイトにビットシフトすることができましたが、そのメソッドをlongの使用に外挿するのに問題があります(後で追加します)。独自の関数を作成するのが初めてなので、unionメソッドを理解するのに問題があります。皆さんはこれを達成しますか?できるだけ簡単にしてください:)

コメント

  • 合計から最大バイト3を差し引くと、最大バイト2を差し引くと、バイト3が得られます。バイト4は、最大バイト4から数値を引いたものから最大バイト3 + 1を引いたものです。

回答

ビットシフトおよびビット単位および演算子。

これは抽出できる例です。 long変数の個々のバイト。異なる長さの変数に拡張するのは簡単なことだと思います。

void loop() { long a=0x12345678, c=0; byte b[4]; Serial.println("Original:"); Serial.println(a,HEX); delay(1000); Serial.println("Individual bytes:"); for (int i=0; i<4; i++) { b[i]=((a>>(i*8)) & 0xff); //extract the right-most byte of the shifted variable Serial.println(b[i],HEX); delay(1000); } for (int i=0; i<4; i++) { c+=b[i]<<(i*8); } Serial.println("Reconstructed:"); Serial.println(c,HEX); delay(1000); } 

予想されるバイト順序(ビッグエンディアンまたはリトルエンディアン)に応じて、次のようになります。送信前または受信後にバイトを並べ替える必要があります。

コメント

  • 非常にわかりやすく、原則を理解しやすいので、ありがとうございます。ただし、"再構築" 5678しか出力しませんか?
  • 私の回答からコードスニペットをコピーしましたか? nodemcuでコードを実行すると、正しい答えが得られるためです。
  • はい、コードをコピーして貼り付け、void setup();を追加しました。およびSerial.begin(9600);コードを私のarduinonanoで実行するには
  • デフォルトで8ビットAVRで、equalsの右側はデフォルトで16ビットで署名されたint演算になります。だから私は配列をループ内のuint32_tにキャストしました。それが最も効率的な方法かどうかはわかりませんが、機能します。助けてくれてありがとう
  • そうです。 nodemcuを試してみたとき、' arduinoコントローラーについては考えていませんでした。

回答

unionタイプはstructに似ていますが、要素の各メンバーが同じメモリ。 structを定義して2つのメンバー(1つは4バイト型、もう1つは1バイト型の4要素配列)を持つようにすると、同じデータを簡単に参照できます。全体として4バイトの要素として、または必要に応じてバイト単位で。

union packed_long { long l; byte b[4]; }; 

これは型であるため、変数を次のように宣言する必要があります。そのタイプ:

packed_long mydata; 

これで、mydataの2つのサブ要素があります:lおよびb[]

longの値を保存するには、

部分:

mydata.l = myaccel.getY(); 

4バイトのそれぞれにアクセスするには:

byte1 = mydata.b[0]; byte2 = mydata.b[1]; byte3 = mydata.b[2]; byte4 = mydata.b[3]; 

受信側では、次の4バイトをそれぞれ取得します。

mydata.b[0] = canbus.read(); mydata.b[1] = canbus.read(); mydata.b[2] = canbus.read(); mydata.b[4] = canbus.read(); 

同じ順序でバイトを受信する限りそれらを送信した場所で、mydata.llong値にアクセスできるようになりました。

異なるサイズタイプはコンパイラとアーキテクチャに依存するため、値を一定サイズの変数として定義して、常に32ビットで作業できるようにすることもできます。int32_t(符号付き32ビット整数)またはuint32_t(符号なし32ビット整数)。

回答

longを送信する方法は、マスクをオフにしてLSBバイト(CAN標準)を送信してから、シフトすることです。次の1つをLSB位置に、4バイトの場合:

uint32_t data; // Send to CAN bus LSB-first // This method is destructive; data should be a temp if the // Arduino is to retain the data after sending it. for( uint8_t b = 4; b > 0; --b ){ sendByte(data & 0xFF); // send curr byte data >>= 8; // shift that byte away } // Read from CAN bus for( uint8_t b = 4; b > 0; --b ){ data >>= 8; // make room for byte data |= (readByte() << 8); // read next higher byte } // 

コメント

  • OK、CAN標準LSBファーストです。 CANの知識があるので、8バイトのパケットを送信していることがわかりますが、これらのデータは1つか2つだけですか?したがって、合計16バイトの情報の場合、8パケットが必要でしょうか?
  • あなたは私を捕まえました!これは、CANバスについて私が知っているすべてのことについての'であり、ウィキペディアからのものです。オンラインにはCANバスのドキュメントがたくさんあります。その記事'の参考文献は良いスタートです。
  • 8バイトは標準の缶フレームのデータペイロードのサイズです。したがって、16バイトの情報を送信するには2つの標準フレームが必要です。新しいcan-fdは、フレームあたり64バイトのデータペイロードをサポートします。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です