Mikrokontrolery STM32 Obsługa kart SD i FatFs


PODZESPOAY
Mikrokontrolery STM32
Obsługa kart SD
Dodatkowe
materiały na CD
i modułu FatFs
Ilości przechowywanych
i przetwarzanych informacji
nieustannie rosnÄ…. Coraz
częściej systemy wbudowane
sÄ… zmuszane do zarzÄ…dzania
dużą ilością danych. W artykule
omówiono sposób wykorzystania
kart pamięci SD i modułu FatFs
w połączeniu z mikrokontrolerami
STM32. BiorÄ…c pod uwagÄ™
nieustanny spadek cen kart
SD warto poważnie zastanowić
siÄ™ nad wykorzystaniem tego
typu nośnika w aplikacji, która
wymaga administrowania
Co to jest? Dzowiesz się na końcu artykułu
nieprzeciętną ilością danych.
Przykładowe aplikacje
lerach sprzętowych sterowników kart SD. Komendy kart pamięci SD
przygotowano dla płytki
Przedstawiciele najbardziej zaawansowanej Nie będziemy wnikać w budowę re-
ewaluacyjnej STM3210B-EVAL.
grupy układów z rodziny STM32 mają wbu- jestrów, w jakie wyposażone są karty SD,
dowany właśnie taki sterownik. ponieważ nie to jest celem niniejszego ar-
Karty SD Obecnie na rynku karty SD można spo- tykułu. Do osiągnięcia naszego celu, czyli
Współcześnie najpopularniejsze i najbar- tkać najczęściej w dwóch typach obudów: uruchomienia obsługi systemu plików FAT
dziej uniwersalne są karty SD (Secure Digital zwykłej SD i SDMicro. Obie przedstawiono w mikrokontrolerze STM32 z użyciem mo-
card). Standard obejmuje karty o pojemności na rys. 1. dułu FatFs, wystarczy znajomość przede
do 4 GB, a jego rozszerzenie, czyli SDHC (Se- W zasadzie wszystkie karty SD dostępne wszystkim budowy komend oraz ich kilku
cure Digital High Capacity), aż do 32 GB. na rynku obsługują dwa standardy komuni- typów, jakie obsługują karty SD.
Standard kart SD został pierwotnie kacyjne: dedykowany SDBus oraz SPI. Jak to Każda komenda, która ma być wysła-
opracowany przez trzy firmy: Matsushita, zwykle bywa, interfejs natywny (SDBus) ofe- na do karty SD, składa się z sześciu bajtów.
SanDisk i Toshiba. Pierwsze nośniki danych ruje duże możliwości i dużą szybkość pracy, Pierwszym bajtem jest zawsze kod komendy,
tego typu pojawiły się pod koniec 2000 roku. ale za cenę wzrostu stopnia skomplikowania kolejne cztery bajty to jej argument. Na koń-
Początkowo dokumentacja standardu SD obsługi interfejsu. Z tego powodu w kartach cu jest przesyłany bajt sumy kontrolnej CRC.
była dosyć trudno dostępna, jednak sytu- SD dostępna jest również komunikacja za O ile w trybie pracy z interfejsem SDBus
acja uległa zmianie wraz z nadejściem roku pomocą o wiele prostszej w obsłudze magi- CRC jest sprawdzane, to przy komunikacji
2006, kiedy to stały się dostępne informacje strali SPI, z tym, że tutaj mamy nieco okro- za pomocą magistrali SPI, suma kontrolna
m. in. na temat interfejsu SDIO, co w efekcie jone możliwości. Jeśli tylko aplikacja nie jest przez kartę ignorowana. Tylko w trakcie
pozwoliło na implementację w mikrokontro- wymaga wyjątkowo dużej szybkości przesy- przesyłania komendy CMD0, przełączającej
Å‚ania danych, to nie ma jakiegokolwiek sen- tryb pracy z SDBus na SPI jest wymagany
su implementacja obsługi interfejsu SDBus, bajt CRC. Nie trzeba go w żaden sposób obli-
wystarczy praca z magistralą SPI. Przedsta- czać, ponieważ jest to stała wartość i wynosi
wione wyżej podejście znakomicie uprasz- 0x95. W tab. 1 umieszczono kilka komend
cza sprawę, ponieważ zdecydowana więk-
szość dostępnych mikrokontrolerów (w tym
oczywiście STM32F103) jest wyposażona
w sprzętowy kontroler SPI.
Sposób podłączenia karty SD przez
magistralę SPI do mikrokontrolera został
przedstawiony na rys. 2. Podobny układ
został wykorzystany na płytce ewaluacyjnej
Rys. 1. STM3210B-EVAL. Rys. 2.
92 ELEKTRONIKA PRAKTYCZNA 6/2009
Obsługa kart SD i modułu FatFs
wowym zródłem informacji na temat danych
zapisanych na nośniku. Zwykle, oprócz
głównej tablicy alokacji, występuje również
jej kopia. Czwarty obszar to katalog główny,
Rys. 3. który jest zakładany automatycznie w trakcie
tworzenia systemu plików. Ostatni, piąty re-
Tab. 1.
gion, to obszar danych.
komenda opis
CMD0 zeruje kartę, pozwala włączyć tryb pracy z magistralą SPI
Moduł FatFs
CMD12 wymuszenie zakończenia transmisji wielu bloków danych
System plików w urządzeniach wbudo-
CMD16 konfiguracja długości bloku danych dla zapisu/odczytu
wanych można zaimplementować na dwa
CMD17 odczyt bloku pamięci o długości określonej przez CMD16
sposoby: pisząc obsługę systemu plików od
CMD24 zapis bloku pamięci o długości określonej przez CMD16
podstaw, lub też wykorzystać gotowe rozwią-
CMD32 w argumencie jest przesyłany adres pierwszego bloku przeznaczonego do skasowania
CMD33 w argumencie jest przesyłany adres ostatniego bloku przeznaczonego do skasowania
zania. W zasadzie nie ma żadnego sensow-
CMD38 kasuje bloki wyznaczone za pomocÄ… CMD32 i CMD33
nego uzasadnienia pierwsze wymienione
podejście. System plików FAT jest na tyle do-
obsługiwanych w trybie pracy z magistra- Nośnik danych w systemie plików FAT brze udokumentowany, a przy tym stosun-
lą SPI wraz z opisem argumentów. Oprócz jest podzielony na pięć części, wszystkie kowo prosty, że powstało wiele darmowych
standardowych komend CMD karty SD mogą przedstawiono na rys. 3. Pierwszą logicz- narzędzi, które radzą sobie bardzo dobrze
wykorzystywać jeszcze tak zwane komendy ną częścią nośnika danych, umieszczoną z administracją zawartości nośnika danych
aplikacji (ACMD). Wysłanie komendy aplika- w pierwszym sektorze, jest obszar zarezer- z systemem plików FAT. Z reguły otwarty
cji wymaga uprzedniego wysłania komendy wowany, który zawiera wszystkie podsta- charakter kodu pozwala na wprowadzenie
CMD55, która informuje kartę SD, że następ- wowe informacje na temat bieżącej partycji koniecznych zmian i poprawek, które mogą
na będzie komenda ACMD. (nośnika). Do tych informacji zaliczają się m. się okazać niezbędne dla stabilności pracy
in.: typ i rozmiar partycji, rozmiar sektora, urzÄ…dzenia.
System plików FAT ilość sektorów w klastrze. Jednym z takich ogólnodostępnych na-
Z perspektywy systemu plików, każdy Za obszarem zarezerwowanym znajdują rzędzi jest moduł FatFs, którego zadaniem
nośnik danych (dysk twardy, karta pamięci) się tablice alokacji plików, które są podsta- jest stanowienie pomostu pomiędzy warstwą
podzielony jest na sektory i klastery. Sekto-
rem nazywamy najmniejszą liczbę bajtów,
List. 1.
static
jaką można zapisać lub odczytać. Zwykle
void SELECT (void) // CS w stan niski
sektor ma rozmiar 512 bajtów. Pliki zapisy-
{
wane sÄ… w numerowanych klastrach. Roz-
GPIO_ResetBits(GPIOC, GPIO_Pin_12);
miar klastra jest zależny od systemu plików
}
i nośnika danych. Każdy klaster jest w cało-
ści przydzielony do danego pliku, co ozna-
cza, że nawet jeśli plik jest dużo mniejszy od
static
rozmiarów klastra, to i tak na dysku zajmuje
void DESELECT (void) // CS w stan wysoki
tyle, co pojedynczy klaster.
{
Kluczowym elementem systemu plików
GPIO_SetBits(GPIOC, GPIO_Pin_12);
FAT (File Allocation Table) jest, zgodnie z je-
}
go nazwą, tablica alokacji plików. System
plików FAT występuje w sumie w czterech
static
odmianach, przy czym w systemach wbu-
dowanych zazwyczaj wykorzystuje siÄ™ dwie,
void xmit_spi (BYTE Data) // Wyslanie bajtu do SD
w zależności od rozmiarów nośnika i wyma-
{
gań aplikacji będzie to FAT16 lub FAT32. // Wyslanie bajtu
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, Data);
}
static
BYTE rcvr_spi (void) // Odebranie bajtu z SD
{
u8 Data = 0;
// Wyslanie 0xFF
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, 0xFF);
// Odebranie bajtu
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
Data = SPI_I2S_ReceiveData(SPI1);
return Data;
}
Rys. 4.
ELEKTRONIKA PRAKTYCZNA 6/2009 93
PODZESPOAY
Za konfiguracjÄ™ kontrolera SPI,
List. 2.
static
portów wejścia/wyjścia i ich sygna-
łów zegarowych odpowiada funkcja BYTE wait_ready (void)
power_on(), którą zamieszczono na
{
list. 3. Po zdefiniowaniu zmiennych,
BYTE res;
Rys. 5. wykorzystywanych w dalszym ko-
dzie funkcji, następuje włączenie
Timer2 = 50; // Czeka przez 500ms
fizyczną (nośnikiem pamięci), a aplikacją sygnałów zegarowych dla wyprowa-
rcvr_spi();
uruchomioną na mikrokontrolerze. Szcze- dzeń (porty GPIOA i GPIOC) i kon-
do
gółowych informacji na temat FatFs należy trolera SPI. Następnie konfiguro-
szukać na jego stronie internetowej  http:// wane jest wyprowadzenie PC12 do res = rcvr_spi();
elm-chan.org/fsw/ff/00index_e.html. Rola mo- sterowania wyborem układu (CS)
while ((res != 0xFF) && Timer2);
dułu FatFs w systemie wbudowanym została oraz piny PA5, PA6, PA7 jako linie
zilustrowana na rys. 4. magistrali SPI.
return res;
Sam moduł FatFs jest napisany w języ- Kontroler SPI jest ustawiany
}
ku C, a zatem jest całkowicie niezależny od jako master do pracy w trybie full
sprzętu. Pliki, które są niezbędne do popraw-
nej pracy FatFs zostały przedstawione na
List. 3.
static
rys. 5 w formie drzewa skopiowanego z pro-
jektu wykorzystującego system plików FAT. void power_on (void)
Teoretycznie, do poprawnej pracy moduł
{
GPIO_InitTypeDef GPIO_InitStructure;
FatFs wymaga obecności w systemie wbudo-
SPI_InitTypeDef SPI_InitStructure;
wanym zegara czasu rzeczywistego (RTC).
u8 i, cmd_arg[6];
u32 Count = 0xFFF;
Można ten wymóg bardzo łatwo obejść wpi-
// Konfiguracja wyprowadzen i kontrolera SPI:
sując stałe wartości w miejsce daty i czasu.
// Wlaczenie sygnalow zegarowych dla peryferiow
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC |
Implementacja modułu FatFs
RCC_APB2Periph_SPI1 | RCC_APB2Periph_AFIO,
w mikrokontrolerach STM32 ENABLE);
 warstwa fizyczna
