0

私が持っているもの:Arduino MEGA 2560; イーサネット+SDシールドhttp://www.amazon.com/dp/B0022TWQ22/?tag=stackoverfl08-20 ; SDカード2GBFAT。

SDには、名前が00000000の400個のファイルが含まれています。0000001; 0000002; ... 00000098; 0000099; 0000100; ... 00000398; 00000399。

「;」で区切られたすべてのファイル名を含むStringvarを作成する必要があります。このように:sdata = "0000001; 0000002; 0000003 ... 00000398; 00000399;";

コード:

#include <SdFat.h>
#include <SPI.h>


const uint16_t chipSelect = SS;
char cnamefile[9];
String sdata="";
SdFat sd;
SdFile file;

void setup() {


  Serial.begin(9600);
  Serial.println("hi");
  sdata="";
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
    Serial.println("List files");
    while (file.openNext(sd.vwd(), O_READ)) {
      file.getFilename(cnamefile);
      file.close();
      sdata = sdata + String(cnamefile) + ";";

    }
  Serial.print(sdata);
}

void loop() { 
}

私が見るCOMポートを聞いています:

hi
List files
00000005;00000006;00000007;00000008;00000009;00000010;00000011;00000012;00000013;00000014;00000015;00000016;00000017;00000018;00000019;00000020;00000021;00000022;00000023;00000024;00000025;00000026;00000027;00000028;00000029;00000030;00000031;00000032;00000033;00000034;00000035;00000036;00000037;00000038;00000039;00000040;00000041;00000042;00000043;00000044;00000045;00000046;00000047;00000048;00000049;00000050;00000051;00000052;00000053;00000054;00000055;00000056;00000057;00000058;00000059;00000060;00000061;00000062;00000063;00000064;00000065;00000066;00000067;00000068;00000069;00000070;00000071;00000072;00000073;00000074;00000075;00000076;00000077;00000078;

この問題を修正し、すべてのファイル名を1つの変数に入れる方法は?

情報:400名と400 ";" その3600バイト。ファイルを読み取ってそのすべての内容(3600バイト以上)を「Stringsdata」に入れようとすると、正常に機能します。リストのみに問題があります。この問題を整理するのを手伝ってください。

4

1 に答える 1

1

これはあなたのプログラムが失敗する正しい場所についてのようです。この無実の線はあなたの問題です:

sdata = sdata + String(cnamefile) + ";";

このような文字列連結では、sdataの2倍のメモリが短時間使用されます。これは、その1行で一連の操作を表示する方法です。

// compiler has done this for you:
String temp1234 = sdata + String();

// note that at this moment, memory usage is now 2x sdata

String temp1235 = temp1234 + ";";

// now you can have 3x the memory used

// assignment to variable
sdata = temp1235;

// now can delete temporary variable
// compiler will do this
//temp1234.delete()
//temp1235.delete()

最大3kバイトの文字列を作成しようとしていますが、合計RAMが8kしかないため、上記を実行できません。

これは、文字列に関するいくつかのポイントを示しています。上記の1行の連結は、必ずしもこの2行形式よりも優れているとは限りません。

sdata = sdata + String(cnamefile);
sdata = sdata  + ";";

この2番目の形式では、中間結果の一時変数が1つだけになることが保証されます。

これは次のヒントにつながります。一時変数をどのようにエスケープするかを考えておく必要があります。そのため、+=演算子があります。最善のチャンスは、次のように連結することです。

sdata += String(cnamefile);
sdata += ";";

Stringクラスで+=演算子が使用可能な場合、コンパイラはこれを使用します。その演算子は、よりメモリ効率の高い連結方法を使用できる場合があります。たとえば、文字列に追加のメモリが事前に割り当てられている場合は、新しい文字を既存のバッファに配置するだけで済みます。

大規模なCPU環境では無視されることが多いコンパイラの内部と演算子の詳細を理解する必要があるため、一般に、これは制約のあるメモリ空間の文字列に関する優れた学習方法です。

提案しているサイズを考えると、文字列バッファを事前に構築してファイル名で埋めるというアプローチに変更した場合にのみ、RAMに収まる可能性があります。言い換えると、マイクロコントローラーでStringを使用しないでください。

于 2013-01-14T00:20:08.003 に答える