У меня проблема с пониманием работы этой библиотеки, после применения встроенной библиотеки SD.h
Я пытаюсь подсчитать количество файлов и папок на карте памяти. В примерах библиотеки SD есть пример “listfiles”. На основе этого примера я написал код, который вел такой подсчет числа папок и файлов. Но работал этот код жутко медленно. В итоге я принял решение переходить на работу с библиотекой SdFat. В границах первого этапа я объявил структуру “SdFat SD;” и в рамках версии библиотеки SdFat [2.2.2] код отлично работал и очень шустро. Но с выходом обновления библиотеки SdFat [2.2.3] рекурсия, которая содержалась в функции
void printDirectory(File dir, int numTabs); стала вызывать ошибку.
Текст listfiles из примеров библиотеки SD я приводить не буду.
Что касается примеров из библиотеки SdFat, то есть только OpenNext, но он выводит имена файлов и папок корневого каталога.
Вот попытка написать свой код на основе данного примера.
#include "SdFat.h"
#include <SPI.h>
#define SD_CS 10
// SD_FAT_TYPE = 0 for SdFat/File as defined in SdFatConfig.h,
// 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT.
#define SD_FAT_TYPE 3
#if SD_FAT_TYPE == 0
SdFat sd;
File entry, currentDir;
#elif SD_FAT_TYPE == 1
SdFat32 sd;
File32 entry, currentDir;
#elif SD_FAT_TYPE == 2
SdExFat sd;
ExFile entry, currentDir;
#elif SD_FAT_TYPE == 3
SdFs sd;
FsFile entry, currentDir;
#else // SD_FAT_TYPE
#error Invalid SD_FAT_TYPE
#endif // SD_FAT_TYPE
uint16_t fileCnt;
uint16_t dirCnt;
void setup() {
Serial.begin(9600);
while (!Serial) {
// wait for serial port to connect. Needed for native USB port only
}
Serial.print(F("\nInitializing SD card..."));
while (!sd.begin(SD_CS, SD_SCK_MHZ(4))) {
delay(1000);
Serial.println(F("initialization failed. Things to check:"));
Serial.println(F("* is a card inserted?"));
}
currentDir.close();
currentDir.open("/", O_RDONLY); //set file to root directory
scanSD(); // подсчитываем число папок и файлов
Serial.print(F("DIRs: \t")); Serial.println(dirCnt);
Serial.print(F("FILEs: \t")); Serial.println(fileCnt);
}
void loop() {}
void scanSD() {
Serial.println(F("Debug ScanSD"));
while(entry.openNext(¤tDir, O_RDONLY)) {
if (entry.isDir() && !entry.isHidden()) {
Serial.print(F("/")); Serial.print(dirCnt);
Serial.println(F(" DIR Found..."));
dirCnt++;
// scanSD();
}
if (entry.isFile()) {
Serial.println(F("FILE Found..."));
fileCnt++;
}
entry.close();
}
}
проблема в том, что этим кодом я не попадаю в внутрь папки и подсчета файлов не происходит.
рекурсия должна быть по закомментированному вызову функции
// scanSD();
Только в примере библиотеки SD у аналогичной функции должен быть аргумент в виде
scanSD(File dir);
Но как раз на это и ругается версия 2.2.3 библиотеки SdFat
Растолкуйте, пожалуйста, как получить мне искомый вариант! Может есть пример такой функции?
Почему бы не пользоваться той версией библиотеки, в которой все работает?
И, кстати, именно в коде этой библиотеки, вероятно, и можно найти искомый Вами пример функции.
#include "SdFat.h"
#include <SPI.h>
#define SD_CS 10
SdFat SD;
File root;
#define filenameLength 64
uint16_t fileCnt;
uint16_t dirCnt;
char fName[filenameLength + 1];
void setup() {
Serial.begin(9600);
while (!Serial) {
// wait for serial port to connect. Needed for native USB port only
}
Serial.print(F("\nInitializing SD card..."));
while (!SD.begin(SD_CS)) {
delay(1000);
Serial.println(F("initialization failed. Things to check:"));
Serial.println(F("* is a card inserted?"));
}
Serial.println(F("Wiring is correct and a card is present."));
fileCnt = dirCnt = 0;
root = SD.open("/", O_READ);
if (!root) root.rewindDirectory(); //возвращаемся к первому файлу, если файл не существует
scanSD(root); // подсчитываем число папок и файлов
root.close();
Serial.print(F("DIRs: \t")); Serial.println(dirCnt);
Serial.print(F("FILEs: \t")); Serial.println(fileCnt);
}
void loop() {}
void scanSD(File dir) {
while (true) {
File entry = dir.openNextFile();
if (!entry) break; // no more files
if (entry.isDirectory()) {
entry.getName(fName, filenameLength);
Serial.print("/"); Serial.println(fName);
dirCnt++;
scanSD(entry);
}
else {
fileCnt++;
}
entry.close();
}
}
Вот этот код подсчитывает число папок и файлов с библиотекой SdFat [2.2.2].
С библиотекой [2.2.3] компилятор выдаёт ошибку
G:\Arduino\SD_SdFat_scanSD\SD_SdFat_scanSD.ino: In function 'void setup()':
SD_SdFat_scanSD:29:14: error: use of deleted function 'File32::File32(const File32&)'
scanSD(root); // подсчитываем число папок и файлов
^
In file included from C:\Users\Documents\Arduino\libraries\SdFat\src/FatLib/FatVolume.h:27:0,
from C:\Users\Documents\Arduino\libraries\SdFat\src/FatLib/FatLib.h:28,
from C:\Users\Documents\Arduino\libraries\SdFat\src/SdFat.h:32,
from G:\Arduino\SD_SdFat_scanSD\SD_SdFat_scanSD.ino:1:
C:\Users\Documents\Arduino\libraries\SdFat\src/FatLib/FatFile.h:1088:7: note: 'File32::File32(const File32&)' is implicitly deleted because the default definition would be ill-formed:
class File32 : public StreamFile<FatFile, uint32_t> {
^~~~~~
C:\Users\Documents\Arduino\libraries\SdFat\src/FatLib/FatFile.h:1088:7: error: use of deleted function 'StreamFile<FatFile, long unsigned int>::StreamFile(const StreamFile<FatFile, long unsigned int>&)'
In file included from C:\Users\Documents\Arduino\libraries\SdFat\src/ExFatLib/ExFatFile.h:883:0,
from C:\Users\Documents\Arduino\libraries\SdFat\src/ExFatLib/ExFatVolume.h:27,
from C:\Users\Documents\Arduino\libraries\SdFat\src/ExFatLib/ExFatLib.h:28,
from C:\Users\Documents\Arduino\libraries\SdFat\src/SdFat.h:31,
from G:\Arduino\SD_SdFat_scanSD\SD_SdFat_scanSD.ino:1:
c:\users\documents\arduino\libraries\sdfat\src\common\arduinofiles.h:61:7: note: 'StreamFile<FatFile, long unsigned int>::StreamFile(const StreamFile<FatFile, long unsigned int>&)' is implicitly deleted because the default definition would be ill-formed:
class StreamFile : public stream_t, public BaseFile {
^~~~~~~~~~
c:\users\documents\arduino\libraries\sdfat\src\common\arduinofiles.h:61:7: error: 'constexpr FatFile::FatFile(const FatFile&)' is private within this context
In file included from C:\Users\Documents\Arduino\libraries\SdFat\src/FatLib/FatVolume.h:27:0,
from C:\Users\Documents\Arduino\libraries\SdFat\src/FatLib/FatLib.h:28,
from C:\Users\Documents\Arduino\libraries\SdFat\src/SdFat.h:32,
from G:\Arduino\SD_SdFat_scanSD\SD_SdFat_scanSD.ino:1:
C:\Users\Documents\Arduino\libraries\SdFat\src/FatLib/FatFile.h:157:3: note: declared private here
FatFile(const FatFile& from) = default;
^~~~~~~
G:\Arduino\SD_SdFat_scanSD\SD_SdFat_scanSD.ino:37:6: note: initializing argument 1 of 'void scanSD(File)'
void scanSD(File dir) {
^~~~~~
G:\Arduino\SD_SdFat_scanSD\SD_SdFat_scanSD.ino: In function 'void scanSD(File)':
SD_SdFat_scanSD:45:19: error: use of deleted function 'File32::File32(const File32&)'
scanSD(entry);
^
G:\Arduino\SD_SdFat_scanSD\SD_SdFat_scanSD.ino:37:6: note: initializing argument 1 of 'void scanSD(File)'
void scanSD(File dir) {
^~~~~~
exit status 1
use of deleted function 'File32::File32(const File32&)'
Правильнее исправить ваш код. В той строке, где ошибка - вы передаете внутрь своей функции scanSD обьект каталога по значению. Так не надо делать, это плохой стиль.
Передавайте его по ссылке - и никаких ошибок не будет.
Да, Вы правы! С указателем на адрес данная функция заработала без проблем с библиотекой [2.2.3]. Огромное спасибо за подсказку!
Но тем не менее, мне бы в рамках данной темы все-таки хотелось бы понять, как подобную функцию можно написать для библиотеки SdFat? Сделал функцию с указателем, но все равно функция openNext() не заходит в папку и нет подсчета числа файлов.
Функцию void scanSD() из первого сообщения нужно заменить на
Ну что ж, давайте разбираться! Я сам не люблю путаницу.
С Вашей подсказкой у меня заработал код из сообщения #5. Но это код, который написан в режиме совместимости двух библиотек. Для этого объявлена структура
SdFat SD;
И все функции в данном листинге принадлежат встроенной библиотеке SD.h за исключением функции чтения имени файла
entry.getName(fName, filenameLength); //для SdFat
Но моё желание полностью уйти от от функций библиотеки SD.h и переписать код для библиотеки SdFat.h.
Сейчас он выглядит так:
#include "SdFat.h"
#include <SPI.h>
#define SD_CS 10
SdFat SD;
File root;
#define filenameLength 64
uint16_t fileCnt;
uint16_t dirCnt;
char fName[filenameLength + 1];
void setup() {
Serial.begin(9600);
while (!Serial) {
// wait for serial port to connect. Needed for native USB port only
}
Serial.print(F("\nInitializing SD card..."));
while (!SD.begin(SD_CS)) {
delay(1000);
Serial.println(F("initialization failed. Things to check:"));
Serial.println(F("* is a card inserted?"));
}
Serial.println(F("Wiring is correct and a card is present."));
fileCnt = dirCnt = 0;
root = SD.open("/", O_READ);
if (!root) root.rewindDirectory(); //возвращаемся к первому файлу, если файл не существует
scanSD(root); // подсчитываем число папок и файлов
root.close();
Serial.print(F("DIRs: \t")); Serial.println(dirCnt);
Serial.print(F("FILEs: \t")); Serial.println(fileCnt);
}
void loop() {}
void scanSD(FsFile &dir) {
while(entry.openNext(&dir, O_RDONLY)) {
if (entry.isDir() && !entry.isHidden()) {
Serial.print(F("/")); Serial.println(dirCnt);
// Serial.println(F(" DIR Found..."));
dirCnt++;
scanSD(entry);
}
else if (entry.isFile()) {
Serial.println(F("FILE Found..."));
fileCnt++;
}
entry.close();
}
}
Но при работе этого кода я читаю только корневой каталог файлов без подсчета общего числа файлов. Это вывод с монитора:
Initializing SD card...Wiring is correct and a card is present.
Debug ScanSD
/0
/1
/2
/3
/4
/5
/6
/7
/8
/9
/10
DIRs: 11
FILEs: 0
сейчас на подопытной карте памяти содержится именно 11 папок и 534 файла. Но подсчет файлов не происходит
Да в том и дело, что остаётся только гадать, ибо примера на эту тему автор библиотеки не предоставил. А я не супер программист, чтобы разобраться в чем причина. Я же не первый день вожусь прежде чем решился создать тему и задать вопрос
Я заглянул в исходники библиотеки - и это сотни отдельных файлов. К сожалению, я не имею сейчас возможности искать в них готовое решение. Организация кода, прямо скажем, не располагает…
не прибедняйтесь. Насколько я могу судить, ваш уровень понимания на голову выше большинства любителей. Я думаю, вы найдете ответ. Побольше тестов, чтобы понять что как работает - и решение отыщется.
Я бы с удовольствием в этом поучаствовал, но это явно не на 20 минут, сорри
Удачи