STM32 и SdFat - Не удается создать файл в каталоге на SD-карте

Я использую библиотеку SdFat.h на STM32 и могу успешно создать файл в корневом каталоге с помощью SD.open("test.txt", FILE_WRITE); но мой код не может создать SD.open("DATA/data_test.txt", FILE_WRITE); в каталоге. Вот фрагмент кода, который успешно создает файл в корне:

String final_book_name = upload_book_name + ".txt";
if (SD.exists(final_book_name.c_str())) {
  SD.remove(final_book_name.c_str());
}
tft.println(final_book_name); // This successfully prints "test.txt"
book_file = SD.open(final_book_name, FILE_WRITE);
if (SD.exists(final_book_name.c_str())) {
  tft.print("Created file");
} else {
  tft.print("Failed to create/replace\nfile!");
}

и вот фрагмент кода, который не может создать файл в каталоге:

if (!SD.exists(DATA_DIR)) {
  SD.mkdir(DATA_DIR);
}
String final_book_name = upload_book_name + ".txt";
String book_data_path = DATA_DIR;
book_data_path += "/data_" + final_book_name;
if (SD.exists(book_data_path.c_str())) {
  SD.remove(book_data_path.c_str());
}
tft.println(book_data_path); // This successfully prints "DATA/data_test.txt"
File book_data_file = SD.open(book_data_path, FILE_WRITE);
if (SD.exists(book_data_path.c_str())) {
  book_data_file.print(upload_book_font);
  book_data_file.print("|");
  book_data_file.print("0");
  book_data_file.close();
} else{
  tft.print("Failed to create/replace\ndata file!");
  if (SD.exists(final_book_name.c_str())) {
    SD.remove(final_book_name.c_str());
  }
}

, 👍0

Обсуждение

Попробуй это сделать с помощью /DATA/test.txt Я помню, что библиотека SD использует классические имена файлов 8.3 и `data_test.txt-это недействительно, @DataFiddler

@DataFiddler Я использую SdFat.h с длинными именами (что позволяет использовать имена до 255 символов), @JingleBells


2 ответа


0

Поскольку вы не указали переменную для DATA_DIR

String book_data_path = DATA_DIR;
book_data_path += "/data_" + final_book_name;

таким образом, ваш результирующий путь выглядит следующим образом

DATA_DIR + "/data_" + final_book_name

ЕСЛИ DATA_DIR ="/", то это будет "/" + "/data_" + final_book_name

В качестве подсказки используйте не класс string, а массивы символов

определение

 const char[] DATA_DIR = "/books";  
 char book_data_path [128] = {'\0'};
 char final_book_name [13] =  {'\0'}; //  ЕСЛИ поддержка LFN не используется, то 8.3 !!!
 const char upload_book_name[] = "my_book";
 strcpy (final_book_name, upload_book_name);
 strcat (final_book_name, ".txt");
 Serial.println(final_book_name);

Если вам нужны длинные имена файлов ,используйте библиотеку SdFat или включите LFB с помощью библиотеки (для которой требуется около 35% памяти или памяти SdFat (при использовании длинных имен файлов).
ОТРЕДАКТИРУЙТЕ
, поскольку вы используете SdFat, и я не знаю, какая версия/вилка связана с записью в подкаталоги. Пожалуйста, проверьте следующее:
Чтобы проверить, запустите SdFat\примеры\Функции директории и следите за результатами на своем последовательном мониторе
SdFile.cpp. В строках 782 и 1452 у вас есть (в моей версии):

if (block <= m_vol->cacheBlockNumber()
  && block < (m_vol->cacheBlockNumber() + nb)) {

Рабочий код имеет:

if (m_vol->cacheBlockNumber() <= block
  && block < (m_vol->cacheBlockNumber() + nBlock)) {

Если у вас есть верхняя версия, измените ее, и она будет работать
ОТРЕДАКТИРУЙТЕ 2. Обходите проблемы с ошибочной библиотекой SdFat
Вот код обходного пути

const char DATA_DIR [] = "data";
char final_book_name[128] ={'\0'};
char book_data_path [256] ={'\0'};

if (!SD.exists(DATA_DIR)) {
  SD.mkdir(DATA_DIR);
  SD.chdir(DATA_DIR);
}

strcpy (final_book_name, upload_book_name);
 strcat (final_book_name, ".txt";
String book_data_path = DATA_DIR;

strcpy(book_data_path, "data_");
strcat(book_data_path, final_book_name);

if (SD.exists(book_data_path)) {
  SD.remove(book_data_path);
}
SD.mkdir(book_data_path);
SD.chdir(book_data_path);

tft.println(DATA_DIR);
tft.println(book_data_path); // Это успешно печатает "DATA/data_test.txt"
File book_data_file = SD.open(final_book_name, FILE_WRITE);
if (SD.exists(final_book_name)) {
  book_data_file.print(upload_book_font);
  book_data_file.print("|");
  book_data_file.print("0");
  book_data_file.close();
} else{
  tft.print("Не удалось создать/заменить файл\ndata!");
  if (SD.exists(final_book_name)) {
    SD.remove(final_book_name);
  }
}
,

DATA_DIR-это "ДАННЫЕ". Я не вижу решения в вашем ответе. Я сделаю свои строки символами, это хорошая идея, но как насчет моей главной проблемы здесь?, @JingleBells

Извините, мне все еще неясно, что я должен делать. Я использую STM32, а не Arduino, и у меня нет последовательного монитора. Я попробую загрузить более новую версию SdFat., @JingleBells

Я скачал новейшую версию SdFat отсюда: https://github.com/greiman/SdFat и запустил его, но по-прежнему не удается создать файл в подкаталоге, @JingleBells

Я мог бы попробовать сделать SD.chdir(DATA_DIR); но я не уверен, как именно это работает и даже если в этом проблема. Я не думаю, что SD.chdir(DATA_DIR); необходим, @JingleBells

Я попытался использовать SD.chdir(DATA_DIR); (насколько я знаю, как его использовать), но это не удалось. (он создал файл в корне, а не в директории), @JingleBells

Используйте мою ПРАВКУ 2 оставьте ее на данный момент такой, какая она есть, @Codebreaker007

"Поскольку вы не хотите исправлять свою явно глючную SD.lib", я никогда этого не говорил. Как мне это исправить, у меня нет последовательного монитора?, @JingleBells

Извините за мой цинизм. Но вы раскрываете информацию шаг за шагом, которая должна быть в вашем вопросе с самого начала.На stm32 вам придется переписать программу для вашего Tft. Итак, вы проверили обходной путь.В STM32 библиотека, как известно, создает проблемы, @Codebreaker007

Я понятия не имею, о чем ты говоришь. Спасибо, что попытались мне помочь. Я посмотрю код, который вы опубликовали, и завтра попытаюсь реализовать некоторые его части. Спасибо за помощь., @JingleBells


1

Я нашел проблему. Я неправильно создаю папку каталога. Когда я проверил SD-карту с другого устройства, папка с ДАННЫМИ была недействительной, и создание ее вручную работает. Я поищу решение и опубликую обновление.

ОБНОВЛЕНИЕ: https://forum.arduino.cc/index.php?topic=421131.0 Я попробую сделать это завтра, но это, вероятно, решит проблему.

,