Руководство по работе с SD-картами на Arduino

Серия примеров чтения и записи данных на SD-карту с Arduino.

Автор: Arduino

Последнее обновление: 30.09.2025

Примечание

Эта статья была пересмотрена 18.11.2021 Карлом Сёдерби (Karl Söderby).

В этом руководстве собраны совместимые аппаратные средства и примеры кода, которые помогут вам начать работу с картами Secure Digital (SD).

Примеры в данном руководстве взяты из библиотеки SD, которая изначально основана на SdFat Уильяма Грейман (William Greiman).

Необходимое оборудование и программное обеспечение

  • Плата Arduino со слотом для SD-карты*

  • Arduino IDE (онлайн или офлайн).

  • Отформатированная SD-карта

*Список плат/шилдов со слотом для SD-карты приведён ниже:

Схема подключения

Ниже показан пример вставки SD-карты в плату MKR Zero. Ни один из приведённых ниже примеров не требует дополнительной схемы.

Вставьте SD-карту.

Вставьте SD-карту.

Примеры

Ниже приведена серия примеров.

Чтение и запись

Этот пример демонстрирует, как считывать данные с SD-карты и записывать их на неё.

  • В setup() создайте новый файл с помощью SD.open() с именем «test.txt». FILE_WRITE включает доступ к файлу на чтение и запись, начиная с конца. Если файл "test.txt" уже находился на карте, он будет открыт.

  • Назовите экземпляр открытого файла «myFile».

  • После открытия используйте myFile.println() для записи строки на карту, завершив её символом возврата каретки. После записи содержимого закройте файл.

  • Снова откройте файл с помощью SD.open(). После открытия прочитайте содержимое файла с помощью SD.read() и передайте его через последовательный порт. После прочтения всего содержимого закройте файл с помощью SD.close().

Примечание

Обратите внимание: пин 4 — это пин Chip Select (CS) по умолчанию для большинства плат. Чтобы задать CS для MKR Zero, можно использовать 28 вместо 4, либо определение SDCARD_SS_PIN.

/*
  SD card read/write

  This example shows how to read and write data to and from 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 (for MKRZero SD: SDCARD_SS_PIN)

  created   Nov 2010
  by David A. Mellis
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

*/

#include <SPI.h>
#include <SD.h>

File myFile;

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

  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void loop() {
  // nothing happens after setup
}

Информация о карте

Этот пример показывает, как считать информацию о SD-карте. Пример выводит тип тома, свободное пространство и другие сведения с помощью библиотеки SD, передавая их через последовательный порт.

/*

  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.

  Pin numbers reflect the default SPI pins for Uno and Nano models

  The circuit:

    SD card attached to SPI bus as follows:

 ** SDO - pin 11 on Arduino Uno/Duemilanove/Diecimila

 ** SDI - pin 12 on Arduino Uno/Duemilanove/Diecimila

 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila

 ** CS - depends on your SD card shield or module.

        Pin 10 used here for consistency with other Arduino examples

  created  28 Mar 2011

  by Limor Fried

  modified 24 July 2020

  by Tom Igoe

*/
// include the SD library:
#include <SPI.h>
#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;
// Default SPI on Uno and Nano: pin 10
// Arduino Ethernet shield: pin 4
// Adafruit® SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN

const int chipSelect = 10;

void setup() {

  // Open serial communications and wait for port to open:

  Serial.begin(9600);

  while (!Serial) {

    ; // wait for serial port to connect. Needed for native USB port only

  }

  Serial.print("\nInitializing SD card...");

  // 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 inserted?");

    Serial.println("* is your wiring correct?");

    Serial.println("* did you change the chipSelect pin to match your shield or module?");

    while (1);

  } else {

    Serial.println("Wiring is correct and a card is present.");

  }

  // print the type of card

  Serial.println();

  Serial.print("Card 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");

    while (1);

  }

  Serial.print("Clusters:          ");

  Serial.println(volume.clusterCount());

  Serial.print("Blocks x Cluster:  ");

  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");

  Serial.println(volume.blocksPerCluster() * volume.clusterCount());

  Serial.println();

  // print the type and size of the first FAT-type volume

  uint32_t volumesize;

  Serial.print("Volume type is:    FAT");

  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks

  volumesize *= volume.clusterCount();       // we'll have a lot of clusters

  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)

  Serial.print("Volume size (Kb):  ");

  Serial.println(volumesize);

  Serial.print("Volume size (Mb):  ");

  volumesize /= 1024;

  Serial.println(volumesize);

  Serial.print("Volume size (Gb):  ");

  Serial.println((float)volumesize / 1024.0);

  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);

  root.close();
}

void loop(void) {
}

Примечание

Обратите внимание: размер кластера определяется пользователем во время форматирования и имеет некоторые значения по умолчанию, которые можно изменить согласно определённым правилам. В приведённом выше скетче используется размер блока по умолчанию, равный 512 байтам согласно стандартам. Это значение не является размером кластера — он вычисляется как количество блоков на кластер. Более подробную информацию о размерах кластеров можно найти в этой статье.

Вывод файла

Этот пример показывает, как прочитать файл с SD-карты с помощью библиотеки SD и передать его через последовательный порт.

На SD-карте находится файл с именем «datalog.txt». В loop() файл открывается при вызове SD.open(). Чтобы передать файл по последовательному порту на компьютер, используйте Serial.print(), считывая содержимое файла с помощью SD.read().

