2

我正在尝试在我的 SD 卡上创建一个文件列表,这很容易做到一次,但是当我多次运行程序时,列表要么缩短,要么程序说根本没有文件。

为了使这尽可能简单,我使用了 arduino SD 库附带的 SD 示例,并将设置部分(通常会运行一次)放在循环部分中。这就是我所拥有的。

#include <SD.h>

File root;

void setup()  
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
 while (!Serial) {
  ; // wait for serial port to connect. Needed for Leonardo only
}


Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin 
// (10 on most Arduino boards, 53 on the Mega) must be left as an output 
// or the SD library functions will not work. 
  pinMode(10, OUTPUT);

if (!SD.begin(10)) {
  Serial.println("initialization failed!");
  return;
}
Serial.println("initialization done.");


}

void loop()
{
  Serial.println("hit any key then enter to run the list");
    while(!Serial.available())
    {;}
  Serial.read();
  root = SD.open("/");

  printDirectory(root, 0);

Serial.println("done!");

// nothing happens after setup finishes.
  }

 void printDirectory(File dir, int numTabs) {
    while(true) {

   File entry =  dir.openNextFile();
   if (! entry) {
     // no more files
     //Serial.println("**nomorefiles**");
     break;
     }
   for (uint8_t i=0; i<numTabs; i++) {
     Serial.print('\t');
      }
   Serial.print(entry.name());
   if (entry.isDirectory()) {
     Serial.println("/");
     printDirectory(entry, numTabs+1);
   } else {
     // files have sizes, directories do not
     Serial.print("\t\t");
     Serial.println(entry.size(), DEC);
   }
 }
}

但是在运行它之后我得到了这个奇怪的输出

正在初始化 SD 卡...初始化完成。

点击任意键然后输入运行列表

HFBVYRG.TXT 7

THBVFG.TXT 7

WAZXDSQ.TXT 7

QAZXSW.TXT 21

WSXZAQ.TXT 7

1478523.TXT 7

QWSDFRE.TXT 7

ZXCVBNM.TXT 7

MKOLIJY.TXT 7

完毕!

点击任意键然后输入运行列表

HFBVYRG.TXT 7

THBVFG.TXT 7

WAZXDSQ.TXT 7

QAZXSW.TXT 21

WSXZAQ.TXT 7

1478523.TXT 7

QWSDFRE.TXT 7

ZXCVBNM.TXT 7

MKOLIJY.TXT 7

完毕!

点击任意键然后输入运行列表

HFBVYRG.TXT 7

THBVFG.TXT 7

WAZXDSQ.TXT 7

QAZXSW.TXT 21

完毕!

点击任意键然后输入运行列表

完毕!

点击任意键然后输入运行列表

完毕!

点击任意键然后输入运行列表

完毕!

点击任意键然后输入运行列表

///////////////////////////////////////// //////////////////////////////

如您所见,它变得越来越短,然后完全停止。

有谁知道为什么?

我尝试过使用指针并关闭并重新打开文件,但我什么也没想到。

任何想法将不胜感激。

4

2 回答 2

3

不匹配的 open() 和 close() 不会带来任何好处。每次循环都打开根目录:

root = SD.open("/");

但从不

root.close();

首先,修复此错误,并在尝试打印列表之前检查打开根目录时是否成功:

root = SD.open("/");
if(root) {
  printDirectory(root, 0);
  Serial.println("done!");
  root.close();
}
else {
  Serial.println("failed to open directory");
}

二、关闭目录walk中打开的文件

void printDirectory(File dir, int numTabs) {

  while(true) {
    File entry = dir.openNextFile();
    ...
    entry.close();
  }
  return;
}

最后,考虑不要在循环()中阻塞。其他事情可能发生在你的 loop() 之外,它们将被无限期地阻止,具体取决于你等待按键的时间。一个更典型的代码模式是在循环()中疯狂地旋转,而不是阻塞等待用户输入。例如:

boolean bNeedPrompt = true;

void loop() {
  // Show the prompt once, then mark as displayed so that text does not
  // continuously scroll on the screen
  if(bNeedPrompt) {
    Serial.println("hit any key then enter to run the list");
    bNeedPrompt = false;
  }

  if(Serial.available()) {
    Serial.read();
    // do action
    // set flag so that prompt will display again
    bNeedPrompt = true;
  }

  return;
}
于 2013-06-07T06:53:18.450 回答
1

jdr5ca 的回答解决了您的设置中的许多问题 - 通过不关闭文件,您将泄漏资源,这不会很好地结束。对于像 Arduino 这样的低内存设置而言,这一点尤其重要,它的原始芯片只有 2k RAM,因此在整个代码中都值得牢记。

您剩下的问题的简短答案:它不会完全可预测,但内存不足可能是您的问题的原因。请阅读以获得更多详情。

我最近对 ​​SD 库有过一些类似的经历,尽管原因并不明显。我发现如果我系统上的可用内存低于大约 500 字节(总 RAM 的四分之一),那么 SD 库在尝试列出目录时就会开始表现得很奇怪。

我看到了和你类似的东西,例如:

  1. 列出根目录下的条目并找到两个子目录
  2. 列出其中一个子目录中的条目,效果很好
  3. 列出根目录下的条目,现在我只找到一个子目录!我列出的内容已经消失了!
  4. 我仍然可以列出子目录的内容,即。它还在那里!
  5. 重置 Arduino 并再次启动得到相同的结果,再次显示文件仍然存在于 SD 卡上

我认为所有这一切都归结为 SD 库既非常消耗内存(立即#include SD.h使用了 500 个字节!),并且没有特别明显地处理低内存错误。

因此,如果事情表现得很奇怪,那么:

  1. 检查您的内存使用情况(参见例如freeRam()来自http://playground.arduino.cc/Code/AvailableMemory

  2. 尽可能减少内存使用量。大致顺序:

    • 删除不需要的库
    • 摆脱您不需要的任何硬编码字符串(例如在调用中Serial.print()
    • 对于硬编码的字符串,您确实需要使它们尽可能短,并将它们存储在闪存中(例如Serial.print(F("String in flash"));)而不是 RAM
    • 您目前无法snprintf在闪存中粘贴格式字符串(例如 for ),因此请避免使用这些字符串,而只需手动构建输出(它比较长,但可以节省内存)
    • 确保您在任何地方都使用适当的变量类型(即适合您目的的最小大小的类型) - 如果您有任何数组,则尤其重要,原因很明显!
于 2013-12-06T12:54:14.037 回答