mirror of
https://github.com/arduino/Arduino.git
synced 2025-03-01 23:29:28 +01:00
Incorporating ladyada's SD changes (multifile & directories).
Grabbed a patch from this repository: https://github.com/adafruit/SD and updated it for Arduino 1.0 (using Arduino.h instead of WProgram.h).
This commit is contained in:
parent
9f412a2628
commit
059bc5f022
@ -14,52 +14,130 @@
|
|||||||
|
|
||||||
#include <SD.h>
|
#include <SD.h>
|
||||||
|
|
||||||
|
/* for debugging file open/close leaks
|
||||||
|
uint8_t nfilecount=0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
File::File(SdFile f, char *n) {
|
||||||
|
// oh man you are kidding me, new() doesnt exist? Ok we do it by hand!
|
||||||
|
_file = (SdFile *)malloc(sizeof(SdFile));
|
||||||
|
if (_file) {
|
||||||
|
memcpy(_file, &f, sizeof(SdFile));
|
||||||
|
|
||||||
|
strncpy(_name, n, 12);
|
||||||
|
_name[12] = 0;
|
||||||
|
|
||||||
|
/* for debugging file open/close leaks
|
||||||
|
nfilecount++;
|
||||||
|
Serial.print("Created \"");
|
||||||
|
Serial.print(n);
|
||||||
|
Serial.print("\": ");
|
||||||
|
Serial.println(nfilecount, DEC);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File::File(void) {
|
||||||
|
_file = 0;
|
||||||
|
_name[0] = 0;
|
||||||
|
//Serial.print("Created empty file object");
|
||||||
|
}
|
||||||
|
|
||||||
|
File::~File(void) {
|
||||||
|
// Serial.print("Deleted file object");
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a pointer to the file name
|
||||||
|
char *File::name(void) {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// a directory is a special type of file
|
||||||
|
boolean File::isDirectory(void) {
|
||||||
|
return (_file && _file->isDir());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void File::write(uint8_t val) {
|
void File::write(uint8_t val) {
|
||||||
SD.file.write(val);
|
if (_file)
|
||||||
|
_file->write(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::write(const char *str) {
|
void File::write(const char *str) {
|
||||||
SD.file.write(str);
|
if (_file)
|
||||||
|
_file->write(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::write(const uint8_t *buf, size_t size) {
|
void File::write(const uint8_t *buf, size_t size) {
|
||||||
SD.file.write(buf, size);
|
if (_file)
|
||||||
|
_file->write(buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int File::peek() {
|
int File::peek() {
|
||||||
char c = SD.file.read();
|
if (! _file)
|
||||||
if (c != -1) SD.file.seekCur(-1);
|
return 0;
|
||||||
|
|
||||||
|
int c = _file->read();
|
||||||
|
if (c != -1) _file->seekCur(-1);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int File::read() {
|
int File::read() {
|
||||||
return SD.file.read();
|
if (_file)
|
||||||
|
return _file->read();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// buffered read for more efficient, high speed reading
|
||||||
|
int File::read(void *buf, uint16_t nbyte) {
|
||||||
|
if (_file)
|
||||||
|
return _file->read(buf, nbyte);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int File::available() {
|
int File::available() {
|
||||||
|
if (! _file) return 0;
|
||||||
return size() - position();
|
return size() - position();
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::flush() {
|
void File::flush() {
|
||||||
SD.file.sync();
|
if (_file)
|
||||||
|
_file->sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean File::seek(uint32_t pos) {
|
boolean File::seek(uint32_t pos) {
|
||||||
return SD.file.seekSet(pos);
|
if (! _file) return false;
|
||||||
|
|
||||||
|
return _file->seekSet(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t File::position() {
|
uint32_t File::position() {
|
||||||
return SD.file.curPosition();
|
if (! _file) return -1;
|
||||||
|
return _file->curPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t File::size() {
|
uint32_t File::size() {
|
||||||
return SD.file.fileSize();
|
if (! _file) return 0;
|
||||||
|
return _file->fileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void File::close() {
|
void File::close() {
|
||||||
SD.file.close();
|
if (_file) {
|
||||||
|
_file->close();
|
||||||
|
free(_file);
|
||||||
|
_file = 0;
|
||||||
|
|
||||||
|
/* for debugging file open/close leaks
|
||||||
|
nfilecount--;
|
||||||
|
Serial.print("Deleted ");
|
||||||
|
Serial.println(nfilecount, DEC);
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File::operator bool() {
|
File::operator bool() {
|
||||||
return SD.file.isOpen();
|
if (_file)
|
||||||
|
return _file->isOpen();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,3 +9,5 @@ License: GNU General Public License V3
|
|||||||
|
|
||||||
(C) Copyright 2010 SparkFun Electronics
|
(C) Copyright 2010 SparkFun Electronics
|
||||||
|
|
||||||
|
Now better than ever with optimization, multiple file support, directory handling, etc - ladyada!
|
||||||
|
|
||||||
|
@ -275,10 +275,10 @@ boolean callback_makeDirPath(SdFile& parentDir, char *filePathComponent,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
boolean callback_openPath(SdFile& parentDir, char *filePathComponent,
|
boolean callback_openPath(SdFile& parentDir, char *filePathComponent,
|
||||||
boolean isLastComponent, void *object) {
|
boolean isLastComponent, void *object) {
|
||||||
/*
|
|
||||||
|
|
||||||
Callback used to open a file specified by a filepath that may
|
Callback used to open a file specified by a filepath that may
|
||||||
specify one or more directories above it.
|
specify one or more directories above it.
|
||||||
@ -293,7 +293,6 @@ boolean callback_openPath(SdFile& parentDir, char *filePathComponent,
|
|||||||
Returns false once the file has been opened--to prevent the traversal
|
Returns false once the file has been opened--to prevent the traversal
|
||||||
from descending further. (This may be unnecessary.)
|
from descending further. (This may be unnecessary.)
|
||||||
|
|
||||||
*/
|
|
||||||
if (isLastComponent) {
|
if (isLastComponent) {
|
||||||
SDClass *p_SD = static_cast<SDClass*>(object);
|
SDClass *p_SD = static_cast<SDClass*>(object);
|
||||||
p_SD->file.open(parentDir, filePathComponent, p_SD->fileOpenMode);
|
p_SD->file.open(parentDir, filePathComponent, p_SD->fileOpenMode);
|
||||||
@ -305,6 +304,8 @@ boolean callback_openPath(SdFile& parentDir, char *filePathComponent,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
boolean callback_remove(SdFile& parentDir, char *filePathComponent,
|
boolean callback_remove(SdFile& parentDir, char *filePathComponent,
|
||||||
@ -345,6 +346,64 @@ boolean SDClass::begin(uint8_t csPin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// this little helper is used to traverse paths
|
||||||
|
SdFile SDClass::getParentDir(char *filepath, int *index) {
|
||||||
|
// get parent directory
|
||||||
|
SdFile d1 = root; // start with the mostparent, root!
|
||||||
|
SdFile d2;
|
||||||
|
|
||||||
|
// we'll use the pointers to swap between the two objects
|
||||||
|
SdFile *parent = &d1;
|
||||||
|
SdFile *subdir = &d2;
|
||||||
|
|
||||||
|
char *origpath = filepath;
|
||||||
|
|
||||||
|
while (strchr(filepath, '/')) {
|
||||||
|
|
||||||
|
// get rid of leading /'s
|
||||||
|
if (filepath[0] == '/') {
|
||||||
|
filepath++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! strchr(filepath, '/')) {
|
||||||
|
// it was in the root directory, so leave now
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract just the name of the next subdirectory
|
||||||
|
uint8_t idx = strchr(filepath, '/') - filepath;
|
||||||
|
if (idx > 12)
|
||||||
|
idx = 12; // dont let them specify long names
|
||||||
|
char subdirname[13];
|
||||||
|
strncpy(subdirname, filepath, idx);
|
||||||
|
subdirname[idx] = 0;
|
||||||
|
|
||||||
|
// close the subdir (we reuse them) if open
|
||||||
|
subdir->close();
|
||||||
|
if (! subdir->open(parent, subdirname, O_READ)) {
|
||||||
|
// failed to open one of the subdirectories
|
||||||
|
return SdFile();
|
||||||
|
}
|
||||||
|
// move forward to the next subdirectory
|
||||||
|
filepath += idx;
|
||||||
|
|
||||||
|
// we reuse the objects, close it.
|
||||||
|
parent->close();
|
||||||
|
|
||||||
|
// swap the pointers
|
||||||
|
SdFile *t = parent;
|
||||||
|
parent = subdir;
|
||||||
|
subdir = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
*index = (int)(filepath - origpath);
|
||||||
|
// parent is now the parent diretory of the file!
|
||||||
|
return *parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
File SDClass::open(char *filepath, uint8_t mode) {
|
File SDClass::open(char *filepath, uint8_t mode) {
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -369,6 +428,72 @@ File SDClass::open(char *filepath, uint8_t mode) {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int pathidx;
|
||||||
|
|
||||||
|
// do the interative search
|
||||||
|
SdFile parentdir = getParentDir(filepath, &pathidx);
|
||||||
|
// no more subdirs!
|
||||||
|
|
||||||
|
filepath += pathidx;
|
||||||
|
|
||||||
|
if (! filepath[0]) {
|
||||||
|
// it was the directory itself!
|
||||||
|
return File(parentdir, "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file itself
|
||||||
|
SdFile file;
|
||||||
|
|
||||||
|
// failed to open a subdir!
|
||||||
|
if (!parentdir.isOpen())
|
||||||
|
return File();
|
||||||
|
|
||||||
|
// there is a special case for the Root directory since its a static dir
|
||||||
|
if (parentdir.isRoot()) {
|
||||||
|
if ( ! file.open(SD.root, filepath, mode)) {
|
||||||
|
// failed to open the file :(
|
||||||
|
return File();
|
||||||
|
}
|
||||||
|
// dont close the root!
|
||||||
|
} else {
|
||||||
|
if ( ! file.open(parentdir, filepath, mode)) {
|
||||||
|
return File();
|
||||||
|
}
|
||||||
|
// close the parent
|
||||||
|
parentdir.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode & (O_APPEND | O_WRITE))
|
||||||
|
file.seekSet(file.fileSize());
|
||||||
|
return File(file, filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
File SDClass::open(char *filepath, uint8_t mode) {
|
||||||
|
//
|
||||||
|
|
||||||
|
Open the supplied file path for reading or writing.
|
||||||
|
|
||||||
|
The file content can be accessed via the `file` property of
|
||||||
|
the `SDClass` object--this property is currently
|
||||||
|
a standard `SdFile` object from `sdfatlib`.
|
||||||
|
|
||||||
|
Defaults to read only.
|
||||||
|
|
||||||
|
If `write` is true, default action (when `append` is true) is to
|
||||||
|
append data to the end of the file.
|
||||||
|
|
||||||
|
If `append` is false then the file will be truncated first.
|
||||||
|
|
||||||
|
If the file does not exist and it is opened for writing the file
|
||||||
|
will be created.
|
||||||
|
|
||||||
|
An attempt to open a file for reading that does not exist is an
|
||||||
|
error.
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
// TODO: Allow for read&write? (Possibly not, as it requires seek.)
|
// TODO: Allow for read&write? (Possibly not, as it requires seek.)
|
||||||
|
|
||||||
fileOpenMode = mode;
|
fileOpenMode = mode;
|
||||||
@ -377,6 +502,7 @@ File SDClass::open(char *filepath, uint8_t mode) {
|
|||||||
return File();
|
return File();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
//boolean SDClass::close() {
|
//boolean SDClass::close() {
|
||||||
@ -436,4 +562,55 @@ boolean SDClass::remove(char *filepath) {
|
|||||||
return walkPath(filepath, root, callback_remove);
|
return walkPath(filepath, root, callback_remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDClass SD;
|
|
||||||
|
// allows you to recurse into a directory
|
||||||
|
File File::openNextFile(uint8_t mode) {
|
||||||
|
dir_t p;
|
||||||
|
|
||||||
|
//Serial.print("\t\treading dir...");
|
||||||
|
while (_file->readDir(&p) > 0) {
|
||||||
|
|
||||||
|
// done if past last used entry
|
||||||
|
if (p.name[0] == DIR_NAME_FREE) {
|
||||||
|
//Serial.println("end");
|
||||||
|
return File();
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip deleted entry and entries for . and ..
|
||||||
|
if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') {
|
||||||
|
//Serial.println("dots");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only list subdirectories and files
|
||||||
|
if (!DIR_IS_FILE_OR_SUBDIR(&p)) {
|
||||||
|
//Serial.println("notafile");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print file name with possible blank fill
|
||||||
|
SdFile f;
|
||||||
|
char name[13];
|
||||||
|
_file->dirName(p, name);
|
||||||
|
//Serial.print("try to open file ");
|
||||||
|
//Serial.println(name);
|
||||||
|
|
||||||
|
if (f.open(_file, name, mode)) {
|
||||||
|
//Serial.println("OK!");
|
||||||
|
return File(f, name);
|
||||||
|
} else {
|
||||||
|
//Serial.println("ugh");
|
||||||
|
return File();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Serial.println("nothing");
|
||||||
|
return File();
|
||||||
|
}
|
||||||
|
|
||||||
|
void File::rewindDirectory(void) {
|
||||||
|
if (isDirectory())
|
||||||
|
_file->rewind();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDClass SD;
|
||||||
|
@ -24,7 +24,14 @@
|
|||||||
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_SYNC)
|
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_SYNC)
|
||||||
|
|
||||||
class File : public Stream {
|
class File : public Stream {
|
||||||
|
private:
|
||||||
|
char _name[13]; // our name
|
||||||
|
SdFile *_file; // underlying file pointer
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
File(SdFile f, char *name); // wraps an underlying SdFile
|
||||||
|
File(void); // 'empty' constructor
|
||||||
|
~File(void); // destructor
|
||||||
virtual void write(uint8_t);
|
virtual void write(uint8_t);
|
||||||
virtual void write(const char *str);
|
virtual void write(const char *str);
|
||||||
virtual void write(const uint8_t *buf, size_t size);
|
virtual void write(const uint8_t *buf, size_t size);
|
||||||
@ -32,11 +39,17 @@ public:
|
|||||||
virtual int peek();
|
virtual int peek();
|
||||||
virtual int available();
|
virtual int available();
|
||||||
virtual void flush();
|
virtual void flush();
|
||||||
|
int read(void *buf, uint16_t nbyte);
|
||||||
boolean seek(uint32_t pos);
|
boolean seek(uint32_t pos);
|
||||||
uint32_t position();
|
uint32_t position();
|
||||||
uint32_t size();
|
uint32_t size();
|
||||||
void close();
|
void close();
|
||||||
operator bool();
|
operator bool();
|
||||||
|
char * name();
|
||||||
|
|
||||||
|
boolean isDirectory(void);
|
||||||
|
File openNextFile(uint8_t mode = O_RDONLY);
|
||||||
|
void rewindDirectory(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SDClass {
|
class SDClass {
|
||||||
@ -47,6 +60,8 @@ private:
|
|||||||
SdVolume volume;
|
SdVolume volume;
|
||||||
SdFile root;
|
SdFile root;
|
||||||
|
|
||||||
|
// my quick&dirty iterator, should be replaced
|
||||||
|
SdFile getParentDir(char *filepath, int *indx);
|
||||||
public:
|
public:
|
||||||
// This needs to be called to set up the connection to the SD card
|
// This needs to be called to set up the connection to the SD card
|
||||||
// before other methods are used.
|
// before other methods are used.
|
||||||
@ -70,7 +85,6 @@ public:
|
|||||||
boolean rmdir(char *filepath);
|
boolean rmdir(char *filepath);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SdFile file;
|
|
||||||
|
|
||||||
// This is used to determine the mode used to open a file
|
// This is used to determine the mode used to open a file
|
||||||
// it's here because it's the easiest place to pass the
|
// it's here because it's the easiest place to pass the
|
||||||
|
108
libraries/SD/examples/CardInfo/CardInfo.pde
Normal file
108
libraries/SD/examples/CardInfo/CardInfo.pde
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
SD card test
|
||||||
|
|
||||||
|
This example shows how use the utility libraries on which the'
|
||||||
|
SD library is based in order to get info about your SD card.
|
||||||
|
Very useful for testing a card when you're not sure whether its working or not.
|
||||||
|
|
||||||
|
The circuit:
|
||||||
|
* SD card attached to SPI bus as follows:
|
||||||
|
** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
|
||||||
|
** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
|
||||||
|
** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
|
||||||
|
** CS - depends on your SD card shield or module
|
||||||
|
|
||||||
|
|
||||||
|
created 28 Mar 2011
|
||||||
|
by Limor Fried
|
||||||
|
*/
|
||||||
|
// include the SD library:
|
||||||
|
#include <SD.h>
|
||||||
|
|
||||||
|
// set up variables using the SD utility library functions:
|
||||||
|
Sd2Card card;
|
||||||
|
SdVolume volume;
|
||||||
|
SdFile root;
|
||||||
|
|
||||||
|
// change this to match your SD shield or module;
|
||||||
|
// Arduino Ethernet shield: pin 4
|
||||||
|
// Adafruit SD shields and modules: pin 10
|
||||||
|
// Sparkfun SD shield: pin 8
|
||||||
|
const int chipSelect = 8;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
Serial.print("\nInitializing 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); // change this to 53 on a mega
|
||||||
|
|
||||||
|
|
||||||
|
// we'll use the initialization code from the utility libraries
|
||||||
|
// since we're just testing if the card is working!
|
||||||
|
if (!card.init(SPI_HALF_SPEED, chipSelect)) {
|
||||||
|
Serial.println("initialization failed. Things to check:");
|
||||||
|
Serial.println("* is a card is inserted?");
|
||||||
|
Serial.println("* Is your wiring correct?");
|
||||||
|
Serial.println("* did you change the chipSelect pin to match your shield or module?");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Serial.println("Wiring is correct and a card is present.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the type of card
|
||||||
|
Serial.print("\nCard type: ");
|
||||||
|
switch(card.type()) {
|
||||||
|
case SD_CARD_TYPE_SD1:
|
||||||
|
Serial.println("SD1");
|
||||||
|
break;
|
||||||
|
case SD_CARD_TYPE_SD2:
|
||||||
|
Serial.println("SD2");
|
||||||
|
break;
|
||||||
|
case SD_CARD_TYPE_SDHC:
|
||||||
|
Serial.println("SDHC");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Serial.println("Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
|
||||||
|
if (!volume.init(card)) {
|
||||||
|
Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// print the type and size of the first FAT-type volume
|
||||||
|
long volumesize;
|
||||||
|
Serial.print("\nVolume type is FAT");
|
||||||
|
Serial.println(volume.fatType(), DEC);
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
volumesize = volume.blocksPerCluster(); // clusters are collections of blocks
|
||||||
|
volumesize *= volume.clusterCount(); // we'll have a lot of clusters
|
||||||
|
volumesize *= 512; // SD card blocks are always 512 bytes
|
||||||
|
Serial.print("Volume size (bytes): ");
|
||||||
|
Serial.println(volumesize);
|
||||||
|
Serial.print("Volume size (Kbytes): ");
|
||||||
|
volumesize /= 1024;
|
||||||
|
Serial.println(volumesize);
|
||||||
|
Serial.print("Volume size (Mbytes): ");
|
||||||
|
volumesize /= 1024;
|
||||||
|
Serial.println(volumesize);
|
||||||
|
|
||||||
|
|
||||||
|
Serial.println("\nFiles found on the card (name, date and size in bytes): ");
|
||||||
|
root.openRoot(volume);
|
||||||
|
|
||||||
|
// list all files in the card with date and size
|
||||||
|
root.ls(LS_R | LS_DATE | LS_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop(void) {
|
||||||
|
|
||||||
|
}
|
77
libraries/SD/examples/listfiles/listfiles.pde
Normal file
77
libraries/SD/examples/listfiles/listfiles.pde
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
SD card basic file example
|
||||||
|
|
||||||
|
This example shows how to create and destroy an SD card file
|
||||||
|
The circuit:
|
||||||
|
* SD card attached to SPI bus as follows:
|
||||||
|
** MOSI - pin 11
|
||||||
|
** MISO - pin 12
|
||||||
|
** CLK - pin 13
|
||||||
|
** CS - pin 4
|
||||||
|
|
||||||
|
created Nov 2010
|
||||||
|
by David A. Mellis
|
||||||
|
updated 2 Dec 2010
|
||||||
|
by Tom Igoe
|
||||||
|
|
||||||
|
This example code is in the public domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <SD.h>
|
||||||
|
|
||||||
|
File root;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
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.");
|
||||||
|
|
||||||
|
root = SD.open("/");
|
||||||
|
|
||||||
|
printDirectory(root, 0);
|
||||||
|
|
||||||
|
Serial.println("done!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user