/*

  SD card file dump

  This example shows how to read a file from the SD card using the

  SD library and send it over the serial port.

  Pin numbers reflect the default SPI pins for Uno and Nano models.

  The circuit:

   SD card attached to SPI bus as follows:

 ** SDO - pin 11

 ** SDI - pin 12

 ** CLK - pin 13

 ** CS - depends on your SD card shield or module.

        Pin 10 used here for consistency with other Arduino examples

   (for MKRZero SD: SDCARD_SS_PIN)

  created  22 December 2010

  by Limor Fried

  modified 9 Apr 2012

  by Tom Igoe

  This example code is in the public domain.

*/
#include <SD.h>

const int chipSelect = 10;

void setup() {

  // Open serial communications and wait for port to open:

  Serial.begin(9600);

  // wait for Serial Monitor to connect. Needed for native USB port boards only:

  while (!Serial);

  Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) {

    Serial.println("initialization failed. Things to check:");

    Serial.println("1. is a card inserted?");

    Serial.println("2. is your wiring correct?");

    Serial.println("3. did you change the chipSelect pin to match your shield or module?");

    Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!");

    while (true);

  }

  Serial.println("initialization done.");

  // open the file. note that only one file can be open at a time,

  // so you have to close this one before opening another.

  File dataFile = SD.open("datalog.txt");

  // if the file is available, write to it:

  if (dataFile) {

    while (dataFile.available()) {

      Serial.write(dataFile.read());

    }

    dataFile.close();

  }

  // if the file isn't open, pop up an error:

  else {

    Serial.println("error opening datalog.txt");

  }
}

void loop() {
}

Управление файлами

Этот пример показывает, как создать и удалить файл на SD-карте.

В setup() откройте новый файл с помощью SD.open() с именем «example.txt». FILE_WRITE включает доступ к файлу на чтение и запись, начиная с конца. В этом примере, однако, сразу же закройте файл, вызвав myFile.close().

После проверки наличия файла с помощью SD.exists() удалите файл с карты с помощью SD.remove.

/*

  SD card basic file example

  This example shows how to create and destroy an SD card file

  The circuit. Pin numbers reflect the default

  SPI pins for Uno and Nano models:

   SD card attached to SPI bus as follows:

 ** SDO - pin 11

 ** SDI - pin 12

 ** CLK - pin 13

 ** CS - depends on your SD card shield or module.

        Pin 10 used here for consistency with other Arduino examples

    (for MKRZero SD: SDCARD_SS_PIN)

  created   Nov 2010

  by David A. Mellis

  modified 24 July 2020

  by Tom Igoe

  This example code is in the public domain.

*/
#include <SD.h>

const int chipSelect = 10;

File myFile;

void setup() {

  // Open serial communications and wait for port to open:

  Serial.begin(9600);

  // wait for Serial Monitor to connect. Needed for native USB port boards only:
  while (!Serial);

  Serial.print("Initializing SD card...");

  if (!SD.begin(10)) {

    Serial.println("initialization failed!");

    while (1);

  }

  Serial.println("initialization done.");

  if (SD.exists("example.txt")) {

    Serial.println("example.txt exists.");

  } else {

    Serial.println("example.txt doesn't exist.");

  }

  // open a new file and immediately close it:

  Serial.println("Creating example.txt...");

  myFile = SD.open("example.txt", FILE_WRITE);

  myFile.close();

  // Check to see if the file exists:

  if (SD.exists("example.txt")) {

    Serial.println("example.txt exists.");

  } else {

    Serial.println("example.txt doesn't exist.");

  }

  // delete the file:

  Serial.println("Removing example.txt...");

  SD.remove("example.txt");

  if (SD.exists("example.txt")) {

    Serial.println("example.txt exists.");

  } else {

    Serial.println("example.txt doesn't exist.");

  }
}

void loop() {

  // nothing happens after setup finishes.
}

Вывод списка файлов

Этот пример показывает, как вывести список файлов, доступных в директории SD-карты.

Основной loop() ничего не делает, поскольку функция, выводящая файловый каталог «/» SD-карты, вызывается из setup(). Это сделано потому, что нам нужно увидеть его только один раз.

Функция printDirectory просматривает список записей и выводит в последовательный порт каждый файл и директорию. Для файлов также выводится их размер.

/*

  Listfiles

  This example shows how print out the files in a

  directory on a SD card. Pin numbers reflect the default

  SPI pins for Uno and Nano models

  The circuit:

   SD card attached to SPI bus as follows:

 ** SDO - pin 11

 ** SDI - pin 12

 ** CLK - pin 13

 ** CS - depends on your SD card shield or module.

        Pin 10 used here for consistency with other Arduino examples

    (for MKRZero SD: SDCARD_SS_PIN)

  created   Nov 2010

  by David A. Mellis

  modified 9 Apr 2012

  by Tom Igoe

  modified 2 Feb 2014

  by Scott Fitzgerald

  modified 24 July 2020

  by Tom Igoe

  This example code is in the public domain.

*/
#include <SD.h>

const int chipSelect = 10;

File root;

void setup() {

 // Open serial communications and wait for port to open:

  Serial.begin(9600);

  // wait for Serial Monitor to connect. Needed for native USB port boards only:

  while (!Serial);

  Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) {

    Serial.println("initialization failed. Things to check:");

    Serial.println("1. is a card inserted?");

    Serial.println("2. is your wiring correct?");

    Serial.println("3. did you change the chipSelect pin to match your shield or module?");

    Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!");

    while (true);

  }

  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

      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);

    }

    entry.close();

  }
}