0

私は C++ の初心者で、Arduino 用のプログラムを作成しようとしています。以下のコードは正常にコンパイルされますが、結果は私が期待するものとは異なります。

PC で受け取ると予想されるのは、 0x04 、 0x61 、 0x62 、 0x63 です。

PC で受信するのは、0xff 0x00 0xb1 0x00 です。

遭遇した問題のみに対処するように、コードを最小限に抑えようとしました。

byte *assembleFrame() {
  byte frame[] = { 4 , 'a' , 'b' , 'c' , 'd' };
  return frame;
}

void setup() {
  Serial.begin( 115200 );
};

void loop() {
  byte *frame = assembleFrame();
  Serial.write( frame , 4 );
  // should send 0x04 0x61 0x62 0x63, leaving out 0x64 being 5th element.
  while ( 1 ) {
  }
}

ポインターと関係があると思いますが、わかりません。

ご参考までに:

Serial.write( buf , len ) arguments:    
  buf: an array to send as a series of bytes
  len: the length of the buffer

編集: これまでの解決策:

int assembleFrame( byte *frame ) {
  int octetCounter = 0;
  frame[ octetCounter++ ] = 'A'; // preamble
  frame[ octetCounter++ ] = 'B'; // preamble
  frame[ octetCounter++ ] = 0;   // frame length set at end of function
  frame[ octetCounter++ ] = h;
  frame[ octetCounter++ ] = m;
  frame[ octetCounter++ ] = s;
  frame[ 2 ] = octetCounter;  // frame length

  return frame[ 2 ];
}

void loop() {
  int bytes_in_frame = assembleFrame( frame );
  Serial.write( frame, bytes_in_frame ); // assuming ptr + bytes to send
  delay( 1000 );
}

望ましい結果が得られます。

4

3 に答える 3

3

+Kristerの答えは良いものです。可能であれば、アセンブリ関数にバッファを渡すことを提案することで改善します。

/* Takes in an array of bytes with at least the given size, returns
 * the number of bytes written into the frame.
 */
int assembleFrame(byte *frame, int frame_size) {
  frame[0] =  4;
  frame[1] = 'a';
  frame[2] = 'b';
  frame[3] = 'c';
  frame[4] = 'd';
  return 5; // only used five bytes in the frame
}

  /* then in loop() */
  byte frame[10];
  bytes_in_frame = assembleFrame(frame, 10);
  someDataSendingFunction(frame, bytes_in_frame); // assuming ptr + bytes to send

そうすれば、後でメモリ リークが発生する可能性がなくなります。

于 2012-04-09T20:42:52.060 に答える
1

あなたの assembleFrame() 関数は、関数が戻るときに範囲外になるローカル変数を返します。次のようなことができます。

 byte* assembleFrame() {
      byte* frame = new byte[5];
      frame[0] = 4;
      frame[1] = 'a';
      frame[2] = 'b';
      frame[3] = 'c';
      frame[4] = 'd';
      return frame;
 }

assembleFrame() によって返されたメモリは、次を使用して解放する必要があることに注意してください。

void loop() {
   byte* frame = assembleFrame();
   Serial.write( frame , frame[ 0 ] );
   // release the memory allocated by assembleFrame()
   delete [] frame;
   while ( 1 ) {
   }
}
于 2012-04-09T20:32:17.287 に答える
0

まず第一に、言われているように、ぶら下がっているポインターと未熟な動作が今のところあります。警告 ( -Wall) を有効にすると、次のようになります。

警告: ローカル変数 'frame' のアドレスが返されました

Arduino が埋め込みを行っており、動的な動的メモリ管理を使用することは、リソースの制限により組み込みでは不快です (デフォルトでは new を呼び出すことさえできません)。

  1. frame静的にする:

    char *assembleFrame() {
        static char frame[] = { 'a' , 'b' , 'c' , 'd', 0 };
        return frame;
    }
    

    当然のことながら、呼び出し後にコード内の配列をassembleFrame変更すると、この変更は持続します。

  2. ポインターを作成frame constして文字列を返す

    const char *assembleFrame() {
        const char* frame = "abcd\0";
        return frame;
    }
    
于 2012-04-09T20:53:03.303 に答える