// PA4 jako CS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
Do opracowania warstwy sprzętowej zo-
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
stał wykorzystany przykładowy projekt, za- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
mieszczony na stronie internetowej modułu
//SCK, MISO and MOSI
FatFs. Wszystkie funkcje, których zadaniem
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
jest sterowanie urzÄ…dzeniami peryferyjnymi
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
mikrokontrolera, oraz zapis i odczyt danych
GPIO_Init(GPIOA, &GPIO_InitStructure);
z karty pamięci, zostały umieszczone w jed-
// Konfiguracja SPI
nym pliku sd_stm32.c.
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
Bezpośrednio ze sprzętem komunikują się
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
cztery funkcje. Za odbieranie danych z kon- SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
trolera magistrali SPI odpowiada funkcja
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
rcvr_spi(), która została przedstawiona, wraz SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
z pozostałymi trzema na list. 1. Wysyłaniem
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
bajtów przez SPI do karty pamięci zajmuje się
funkcja xmit_spi(). Do zadań interfejsu sprzę- // Wlacz SPI
SPI_Cmd(SPI1, ENABLE);
towego należy jeszcze sterowanie sygnałem
wyboru układu CS, co należy do obowiązków
// Inicjalizacja karty i przelaczenie w tryb SPI:
funkcji SELECT() i DESELECT().
DESELECT(); // CS = 1
Czasem, gdy mikrokontroler zażąda do-
stępu do zasobów karty pamięci, może się
for (i = 0; i < 10; i++)
okazać, że ta ostatnia jest w danym momen-
xmit_spi(0xFF); // Wyslij 0xFF 10 razy = 80 cykli zegarowych
// (wymaganych co najmniej 74 cykli)
cie zajęta wykonywaniem innych operacji.
SELECT(); // CS = 0
Wtedy istotna jest możliwość sprawdzania
// Przygotowanie ramki inicjujacej do wyslania
zajętości karty. W tym celu została napisa-
cmd_arg[0] = (CMD0 | 0x40);
cmd_arg[1] = 0; // Argument komendy
na funkcja wait_ready(), przedstawiona na
cmd_arg[2] = 0; // nawet, gdy komenda go nie ma
list. 2. Jej zadaniem jest oczekiwanie przez
cmd_arg[3] = 0; // musi zostac wyslany w postaci zer
cmd_arg[4] = 0;
maksymalny czas 500 ms, aż odebrany bajt
cmd_arg[5] = 0x95; // CRC = 0x95
będzie miał wartość 0xFF. Jeżeli w ciągu
for (i = 0; i < 6; i++) // Wyslanie ramki
500 ms nie zostanie odebrany bajt 0xFF, to
xmit_spi(cmd_arg[i]);
funkcja kończy swoje działanie, zwracając
while ((rcvr_spi() != 0x01) && Count) // Czeka na 0x01
ostatnią wartość odczytaną z kontrolera SPI.
Count--;
Mamy już wszystkie niezbędne funkcje
DESELECT(); // CS = 1
zajmujące się interfejsem sprzętowym, jed- xmit_spi(0XFF); // Wyslij 0xFF
nak, aby mogły one w ogóle pracować, to
PowerFlag = 1;
sam sprzęt musi zostać odpowiednio skon-
}
figurowany.
94 ELEKTRONIKA PRAKTYCZNA 6/2009
Obsługa kart SD i modułu FatFs
List. 4.
wał funkcję disk_timerproc(), która jest wy-
void SysTick_Conf(void)
korzystywana dalej do odmierzania czasu.
{
// SysTick bedzie taktowany z f = 72MHz/8 = 9MHz
Do cyklicznego wywoływania wymienionej
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
wyżej funkcji został wykorzystany 24  bito-
// Przerwanie ma byc co 10ms, f = 9MHz czyli liczy od 90000
wy timer SysTick. Jego konfiguracja została
SysTick_SetReload(90000);
przedstawiona na list. 4.
// Odblokowanie przerwania od timera SysTick
Domyślnie główny zegar systemowy, po
SysTick_ITConfig(ENABLE);
powieleniu przez układ PLL, wynosi 72 MHz
// Wlaczenie timera
SysTick_CounterCmd(SysTick_Counter_Enable);
i z taką częstotliwością domyślnie jest takto-
}
wany SysTick. Aby uzyskać przerwanie co
10 ms zastosowano preskaler, dzielący sygnał
Tab. 2.
72 MHz przez 8, co w efekcie daje 9 MHz. Je-
komenda opis
śli chcemy, aby funkcja obsługi przerwania
f_mount  montuje (rejestruje dysk logiczny w systemie
od timera SysTick (SysTickHandler()) była
f_open otwieranie i/lub tworzenie pliku
wywoływana z częstotliwością 100 Hz, to
f_close zamykanie pliku
należy sprawić, aby licznik liczył od 90000.
f_read czytanie zawartości pliku
Bardziej szczegółowo timer SysTick został
f_write zapisywanie pliku
omówiony w EP12/08, natomiast w tym
f_Iseek przesuwa wskaznik zapisu/odczytu pliku
przypadku funkcja obsługi jego przerwania
f_truncate skraca długość pliku
wygląda następująco:
działanie podobne do f_close, z tym, że plik pozostaje otwarty, więc dalej można wy-
void SysTickHandler(void)
f_sync
konywać na nim operacje
{
f_opendir otwiera katalog
disk_timerproc();
f_readdir czyta zawartość katalogu
}
f_getfree pozwala odczytać liczbę wolnych klastrów
Omówione funkcje są jedynymi zależny-
f_stat odczytuje informacje o pliku/katalogu
mi od sprzętu fragmentami kodu w module
f_mkdir tworzy katalog
FatFs, zatem teraz zajmiemy się już najwyż-
f_unlink usuwa katalog lub plik
szą jego warstwą, umożliwiającą operacje na
f_chmod zmienia atrybuty pliku lub katalogu, np. plik może być tylko do odczytu
plikach i katalogach.
f_utime zmienia datę i czas dla określonego pliku lub katalogu
f_rename zmiana nazwy lub przeniesienie pliku/katalogu
Podstawowe operacje na plikach
f_mkfs tworzy system plików na nośniku
i katalogach
f_forward czyta dane z nośnika i bezpośrednio przekazuje dalej
Gdy mikrokontroler umie się już poro-
zumiewać z kartą SD i system plików jest
dupleks. Ramka danych będzie wynosić 8 karta SD domyślnie po włączeniu zasila- należycie obsługiwany, to kolejnym krokiem
bitów, a zatrzaskiwanie stanu linii będzie nia pracuje w trybie obsługi dedykowanego są już właściwe operacje na plikach i katalo-
następować na zboczu narastającym sygnału standardu SDBus. Aby komunikacja (odbie- gach, jakie wymaga projektowana aplikacja.
zegarowego. W stanie nieaktywnym na linii ranie komend) była w ogóle możliwa, należy Wszystkie funkcje, jakie oferuje moduł FatFs
SCK będzie występował stan wysoki. w pierwszej kolejności wysłać co najmniej 74 zostały omówione na jego stronie interneto-
Preskaler dla zegara kontrolera SPI zo- cykle zegarowe, w celu zainicjowania karty. wej http://elm-chan.org/fsw/ff/00index_e.html,
stał ustawiony na 4, co oznacza, że dane Następnie, żeby przejść do trybu pracy z SPI, a ich spis umieszczono w tab. 2. Tutaj zaj-
będą przesyłane z niebagatelną prędkością należy wysłać komendę CMD0. Jeśli inicja- miemy się przykładami aplikacji wykonywu-
18 Mbit/s. Po ustawieniu wszystkich pa- lizacja karty do pracy w trybie SPI zostanie jących niezbędne zadania na plikach i kata-
rametrów SPI, kontroler zostaje włączony przeprowadzona poprawnie, to karta zwróci logach.
przez wywołanie funkcji SPI_Cmd(). bajt potwierdzenia wynoszący 0x01. Przykładowy program, którego zadaniem
Od tego momentu mikrokontroler jest Moduł FatFs wymaga do pracy sygnału są podstawowe operacje na plikach i katalo-
już prawidłowo skonfigurowany, natomiast zegarowego, który co 10 ms będzie wywoły- gach pokazano na list. 5. Przedstawiony kod
REKLAMA
ELEKTRONIKA PRAKTYCZNA 6/2009 95
PODZESPOAY
najpierw montuje dysk logiczny za pomocÄ…
List. 5.
int main(void)
funkcji f_mount(), dzięki czemu moduł FatFs
{
FRESULT fresult;
będzie mógł wykonywać operacje dyskowe.
FIL plik;
W argumentach przesyłamy numer dys- WORD zapisanych_bajtow;
ku (tutaj 0) oraz, przez referencję, główną
RCC_Conf();
GPIO_Conf();
zmienną systemu plików typu FATFS.
SysTick_Conf();
Po zamontowaniu dysku można już do-
fresult = f_mount(0, &g_sFatFs);
wolnie zarządzać zawartością karty pamię-
// Tworzenie pliku
ci. W omawianym programie w pierwszej
fresult = f_open (&plik, plik.txt , FA_CREATE_ALWAYS);
kolejności następuje utworzenie nowego
fresult = f_close (&plik);
pliku tekstowego w katalogu głównym karty.
// Tworzenie katalogu
fresult = f_mkdir( katalog1 );
Wykorzystano do tego celu funkcjÄ™ f_open(),
która z pozoru (nazwy) nie ma z czynnościa- // Zapis pliku
fresult = f_open (&plik, plik.txt , FA_WRITE);
mi tworzenia plików wiele wspólnego. Mimo
fresult = f_write(&plik,  zawartosc pliku , 15, &zapisanych_bajtow);
fresult = f_close (&plik);
tego, że nazwa funkcji na to nie wskazuje, to
służy ona również do tworzenia nowych pli- // Usuniecie pliku
fresult = f_unlink( plik.txt );
ków.
while(1);
Jako pierwszy argument przekazujemy
}
(prze referencjÄ™) adres do uchwytu pliku.
Warto na to zwrócić uwagę, ponieważ, jak
Tab. 3.
się przy okazji omawiania pozostałych funk-
sposób otwarcia opis
cji okaże, jeśli operacje są wykonywane na
FA_READ plik otwierany do odczytu
pliku, to zawsze przekazujemy jego uchwyt
FA_WRITE plik otwierany do zapisu
w ten sposób. Drugim argumentem jest łań-
FA_OPEN_EXISTING otwarcie pliku, jeśli plik nie istnieje to zostanie zgłoszony błąd
cuch znaków, który będzie stanowił nazwę
FA_OPEN_ALWAYS otwarcie pliku, jeśli nie istnieje to zostanie stworzony nowy plik
pliku, w przedstawionym przykładzie bę-
FA_CREATE_NEW utworzenie nowego pliku, jeżeli plik istnieje to zostanie zgłoszony błąd
dzie to plik tekstowy o plik.txt. Jako trzeci
FA_CREATE_ALWAYS utworzenie nowego pliku, jeżeli już istnieje to nadpisanie na stary plik
argument przesyłamy żądanie akcji, jaka ma
być wykonana. Dla funkcji f_open() wszyst-
kie możliwe wartości ostatniego argumentu Jeśli można tworzyć pliki i katalogi, to wy- pliku, czyli innymi słowy zmniejszenia jego
pokazano w tab. 3. Na omawianym list. 5 wi- padałoby również móc je usuwać. Zapewnia rozmiarów. Można tego dokonać dzięki funkcji
dać, że program tworzy nowy plik, niezależ- to wywołanie funkcji f_unlink(), w argumencie f_truncate() (truncate  skracać), której wywoła-
nie, czy wcześniej istniał na karcie pamięci należy podajać nazwę pliku lub katalogu prze- nie może wyglądać podobnie poniżej zamiesz-
plik o nazwie plik.txt, czy nie. znaczonego do usunięcia. Zapis do pliku, po czonej linii kodu:
Każda funkcja z modułu FatFs zwraca jego wcześniejszym otwarciu do zapisu, wy- fresult = f_truncate(&plik);
wartość typu FRESULT. Generalnie, jeśli konuje się przez wywołanie funkcji f_write(). Jak widać, jedynym wymaganym do prze-
zwracana wartość wynosi 0, to wszystko Oprócz uchwytu do pliku przekazujemy tablice kazania argumentem jest adres do uchwytu
przebiegło prawidłowo, w przeciwnym wy- z bajtami przeznaczonymi do zapisu oraz liczbę pliku, czyli zmiennej (struktury) zawierają-
padku wystąpiły błędy. zapisywanych bajtów. Ostatnim argumentem cej wszystkie informacje na temat pliku, nie-
Oprócz tworzenia plików warto rów- jest przekazanie przez referencję zmiennej typu zbędne do jego poprawnego egzystowania
nież dysponować mechanizmem pozwala- DWORD, do której zostanie wpisana faktyczna w systemie plików. Funkcja f_truncate() do
jącym na tworzenie katalogów. W module ilość zapisanych do pliku bajtów. skracania długości pliku wykorzystuje aktu-
FatFs takiego mechanizmu dostarcza funkcja Administrowanie zawartością karty pamię- alny wskaznik zapisu/odczytu. Mechanizm
f_mkdir(). W argumencie do funkcji przeka- ci może niekiedy wymagać skracania długości zmniejszania rozmiarów pliku przedstawio-
zujemy nazwę katalogu. Jeśli katalog nie ma
być utworzony w jakimś innym katalogu to
List. 6.
/* File status structure */
wystarczy jego nazwa, a jeśli chcemy utwo-
typedef struct _FILINFO {
rzyć folder jako podkatalog, to należy podać DWORD fsize; /* Size */
WORD fdate; /* Date */
całą jego ścieżkę. Ostatni przypadek przed-
WORD ftime; /* Time */
char fname[13]; /* Name (8.3 format) */
stawia poniższa linia kodu:
} FILINFO;
fresult = f_mkdir( katalog1/
katalog2 );
List. 7.
fresult = f_opendir(&Dir,  katalog1 );
if(fresult != FR_OK)
return(fresult);
for(;;)
{
fresult = f_readdir(&Dir, &plikInfo);
if(fresult != FR_OK)
return(fresult);
if(!plikInfo.fname[0])
break;
// p jest wkaznikiem na tablice elemetnow typu FILINFO
*p++ = plikInfo;
}
Rys. 6.
96 ELEKTRONIKA PRAKTYCZNA 6/2009
Obsługa kart SD i modułu FatFs
List. 8.
no na rys. 6. Mechanizm skracania długości
void LCD_BMP(u8 * nazwa_pliku)
pliku może znalezć zastosowanie na przy-
{
u32 i = 0, j = 0, liczba_pikseli = 0, liczba_bajtow =0;
kład w systemach akwizycji dużej ilości da-
u16 piksel;
u8 temp[4]; nych, gdzie niekiedy zachodzi potrzeba od-
WORD ile_bajtow;
rzucenia części zebranych informacji.
FRESULT fresult;
FIL plik;
Przeglądanie zawartości karty
// Otwarcie do odczytu pliku bitmapy
fresult = f_open (&plik, (const char *) nazwa_pliku, FA_READ);
pamięci, informacje o plikach
// Opuszczenie dwoch pierwszych bajtow i katalogach
fresult = f_read (&plik, &temp[0], 2, &ile_bajtow);
Informacje na temat plików w modu-
// rozmiar pliku w bajtach
fresult = f_read (&plik, (u8*) &liczba_bajtow, 4, &ile_bajtow);
le FatFs można uzyskać poprzez wywoła-
nie funkcji f_stat(), wystarczy w programie
// Opuszczenie 4 bajtow
fresult = f_read (&plik, &temp[0], 4, &ile_bajtow);
umieścić następującą linię kodu:
// Odczytanie przesuniecia (offsetu) od poczatku pliku do
// poczatku bajtow opisujacych obraz
fresult = f_stat( plik.txt ,
fresult = f_read (&plik, (u8*) &i, 4, &ile_bajtow);
&plikInfo);
// Opuszczenie liczby bajtow od aktualnego miejsca
// do poczatku danych obrazu, wartosc 14, bo odczytane zostalo
Jako pierwszy argument należy podać łań-
// juz z pliku 2+4+4+4=14 bajtow
for(j = 0; j < (i - 14); j++) cuch znaków zawierający nazwę pliku, ściślej
fresult = f_read (&plik, &temp[0], 1, &ile_bajtow);
wskaznik na poczÄ…tek tablicy z nazwÄ… pliku.
// Liczba pikseli obrazu = (rozmiar pliku - offset)/2 bajty na pisel
liczba_pikseli = (liczba_bajtow - i)/2;
Informacje zostajÄ… zapisane do struktu-
ry typu FILINFO, której budowa pokazano
// Ustawienie parametrow pracy LCD (m. in. format BGR 5-6-5)
LCD_WriteReg(R3, 0x1008);
na list. 6, a jej adres jest przekazywany jako
LCD_WriteRAM_Prepare();
drugi argument w wywołaniu funkcji f_stat().
// Odczyt bajtow z karty SD i wyslanie danych do LCD
Dane na temat pliku, jakie otrzymujemy to:
for(i = 0; i < liczba_pikseli; i++)
{
rozmiar, data ostatniej modyfikacji, czas mo-
fresult = f_read (&plik, (u8*) &piksel, 2, &ile_bajtow);
LCD_WriteRAM(piksel); dyfikacji, atrybuty pliku, nazwa w tablicy 13
}
elementowej (format 8+3).
LCD_CtrlLinesWrite(GPIOB, CtrlPin_NCS, Bit_SET);
Przeglądu zawartości całego katalogu moż-
// Przywrocenie ustawien LCD
na dokonać z wykorzystaniem funkcji f_read-
LCD_WriteReg(R3, 0x1018);
dir(). Przykładowy program, który zbiera infor-
// Zamyka plik
fresult = f_close (&plik); macjÄ™ na temat tego, co znajdujÄ™ siÄ™ w folderze
}
katalog1 został przedstawiony na list. 7.
REKLAMA
ELEKTRONIKA PRAKTYCZNA 6/2009 97
PODZESPOAY
List. 9.
int main(void)
{
FRESULT fresult;
FATFS g_sFatFs;
DIR Dir;
FILINFO PlikInfo;
RCC_Conf(); NVIC_Conf(); GPIO_Conf(); SysTick_Conf();
// Inicjalizuj LCD
STM3210B_LCD_Init();
// Wyczysc LCD, tlo czarne
LCD_Clear(Black);
fresult = f_mount(0, &g_sFatFs);
//  Otworzenie katalogu glownego
fresult = f_opendir(&Dir,  / );
if(fresult != FR_OK)
return(fresult);
while (1)
{
Rys. 7.
if(!GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9))
{
fresult = f_readdir(&Dir, &PlikInfo);
Po otwarciu katalogu za pomocÄ… funkcji
// Jesli ostatli plik to przegladanie
f_opendir() w nieskończonej pętli następuje
// od poczatku
odczytywanie informacji o kolejnych plikach
if(!PlikInfo.fname[0])
{
i folderach przez skopiowanie struktury wy-
fresult = f_opendir(&Dir,  / );
żej omówionego typu (FILINFO). Kolejne wy- fresult = f_readdir(&Dir, &PlikInfo);
}
wołania funkcji f_readdir() powodują samo-
if(fresult != FR_OK)
czynne czytanie informacji o następujących
return(fresult);
po sobie elementach katalogu. Jeśli pole na-
LCD_DrawBMP((u8*) PlikInfo.fname);
zwy elementu będzie puste, to oznacza wte-
}
dy, że nie ma już w danym folderze elemen- }
}
tów i wykonywanie pętli zostaje przerwane.
Przeglądarka obrazów Zakładamy, że obrazy mają być dopasowane prezentowany przez cztery bajty, to nie ma
Płytka ewaluacyjna STM3210B-EVAL do wyświetlacza, a zatem ich wymiary muszą możliwości bezpośredniego uzyskania roz-
jest wyposażona w graficzny wyÅ›wietlacz mieć 320×240 pikseli. Plik graficzny musi być miaru w zmiennej 32 bitowej. Problem zo-
LCD o rozmiarach 320 na 240 pikseli, który zakodowany w formacie 16 bitowej bitmapy, stał rozwiązany przez przekazanie do funkcji
umożliwia wyświetlanie obrazów w 262000 ponieważ taki typ wspiera wyświetlacz graficz- czytającej bajty z pliku zmiennej 32-bitowej
kolorów. Mając do dyspozycji karty pamięci ny dostarczany wraz z STM3210B-EVAL. Taki z wcześniejszym rzutowaniem na wskaznik
i graficzny LCD można zbudować przyjazny, tryb kodowania oznacza, że na każdy piksel 8-bitowy. Dzięki temu funkcja f_read() bę-
graficznie rozbudowany interfejs użytkowni- przypadają dwa bajty. Niestety standardowe dzie zapisywać pojedyncze komórki pamięci
ka. Do obsługi wyświetlacza LCD zostały wy- narzędzia Windowsa nie umożliwiają zapisu tak, jakby była to tablica czteroelementowa.
korzystane funkcje dostarczane przez firmÄ™ pliku bitmapy w formacie 16-bitowym, jest W efekcie uzyskany zostanie efekt zapisu ca-
STMicroelectronics. jednak wiele programów dostępnych w Inter- łej zmiennej 32-bitowej wartością określają-
Jedną z możliwych aplikacji, która poka- necie, które umożliwiają konwersję bitmap. cą rozmiar pliku.
zuje sposób współpracy karty SD i wyświe- Po przygotowaniu kilku obrazów do testów Zgodnie z przedstawionym nieco wcze-
tlacza graficznego, jest przeglądarka obrazów i wgraniu ich na kartę pamięci do katalogu śniej rys. 7 teraz należy opuścić cztery bajty,
zapisanych na karcie pamięci. Zadaniem głównego, można już przystąpić do budowy by następnie odczytać przesunięcie danych
przeglądarki obrazów będzie odczytywanie i testowania aplikacji. obrazu w stosunku do początku pliku. Na
zawartości plików w formacie BMP z karty Cały kod, jaki jest niezbędny do po- podstawie uzyskanego offsetu zostaje wyzna-
SD, a następnie pokazywanie obrazu na LCD. prawnego odczytania i pokazania na LCD czona liczba piskeli, z jakiej składa się obraz,
Żeby dobrze zrozumieć działanie progra- zawartości pliku bitmapy, został zapisany po czym w pętli odczytywane są bajty pikseli
mu, najpierw należy zapoznać się z budową w funkcji LCD_BMP(), którą przedstawiono i wysyłane do wyświetlacza LCD.
plików w formacie bitmapy (BMP). W pierw- na list. 8. Jako argument do funkcji należy Główna funkcja programu została za-
szym przybliżeniu każdy plik BMP składa się przesłać łańcuch znaków reprezentujący na- mieszczona na list. 9. Jej zadanie polega na
z nagłówka oraz właściwych danych opisują- zwę pliku. Funkcja po zadeklarowaniu nie- konfiguracji urządzeń peryferyjnych do pra-
cych obraz. Nagłówek zawiera informacje m. zbędnych zmiennych otwiera, znajdujący się cy oraz na reagowaniu na naciśnięcie przy-
in. na temat rozmiaru pliku, rozmiarów obrazu w katalogu głównym karty, plik o nazwie po- cisku użytkownika na płycie ewaluacyjnej.
w pikselach itd. Do zaprogramowania przeglą- danej przesłanej w argumencie wywołania. Z każdym naciśnięciem będzie wyświetlany
darki obrazów z nagłówka wystarczy wyłuskać Pierwszą niezbędną informacją, jaką nale- kolejny obraz z karty SD. Działanie aplikacji,
informacje na temat liczby pikseli z jakiej skła- ży uzyskać jest rozmiar całego pliku w baj- z przykładowym obrazem na wyświetlaczu
da się obraz oraz miejsce w pliku, gdzie rozpo- tach, który jest zapisany na czterech bajtach LCD, ilustruje fotografia otwierająca artykuł.
czynają się bajty opisujące piksele. z przesunięciem 2 bajtów (rys. 7). Podczas Krzysztof Paprocki
BudowÄ™ aplikacji znacznie uproszczÄ… odczytywania rozmiaru pliku wykorzystano poprocki.krzysztof@gmail.com
wstępne wymagania co do plików graficznych. ciekawy sposób. Ponieważ rozmiar jest re-
forum.ep.com.pl
98 ELEKTRONIKA PRAKTYCZNA 6/2009


Wyszukiwarka

Podobne podstrony:
Obsługa kart pamięciowych SD, cz 2
Bootloader dla mikrokontrolerów STM32 Aktualizacja oprogramowanie z zastosowaniem karty SD lub prz
Obsługa kart pamięci Flash, część 2
Obsługa kart pamięci Flash, część 7
Obsługa kart pamięci Flash, część 4
Mikrokontrolery STM32 Bezpieczeństwo i stabilność
Obsługa kart pamięci Flash, część 3
Mikrokontrolery STM32 Wykorzystanie ADC i DMA
Mikrokontrolery STM32 Użycie interfejsu I2C, USART, SPI
Obsługa kart pamięci Flash, część 6
Obsługa kart pamięci Flash, część 5
Programowanie pamięci Flash mikrokontrolerów STM32 – Flash Loader
Obsługa kart pamięci Flash, część 1
STM32 Butterfly RS232
obsługa pojazdu Egzamin

więcej podobnych podstron