[162] Karta SD cz. 2

W poprzednim artykule poznaliśmy karty SD z punktu widzenia arduinowca. Wiemy już jak je podłączać i sprawdzać czy mają ochotę na dialog z naszym systemem. Czas więc nauczyć się rozmawiać z kartami. Na początek – taki trochę DOS: przeprowadzimy szereg operacji na plikach. Stwórzmy więc nowy szkic.


#include <SD.h>  // Biblioteka obsługi karty SD
File file;
const byte cardCS = 4;  // Deklaracja adresu linii CS11

void setup() {
  Serial.begin(115200);                                      // Inicjuj port monitora.
  Serial.println(F("\
Czekam na sygnał z karty SD..."));     // Wyślij komunikat.
  if (!SD.begin(cardCS)) {                                   // Inicjuj kartę określając port CS (jeśli brak - pin 10)
    Serial.println(F("Niepowodzenie, nie wykryto karty."));  // Karta nie została wykryta.
    while (1)                                                // Koniec programu.
      ;
  }
  Serial.println(F("Powodzenie, wykryto kartę."));

  Serial.println(F("\
Czy na karcie istnieje plik DANE.TXT ?"));  // Wykrywanie plików.
  if (SD.exists("DANE.TXT")) {                                    // Sprawdzam czy na karcie istnieje plik DANE.TXT
    Serial.println(F("Znaleziono na karcie plik DANE.TXT"));
  } else {
    Serial.println(F("Nie znaleziono pliku DANE.TXT"));
  }

  Serial.println(F("\
Stworzę plik DANE.TXT..."));  // Tworzenie plików.
  file = SD.open("DANE.TXT", FILE_WRITE);           // Otwieram plik DANE.TXT, który będzie zapisywany.
  file.close();                                     // Zapisuję wcześniej otwarty plik na karcie.
  if (SD.exists("DANE.TXT")) {                      // Sprawdzam czy na karcie istnieje plik DANE.TXT
    Serial.println(F("Powodzenie, stworzyłem plik DANE.TXT"));
  } else {
    Serial.println(F("Niepowodzenie, nie dałem rady stworzyć pliku DANE.TXT"));
  }

  Serial.println(F("\
Usunę plik DANE.TXT..."));  // Usuwanie plików.
  SD.remove("DANE.TXT");                          // Usuwam plik DANE.TXT
  if (SD.exists("DANE.TXT")) {                    // Sprawdzam czy na karcie istnieje plik DANE.TXT
    Serial.println(F("Niepowodzenie, nie dałem rady usunąć pliku DANE.TXT"));
  } else {
    Serial.println(F("Powodzenie, usunąłem plik DANE.TXT"));
  }

  Serial.println(F("\
Stworzę katalog FOLDER..."));  // Tworzenie katalogów.
  SD.mkdir("FOLDER");                                // Tworzę katalog FOLDER.
  if (SD.exists("FOLDER")) {                         // Sprawdzam czy na karcie istnieje katalog FOLDER
    Serial.println(F("Powodzenie, stworzyłem katalog FOLDER"));
  } else {
    Serial.println(F("Niepowodzenie, nie dałem rady stworzyć katalogu FOLDER"));
  }

  Serial.println(F("\
Usunę katalog FOLDER..."));  // Usuwanie katalogów.
  SD.rmdir("FOLDER");                              // Usuwam katalog FOLDER.
  if (SD.exists("FOLDER")) {                       // Sprawdzam czy na karcie istnieje katalog FOLDER
    Serial.println(F("Niepowodzenie, nie dałem rady usunąć katalogu FOLDER"));
  } else {
    Serial.println(F("Powodzenie, usunąłem katalog FOLDER"));
  }

  Serial.println(F("\
Stworzę plik dane.txt w katalogu FOLDER..."));  // Tworzenie plików w katalogach.
  SD.mkdir("FOLDER");                                                 // Tworzę katalog FOLDER.
  file = SD.open("FOLDER/DANE.TXT", FILE_WRITE);                      // Otwieram plik DANE.TXT w katalogu FOLDER, który będzie zapisywany.
  file.close();                                                       // Zapisuję wcześniej otwarty plik na karcie.
  if (SD.exists("FOLDER/DANE.TXT")) {                                 // Sprawdzam czy na karcie istnieje plik DANE.TXT
    Serial.println(F("Powodzenie, stworzyłem plik FOLDER/DANE.TXT"));
  } else {
    Serial.println(F("Niepowodzenie, nie dałem rady stworzyć pliku FOLDER/DANE.TXT"));
  }

  Serial.println(F("\
Usunę plik FOLDER/DANE.TXT oraz katalog FOLDER..."));  // Usuwanie plików z katalogów wraz z katalogiem.
  SD.remove("FOLDER/DANE.TXT");                                              // Usuwam plik FOLDER/DANE.TXT
  SD.rmdir("FOLDER");                                                        // Usuwam katalog FOLDER.
  if (SD.exists("FOLDER/DANE.TXT")) {                                        // Sprawdzam czy na karcie istnieje plik FOLDER/DANE.TXT
    Serial.println(F("Niepowodzenie, nie dałem rady usunąć pliku FOLDER/DANE.TXT"));
  } else {
    Serial.println(F("Powodzenie, usunąłem plik FOLDER/DANE.TXT oraz katalog FOLDER"));
  }
}
void loop() {}

