Библиотека SD для работы Arduino с SD картами
Библиотека SD для Arduino позволяет выполнять чтение и запись на SD карты, установленные, например, на плату расширения Arduino Ethernet Shield, и поддерживает файловые системы FAT16 и FAT32 на стандартных SD картах и картах SDHC.
Содержание
Введение
Библиотека SD позволяет выполнять чтение и запись на SD карты, установленные, например, на плату расширения Arduino Ethernet Shield. Она построена на базе sdfatlib от William Greiman. Библиотека поддерживает файловые системы FAT16 и FAT32 на стандартных SD картах и картах SDHC. Она использует короткие имена файлов 8.3. Имена файлов, переданные функциям SD библиотеки, могут включать пути, разделенные прямыми слешами, /, например, "directory/filename.txt". Поскольку рабочий каталог – это всегда корневой каталог SD карты, имя ссылается на один и тот же файл, независимо от того, включает ли оно прямой слеш (например, "/file.txt' эквивалентно "file.txt"). С версии 1.0 библиотека поддерживает открытие нескольких файлов.
Связь между микроконтроллером и SD картой использует интерфейс SPI, который использует цифровые выводы 11, 12 и 13 (на большинстве плат Arduino) или 50, 51 и 52 (на платах Arduino Mega). Кроме того, для выбора SD карты должен использоваться еще один вывод. Это может быть аппаратный вывод SS – вывод 10 (на большинстве плат Arduino) или вывод 53 (на платах Arduino Mega) – или какой-либо другой вывод, заданный с помощью вызова SD.begin()
. Обратите внимание, что даже если вы не используете аппаратный вывод SS, он должен быть оставлен настроенным для работы на выход, иначе библиотека SD работать не будет.
Описание методов и классов
Класс SD
Класс SD
предоставляет функции для доступа к SD карте и манипуляций с файлами и каталогами.
begin()
Инициализирует библиотеку SD и карту. Это запускает использование шины SPI (цифровые выводы 11, 12 и 13 на большинстве плат Arduino; 50, 51 и 52 на Arduino Mega) и вывод выбора чипа, который по умолчанию является аппаратным выводом SS (вывод 10 на большинстве плат Arduino, 53 на Arduino Mega). Обратите внимание, что даже если вы используете какой-либо другой вывод выбора чипа, аппаратный вывод SS должен быть оставлен настроенным для работы на выход, иначе библиотека SD работать не будет.
Синтаксис
SD.begin() SD.begin(cspin)
Параметры
cspin
(необязательный): вывод, подключенный к линии выбора чипа на SD карте; по умолчанию устанавливается аппаратный вывод SS шины SPI.Возвращаемое значение
true
в случае успеха;false
в случае неудачи.exists()
Проверяет, существует ли на SD карте файл или каталог.
Синтаксис
SD.exists(filename)
Параметры
filename
: имя файла, проверяемого на существование, может включать каталоги (отделенные прямыми слешами, /).Возвращаемое значение
true
, если файл или каталог существует;false
, если нет.mkdir()
Создает каталог на SD карте. Он также создает промежуточные каталоги, которые еще не существуют; например
SD.mkdir("a/b/c")
создаст a, b и c.Синтаксис
SD.mkdir(filename)
Параметры
filename
: имя каталога, который необходимо создать, может включать подкаталоги (отделенные прямыми слешами, /).Возвращаемое значение
true
, если каталог создан успешно;false
, если нет.open()
Открывает файл на SD карте. Если файл открывается для записи, и если он еще не существует, то он будет создан (но содержащий его каталог уже должен существовать).
Синтаксис
SD.open(filepath) SD.open(filepath, mode)
Параметры
filename
: имя файла, который необходимо открыть, может включать каталоги (отделенные прямыми слешами, /), переменная типаchar*
.mode
(необязательный): режим, в котором открыть файл (по умолчаниюFILE_READ
), переменная типаbyte
. Допустимые значения:FILE_READ
: открыть файл для чтения, начиная с начала файла;FILE_WRITE
: открыть файл для чтения и записи, начиная с конца файла.
Возвращаемое значение
Объект
File
, ссылающийся на открытый файл; если файл не может быть открыт, этот объект объект в булевом контексте будет оцениваться какfalse
, то есть вы можете проверить возвращенное значение с помощью "if(f)
".remove()
Удаляет файл с SD карты.
Синтаксис
SD.remove(filename)
Параметры
filename
: имя файла, который необходимо удалить, может включать каталоги (отделенные прямыми слешами, /).Возвращаемое значение
true
, если файл удален успешно;false
, если нет. Если файл не существует, возвращаемый результат не определен.rmdir()
Удаляет каталог с SD карты. Каталог должен быть пустым.
Синтаксис
SD.rmdir(filename)
Параметры
filename
: имя каталога, который необходимо удалить, может включать подкаталоги (отделенные прямыми слешами, /).Возвращаемое значение
true
, если каталог удален успешно;false
, если нет. Если каталог не существует, возвращаемый результат не определен.
Класс File
Класс File
служит для чтения и записи отдельных файлов на SD карте.
name()
Возвращает имя файла.
Синтаксис
file.name()
Возвращаемое значение
Имя файла.
available()
Проверяет, доступно ли какое-либо количество байтов для чтения из файла.
available()
наследуется из вспомогательного классаStream
.Синтаксис
file.available()
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).Возвращаемое значение
Количество доступных байтов (
int
).close()
Закрывает файл и гарантирует, что любые данные, записанные в него, физически сохранены на SD карту.
Синтаксис
file.close()
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).Возвращаемое значение
Нет.
flush()
Гарантирует, что любые байты, записанные в файл, физически сохраняются на SD карту. Этот метод выполняется автоматически при закрытии файла.
flush()
наследуется из вспомогательного классаStream
.Синтаксис
file.flush()
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).Возвращаемое значение
Нет.
peek()
Читает байт из файла без продвижения к следующему. То есть, успешный вызов
peek()
возвратит то же значение, что и следующий вызовread()
.peek()
наследуется из вспомогательного классаStream
.Синтаксис
file.peek()
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).Возвращаемое значение
Следующий байт (или символ) или -1, если ничего недоступно.
position()
Выдает текущую позицию внутри файла (то есть, положение, с которого будет прочитан или записан следующий файл).
Синтаксис
file.position()
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).Возвращаемое значение
Позиция внутри файла (
unsigned long
).print()
Печатает данные в файл, который должен быть открыт для записи. Числа печатаются как последовательность цифр, каждая ASCII символ (то есть число 123 посылается как три символа '1', '2', '3').
Синтаксис
file.print(data) file.print(data, BASE)
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).data
: данные для печати (char
,byte
,int
,long
илиstring
).BASE
(необязательно): основание для печати чисел:BIN
для двоичных (основание 2),DEC
для десятичных (основание 10),OCT
для восьмеричных (основание 8),HEX
для шестнадцатеричных (основание 16).Возвращаемое значение
byte
print()
возвратит количество записанных байтов, чтение этого значения необязательно.println()
Печатает данные, а затем символ возврата каретки или новой строки в файл, который должен быть открыт для записи. Числа печатаются как последовательность цифр, каждая ASCII символ (то есть число 123 посылается как три символа '1', '2', '3').
Синтаксис
file.println() file.println(data) file.print(data, BASE)
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).data
: данные для печати (char
,byte
,int
,long
илиstring
).BASE
(необязательно): основание для печати чисел:BIN
для двоичных (основание 2),DEC
для десятичных (основание 10),OCT
для восьмеричных (основание 8),HEX
для шестнадцатеричных (основание 16).Возвращаемое значение
byte
print()
возвратит количество записанных байтов, чтение этого значения необязательно.seek()
Ищет новую позицию в файле, которая должна быть между 0 и размером файла (включительно).
Синтаксис
file.seek(pos)
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).pos
: позиция для поиска (unsigned long
).Возвращаемое значение
true
, если успешно;false
, если нет (boolean
).size()
Получить размер файла.
Синтаксис
file.size()
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).Возвращаемое значение
Размер файла в байтах (
unsigned long
).read()
Прочитать из файла.
read()
наследуется из вспомогательного классаStream
.Синтаксис
file.read() file.read(buf, len)
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).buf
: массив символов или байтов.len
: количество элементов вbuf
.Возвращаемое значение
Следующий байт (или символ), или -1, если нет доступных.
write()
Записать данные в файл.
Синтаксис
file.write(data) file.write(buf, len)
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).data
:byte
,char
или строка (char *
) для записи.buf
: массив символов или байтов.len
: количество элементов вbuf
.Возвращаемое значение
byte
write()
возвратит количество записанных байтов, чтение этого значения необязательно.isDirectory()
Каталоги (или папки) – это специальные типы файлов, данная функция сообщает, является ли текущий файл каталогом или нет.
Синтаксис
file.isDirectory()
Параметры
file
: объект классаFile
(возвращается методомSD.open()
).Возвращаемое значение
boolean
Пример
#include <SD.h> File root; void setup() { Serial.begin(9600); pinMode(10, OUTPUT); SD.begin(10); root = SD.open("/"); printDirectory(root, 0); Serial.println("done!"); } void loop() { // Ничего не делаем после завершения настройки. } void printDirectory(File dir, int numTabs) { while(true) { File entry = dir.openNextFile(); if (!entry) { // больше нет файлов //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 { // у файлов есть размеры, у каталогов - нет Serial.print("\t\t"); Serial.println(entry.size(), DEC); } } }
openNextFile()
Возвращает следующий файл или каталог в каталоге.
Синтаксис
file.openNextFile()
Параметры
file
: объект классаFile
, который является каталогом.Возвращаемое значение
char
: следующий файл или каталог.Пример
#include <SD.h> File root; void setup() { Serial.begin(9600); pinMode(10, OUTPUT); SD.begin(10); root = SD.open("/"); printDirectory(root, 0); delay(2000); Serial.println(); Serial.println("Rewinding, and repeating below:" ); Serial.println(); delay(2000); root.rewindDirectory(); printDirectory(root, 0); root.close(); } void loop() { // после настройки ничего не делаем. } void printDirectory(File dir, int numTabs) { while (true) { File entry = dir.openNextFile(); if (!entry) { if (numTabs == 0) Serial.println("** Done **"); return; } 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 { Serial.print("\t\t"); Serial.println(entry.size(), DEC); } entry.close(); } }
rewindDirectory()
rewindDirectory()
вернет вас назад к первому файлу в каталоге, используется совместно сopenNextFile()
.Синтаксис
file.rewindDirectory()
Параметры
file
: объект классаFile
.Возвращаемое значение
Нет.
Пример
#include <SD.h> File root; void setup() { Serial.begin(9600); pinMode(10, OUTPUT); SD.begin(10); root = SD.open("/"); printDirectory(root, 0); Serial.println("done!"); } void loop() { // после завершения настройки ничего не делаем. } void printDirectory(File dir, int numTabs) { while(true) { File entry = dir.openNextFile(); if (! entry) { // файлов больше нет // возвращаемся к первому файлу в каталоге dir.rewindDirectory(); 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 { // у файлов есть размеры, у каталогов - нет Serial.print("\t\t"); Serial.println(entry.size(), DEC); } } }
Примеры
- Использование библиотеки SD для Arduino для получения информации об SD карте через последовательный порт
- DataLogger: использование библиотеки SD для сохранения лога показаний датчиков на SD карте
- Dump File: использование библиотеки SD для получения информации с SD карты через последовательный порт
- Файлы: использование библиотеки SD для Arduino для создания и удаления файлов на SD карте
- Списки файлов: использование библиотеки SD для Arduino для вывода списка каталогов и файлов на SD карте
- Использование библиотеки SD для Arduino для чтения и записи файла на SD карте
Некоторые вещи, которые необходимо учитывать при использовании библиотеки SD
Обзор
Связь между микроконтроллером и SD картой использует интерфейс SPI, который занимает цифровые выводы 11, 12 и 13 (на большинстве плат Arduino) или 50, 51 и 52 (Arduino Mega). Кроме того, для выбора SD карты должен использоваться еще один дополнительный вывод. Это может быть аппаратный вывод SS – вывод 10 (на большинстве плат Arduino) или вывод 53 (на платах Arduino Mega) – или какой-либо другой вывод, заданный с помощью вызова SD.begin()
. Обратите внимание, что даже если вы не используете аппаратный вывод SS, он должен быть оставлен настроенным для работы на выход, иначе библиотека SD работать не будет. Разные платы расширения для этого используют разные выводы, поэтому убедитесь в правильности выбора вывода в SD.begin()
.
Форматирование/подготовка карты
Примечание: всякий раз, когда в данной статье упоминается SD карта, это означает и SD, и microSD размеры, а также SD и SDHD форматы.
Большинство SD карт работает правильно сразу из коробки, но, возможно, ваша карта использовалась в компьютере или камере и не может быть прочитана с помощью библиотеки SD. Форматирование такой карты создаст файловую систему, в которой Arduino сможет читать и писать.
Часто форматировать SD карты нежелательно, так как это уменьшает их срок службы.
Для форматирования карты вам понадобятся SD ридер и компьютер. Библиотека поддерживает файловые системы FAT16 и FAT32, но по возможности лучше используйте FAT16.
Именование файлов
Файловые системы FAT имеют ограничения, когда в них используются соглашения по именованию файлов. Вы должны использовать формат 8.3, в котором имена файлов выглядят так "NAME001.EXT", где "NAME001" – строка из 8 или менее символов, а "EXT" – расширение из 3 символов. Люди часто используют расширения .TXT и .LOG. Возможно использовать и более короткие имена (например, mydata.txt или time.log), но более длинные имена файлов использовать запрещается.
Открытие/закрытие файлов
Когда вы используете file.write()
, то на карту ничего не будет записано, пока вы не вызовете flush()
или close()
. Всякий раз, когда вы открываете файл, убедитесь, что закрыли его, чтобы сохранить свои данные.
Начиная с версии 1.0, стало возможно иметь открытыми сразу несколько файлов.
Различные платы расширения
Ниже приведено несколько различных плат расширения, поддерживающих SD карты. Этот список неполный, но в нем приведены наиболее часто используемые платы.
Arduino Ethernet Shield
Плата расширения Ethernet Shield поставляется со слотом для SD карты. Плата устанавливается на Arduino сверху. Поскольку Ethernet модуль использует вывод 10, вывод CS для SD карты был перемещен на вывод 4. Для использования функционала SD карты вызывайте метод SD.begin(4)
.
Adafruit Micro-SD breakout Board
Данная плата поддерживает Micro-SD карты. Перед использованием ее необходимо правильно подключить к Arduino. Вывод GND на плате соедините с шиной земли на Arduino, вывод 5V – с шиной 5V, CLK – с выводом 13 на Arduino, DO – с выводом 12, DI – с выводом 11, CS – с выводом 10. Если вы уже используете вывод 10, то можете к CS подключить другой вывод, но не забудьте изменить вывод в SD.begin()
.
Sparkfun SD Shield
Плата расширения Sparkfun устанавливается на Arduino сверху и использует вывод 8 для CS. При использовании SD карты вам необходимо вызвать метод SD.begin(8)
.