Cześć,
w dzisiejszej części chcielibyśmy Wam pokazać w jaki sposób obsługiwać karty SD. Zapraszamy
Spis treści:
- Co to jest karta SD, podstawowe parametry
- Podstawowe funkcje do obsługi karty
- Pierwszy program: Zapis do karty SD
- Drugi program: Odczyt z karty SD
Co będziemy potrzebować:
- 1x Arduino
- 1x czytnik kart SD (gotowy moduł, albo taki jaki zrobiliśmy wcześniej)
- 1x Zestaw przewodów połączeniowych
Zaczynamy ;)
1.Co to jest karta SD, podstawowe parametry
Karta SD, a dokładniej Standard SD (ang. secure digital) to jeden ze standardów kart pamięci opracowany przez firmy Panasonic, SanDisk i Toshiba w 2000 roku. Karty SD charakteryzują się niewielkimi wymiarami (24 × 32 × 2,1 mm).
Karty SD posiadają 9 wyprowadzeń. Dodatkowo karta SD ma na brzegu przełącznik blokujący możliwość zapisu. Karta SD operuje na napięciu 3,3V.
Przy zakupie kart mamy do wyboru rodzaj standardu oraz klasę karty. Można powiedzieć, że standard karty oznacza między innymi zakres pamięci karty
- SD (8MB – 2GB)
- SDHC (4GB – 32GB)
- SDXC (64GB – 2TB)
Natomiast klasa karty określa prędkość odczytu i zapisu z karty (tutaj panuje zasada „im wyższy numer tym lepsza”):
odczyt (zapis)
- klasa 2: 16 Mb/s (2 MB/s)
- klasa 4: 32 Mb/s (4 MB/s)
- klasa 6: 48 Mb/s (6 MB/s)
- klasa 10: 80 Mb/s (10 MB/s)
Na potrzeby tej części kursu powiem, że mikrokontrolery są w stanie bezproblemowo obsługiwać karty SD do 4GB klasy 4. Oczywiście są również wyjątki, jakim jest w moim przypadku karta SDHC 8GB klasy 4. Karta musi być sformatowana w systemie FAT16/FAT32.
Karta SD łączy się z mikrokontrolerem przy pomocy interfejsu SPI, w którego skład wchodzą piny MISO, MOSI, SCK, CS.
2. Podstawowe funkcje do obsługi karty
Teraz opiszę funkcję, które musimy znać, aby być w stanie bez problemu obsługiwać kartę SD.
Na początku musimy dodać biblioteki obsługujące interfejs SPI oraz standard SD:
1 2 |
#include <SPI.h> #include <SD.h> |
Następnie tworzymy instancję do klasy File, która jest odpowiedzialna m.in. za operacje na plikach:
1 |
File plik; |
Instancji File możemy nadać dowolną nazwę, ja nadałem po prostu nazwę plik.
Uruchamiamy obsługę karty. Można to zrobić na dwa sposoby:
- Dajemy Arduino bezpośrednią informację, że karta jest podłączona. On wtedy nie sprawdza stanu faktycznego tylko próbuje wykonywać program
- Arduino sprawdzi czy karta jest podłączona do Arduino i wtedy podejmie decyzję co zrobić.
W pierwszym przypadku po prostu piszemy:
1 2 |
SD.begin(pin_CS) //pin_CS - numer pinu do którego podpięty jest sygnał CS z karty SD |
Drugi sposób opiera się na sprawdzeniu warunku:
1 2 3 4 5 |
if (!SD.begin(4)) //sprawdź czy nie ma karty na pinie ChipSelect 4 { Serial.println("Nie wykryto karty"); //błąd wykrycia karty return; //przerwij program } |
Sprawdź czy nie ma karty, wstawiając operator zaprzeczenia „!”. Jeżeli karta nie zostanie wykryta to wydrukuj komunikat i przerwij wykonywanie programu przy pomocy funkcji return. Wtedy dalsza część programu nie będzie wykonywana. Dopiero po włożeniu karty i ponownym zresetowaniu Arduino będzie wykonywana dalsza część programu.
Teraz, gdy Arduino już wie, czy karta jest podłączona czy nie to możemy przejść do wykonywania operacji na plikach.
Możemy sprawdzić czy w pamięci karty znajduje się dany plik, w następujący sposób:
1 |
SD.exists("nazwa_pliku") |
W nazwie pliku musi się znajdować również rozszerzenie. Ważne aby nazwy plików nie były dłuższe niż 8 znaków i nie zawierały specjalnych znaków.
Kolejną funkcją tworzymy plik, otwieramy oraz przyznajemy prawa zapisu i odczytu danych:
1 |
plik = SD.open("nazwa_pliku", FILE_WRITE); |
plik to reprezentacja instancji, w nazwie pliku podajemy również nazwę maksymalnie 8 znakową wraz z rozszerzeniem, a przy pomocy FILE_WRITE przyznajemy prawa zapisu i odczytu. Możemy jeszcze użyć FILE_READ, ale wtedy przyznamy tylko prawa do odczytu danych z pliku. Przy operacji na plikach ważne jest, iż jednocześnie może być otwarty tylko jeden plik.
Do usuwania plików, używam analogicznie SD.remove() z pominięciem instancji:
1 |
SD.remove("123.txt"); |
Jeżeli tworzymy jakiś rozbudowany projekt to możemy również tworzyć katalogi na karcie przy pomocy funkcji:
1 |
plik = SD.mkdir("a/b/c"); |
Literki a b c oznaczają strukturę katologów, czyli zostanie utworzony folder „c” w folderze „b” i te oba foldery jeszcze w folderze „a”. Aby zapisać jakiś plik w takiej strukturze to musimy użyć funkcji SD.open:
1 2 3 |
plik = SD.open("/a/123.txt", FILE_WRITE); plik = SD.open("/a/b/345.txt", FILE_WRITE); plik = SD.open("/a/b/c/567.txt", FILE_WRITE); |
Gdybyśmy nie poprzedzili ścieżki do pliku po przez „/” to by utworzyło plik o takiej nazwie jak wygląda ścieżka.
W taki sam sposób działa usuwanie katalogów, tylko, że zamiast mkdir piszemy rmdir:
1 |
SD.rmdir("a/b/c"); |
Teraz przejdźmy do operacji na plikach:
Przy pomocy poniższej funkcji możemy zapisywać dane do pliku:
1 |
plik.print("wpisywane dane"); |
plik to instancja klasy File. Zasada obsługi print jest taka sama jak dla UARTu, czyli print– pisanie w jednej linii, println– pisanie od nowej linii.
Aby odczytać dane to już nie jest tak łatwo- tzn. nie przy pomocy jednej funkcji ;)
Najpierw musimy sprawdzić czy w danym pliku są jakieś dane (bajty danych) do odczytania przy pomocy:
1 |
plik.available() |
Następnie gdy jakieś dane będą to musimy wykorzystać funkcję:
1 |
plik.read() |
Nie mniej jednak nie można wpisać tak bezpośrednio tych funkcji, tylko muszą tworzyć logiczną całość, ale o tym później ;)
Okej „przebrnęliśmy” przez podstawowe funkcje. Wydaje się, że jest ich dużo, ale jak zobaczycie sposób ich wykorzystania to się okaże, że obsługa kart jest banalnie prosta ;)