Początek będzie podobny: zaczytanie biblioteki i deklaracja niezbędnego dla jej funkcjonowania obiektu. Różnicę mamy już na wstępie: wykorzystamy alternatywny wobec poprzedniego sposób inicjacji karty. Instrukcja card.init(SPI_HALF_SPEED, cardCS) pozwalała zdefiniować szybkość, metoda SD.begin(cardCS) jest uproszczona i sprowadza się tylko do deklaracji pinu linii dostępu.

Pobawmy się plikami. W pierwszym etapie sprawdzimy czy na karcie znajduje się plik DANE.TXT.

Serial.println(F("\
Czy na karcie istnieje plik DANE.TXT ?"));  // Wykrywanie plików.
if (SD.exists("DANE.TXT")) {                                    // Sprawdzam czy na karcie istnieje plik DANE.TXT
  Serial.println(F("Znaleziono na karcie plik DANE.TXT"));
} else {
  Serial.println(F("Nie znaleziono pliku DANE.TXT"));
}

Za pomocą instrukcji SD.exists("nazwa pliku"), zwracającej prawdę albo fałsz, dostaniemy odpowiedź. Ponieważ takiego pliku tam nie umieszczałem, utworzę go.

Serial.println(F("\
Stworzę plik DANE.TXT..."));  // Tworzenie plików.
file = SD.open("DANE.TXT", FILE_WRITE);           // Otwieram plik DANE.TXT, który będzie zapisywany.
file.close();                                     // Zapisuję wcześniej otwarty plik na karcie.
if (SD.exists("DANE.TXT")) {                      // Sprawdzam czy na karcie istnieje plik DANE.TXT
  Serial.println(F("Powodzenie, stworzyłem plik DANE.TXT"));
} else {
  Serial.println(F("Niepowodzenie, nie dałem rady stworzyć pliku DANE.TXT"));
}

Jakiekolwiek operacje związane z manipulowaniem treścią plików wymagają operacji otwarcia na początku i zamknięcia na końcu tzw. obiektu, który jest plikiem jako takim, a już jego nazwę definiuje się na miejscu. Tylko jeden plik jednocześnie może być otwarty, więc jeśli będziemy chcieli zająć się innym, musimy zamknąć bieżący. Wszelkie zmiany pliku – jeśli są wymagane – zostaną przeprowadzone właśnie w chwili jego zamknięcia. Pominięcie etapu zamknięcia pliku pogubi nam dane.

Przejdźmy więc do etapu drugiego: stwórzmy plik DANE.TXT Otwieramy plik o takiej nazwie w trybie zapisu, po czym go zapisujemy. Na razie będzie pusty. Ponownie sprawdzamy czy na karcie istnieje taki plik. Oczywiście istnieje, bo właśnie go stworzyliśmy. Przetestujmy więc kolejną instrukcję, która usuwa pliki.

Serial.println(F("\
Usunę plik DANE.TXT..."));  // Usuwanie plików.
SD.remove("DANE.TXT");                          // Usuwam plik DANE.TXT
if (SD.exists("DANE.TXT")) {                    // Sprawdzam czy na karcie istnieje plik DANE.TXT
  Serial.println(F("Niepowodzenie, nie dałem rady usunąć pliku DANE.TXT"));
} else {
  Serial.println(F("Powodzenie, usunąłem plik DANE.TXT"));
}

Tutaj wykorzystuje się prostą instrukcję, przy czym nie trzeba tym razem otwierać i zamykać obiektu, bo tym razem nie interesuje nas jego treść, a on sam jako całość. Zaraz potem jak zwykle sprawdzam, czy zadanie usuwania zakończyło się powodzeniem.

Serial.println(F("\
Stworzę katalog FOLDER..."));  // Tworzenie katalogów.
SD.mkdir("FOLDER");                                // Tworzę katalog FOLDER.
if (SD.exists("FOLDER")) {                         // Sprawdzam czy na karcie istnieje katalog FOLDER
  Serial.println(F("Powodzenie, stworzyłem katalog FOLDER"));
} else {
  Serial.println(F("Niepowodzenie, nie dałem rady stworzyć katalogu FOLDER"));
}

