0

I have: Arduino MEGA 2560; Ethernet+SD shield http://www.amazon.com/dp/B0022TWQ22/?tag=stackoverfl08-20 ; SD card 2GB FAT.

SD contains 400 files with names 00000000; 0000001; 0000002; ... 00000098; 0000099; 0000100; ... 00000398; 00000399.

I need to construct String var which will contain all the Filenames separated by ";" like this: sdata = "0000001;0000002;0000003 ... 00000398;00000399;";

Code:

#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() { 
}

Listening to the COM port i see:

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;

How to fix this problem and put all filenames in one variable?

Information for: 400 names and 400 ";" its 3600 bytes. When i try to read any file and put all its contents (more than 3600 bytes) in "String sdata" it works normally. Problem only with listing. Please help me in sorting out this issue.

4

1 回答 1

1

这似乎是您的程序将失败的正确位置。这条无辜的线是你的问题:

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

像这样的字符串连接将在短时间内使用 2X 的 sdata 内存。这就是您应该如何查看该行中的操作顺序

// 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,因此无法执行上述操作。

这展示了关于字符串的几点。您在一行上的串联不一定比这两行形式更好:

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

在第二种形式中,您可以确保中间结果只有一个临时变量。

这导致下一个提示。您应该在想我将如何逃避临时变量。这就是我们有 += 运算符的原因。你最好的机会是像这样连接:

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

如果 += 运算符在 String 类上可用,编译器将使用它。该运算符可能能够使用更节省内存的连接方式。例如,如果字符串预先分配了一些额外的内存,那么它可以将新字符放入现有缓冲区。

总的来说,这是一个很好的学习受限内存空间中字符串的方法,因为您必须了解一些在大型 CPU 环境中经常被忽略的编译器内部和运算符细节。

鉴于您建议的大小,如果您更改为预先构建字符串缓冲区并用文件名填充它的方法,您可能只能适合 RAM 。换句话说:不要在微控制器上使用 String 。

于 2013-01-14T00:20:08.003 回答