W końcu zajmiemy się katalogami, tudzież – po nowemu: folderami. Katalog tworzymy poleceniem mkdir, przy czym nic tu nie otwieramy i nie zamykamy, bo katalogi to nie pliki. Jak zwykle sprawdzamy, czy powstał taki twór.

Serial.println(F("\
Usunę katalog FOLDER..."));  // Usuwanie katalogów.
SD.rmdir("FOLDER");                              // Usuwam katalog FOLDER.
if (SD.exists("FOLDER")) {                       // Sprawdzam czy na karcie istnieje katalog FOLDER
  Serial.println(F("Niepowodzenie, nie dałem rady usunąć katalogu FOLDER"));
} else {
  Serial.println(F("Powodzenie, usunąłem katalog FOLDER"));
}

Teraz usuniemy katalog dopiero co powstały katalog pleceniem rmdir i znowu sprawdzimy, czy się nam to udało. Pamiętajmy, że usuwać możemy tylko katalogi puste. Jeśli mamy wewnątrz jakiekolwiek pliki – musimy je wcześniej usunąć osobno.

Serial.println(F("\
Stworzę plik dane.txt w katalogu FOLDER..."));  // Tworzenie plików w katalogach.
SD.mkdir("FOLDER");                                                 // Tworzę katalog FOLDER.
file = SD.open("FOLDER/DANE.TXT", FILE_WRITE);                      // Otwieram plik DANE.TXT w katalogu FOLDER, który będzie zapisywany.
file.close();                                                       // Zapisuję wcześniej otwarty plik na karcie.
if (SD.exists("FOLDER/DANE.TXT")) {                                 // Sprawdzam czy na karcie istnieje plik DANE.TXT
  Serial.println(F("Powodzenie, stworzyłem plik FOLDER/DANE.TXT"));
} else {
  Serial.println(F("Niepowodzenie, nie dałem rady stworzyć pliku FOLDER/DANE.TXT"));
}

Na koniec zostawiłem sobie przypadek pliku w katalogu. Generalnie nie różni się on niczym od tego, co już przedstawiłem. Należy tylko zachować logiczną kolejność. A więc: najpierw tworzymy katalog FOLDER, potem wewnątrz niego – plik DANE.TXT Aby teraz usunąć wszystko, najpierw usuwamy plik, a następnie katalog.

Serial.println(F("\
Usunę plik FOLDER/DANE.TXT oraz katalog FOLDER..."));  // Usuwanie plików z katalogów wraz z katalogiem.
SD.remove("FOLDER/DANE.TXT");                                              // Usuwam plik FOLDER/DANE.TXT
SD.rmdir("FOLDER");                                                        // Usuwam katalog FOLDER.
if (SD.exists("FOLDER/DANE.TXT")) {                                        // Sprawdzam czy na karcie istnieje plik FOLDER/DANE.TXT
  Serial.println(F("Niepowodzenie, nie dałem rady usunąć pliku FOLDER/DANE.TXT"));
} else {
  Serial.println(F("Powodzenie, usunąłem plik FOLDER/DANE.TXT oraz katalog FOLDER"));
}

A co będzie gdy stworzymy plik, który już istnieje? Oryginał pozostanie nienaruszony, a przy zapisie nowe treści dołączą do treści już istniejących. Ponowne stworzenie istniejącego już katalogu także nie daje błędu, ale nie wpływa na nic. Poniżej zamieszczam zrzut z monitora ze szkicu, który omawiałem. Niestety w zasobach nie ma instrukcji kopiowania plików, ich przenoszenia po katalogach czy zmiany nazw. Te rzeczy trzeba czynić naokoło, otwierając pliki i przerzucając między nimi ich zawartość.

Czekam na sygnał z karty SD...
Powodzenie, wykryto kartę.

Czy na karcie istnieje plik DANE.TXT ?
Nie znaleziono pliku DANE.TXT

Stworzę plik DANE.TXT...
Powodzenie, stworzyłem plik DANE.TXT

Usunę plik DANE.TXT...
Powodzenie, usunąłem plik DANE.TXT

Stworzę katalog FOLDER...
Powodzenie, stworzyłem katalog FOLDER

Usunę katalog FOLDER...
Powodzenie, usunąłem katalog FOLDER

Stworzę plik dane.txt w katalogu FOLDER...
Powodzenie, stworzyłem plik FOLDER/DANE.TXT

Usunę plik FOLDER/DANE.TXT oraz katalog FOLDER...
Powodzenie, usunąłem plik FOLDER/DANE.TXT oraz katalog FOLDER

I to byłoby na tyle w temacie manipulacji plikami. W kolejnym artykule zajmiemy się już zmienianiem treści plików.

Płytka edukacyjna TME-EDU-ARD-2Płytka edukacyjna TME-EDU-ARD-2

Inne artykuły z tej kategorii

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2026 arduino.pl