Свързване на sd картата към микроконтролера
В една от предишните статии показахме картина на дисплея от sd карта, но някои точки бяха пропуснати в нея, първата - свързването на самата карта, втората - беше разгледана само част от функциите на библиотекатаPetit FatFs, нека се спрем на тези точки по-подробно.
Комуникацията с картата е възможна чрез един от двата интерфейса,SPIилиSD.
Трябва да кажа, че SD интерфейсът може да работи в еднобитов и четирибитов режим.
Схемата за свързване на картата през SPI е стандартна и изглежда така, неизползваните щифтове на картата трябва да бъдат свързани към захранването с помощта на резистор 10K.
Но в аматьорските дизайни издърпващите резистори често се пренебрегват, което опростява схемата на свързване.
Трябва да се отбележи, че когато е свързана през SPI, картата е много взискателна към захранващото напрежение и малък спад на захранващото напрежение води до неработоспособност на картата, това е проверено от личен опит, няма какво да кажа за SD интерфейса, все още не съм го пробвал. Всичко това беше написано на факта, чее необходимо да се инсталират кондензатори за захранване. Що се отнася до индуктора, той трябва да бъде номинален за ток до 100mA, но не е необходимо да го инсталирате.
Показаните по-горе диаграми показват, че картата се нуждае от 3,3 волта, за да работи, съответно в линиите за данни напрежението не трябва да надхвърля диапазона от 0 - 3,3 волта и тук възниква въпросът, какво ще стане, ако MC се захранва от 5 волта? Отговорът е прост, трябва да координирате линиите за данни и това може да стане с помощта на конвенционален резистивен делител.
Разбрахме връзката, сега нека да видим как да използваме библиотекатаPetit FatFs, който е предназначен за 8-битови микроконтролери с малък размер на паметта.
Библиотеката се състои от 5 файла:integer.h- заглавен файл, който описва основните типове данни.
diskio.h- заглавен файл, който декларира прототипи на дискови функции от ниско ниво и кодове за състояние, които те връщат.
diskio.c- в този файл трябва да бъдат внедрени функции от ниско ниво, първоначално има "закъснения".
pffconf.h- конфигурационен файл.
pff.h- заглавен файл, който декларира прототипите на функциите за взаимодействие с дисковата файлова система.
pff.c- файлът съдържа реализации на функции за взаимодействие с дисковата файлова система.
Вижда се, че за да работи библиотеката, е необходимо да се внедрят функции от ниско ниво. Но ако говорим за AVR или PIC, можете да изтеглите пример за работа с библиотеката за тях на сайта, в който има файлmmc, функциите на ниско ниво вече са внедрени в него. Също така е необходимо да зададете конфигурацията на библиотеката във файла pff.h и да напишете функциите, необходими за работата на SPI.
Функции на Petit FatFs.
FRESULT pf_mount (FATFS*)— функцията монтира/демонтира диск. Тази функция трябва да бъде извикана преди започване на работа с диска, ако извикате функцията с нулев указател, дискът се демонтира. Функцията може да бъде извикана по всяко време.
ПараметриFATFS* fsе указател към обект от типа FATFS, описание на тази структура може да се намери във файла pff.h. Просто трябва да декларираме променлива от този тип.
Върнати стойности:FR_OK (0)- връща се, ако функцията е била успешнаFR_NOT_READY- устройството не може да бъде инициализираноFR_DISK_ERR- възникнагрешка при четене от дискFR_NO_FILESYSTEM- дискът няма валиден FAT дял
Параметриconst char* pathе указател към низ, указващ пътя към файла. Пътят трябва да бъде посочен изцяло спрямо главната директория, разделяйки директориите с наклонена черта.
Върнати стойности:FR_OK (0)- връща се, ако функцията е била успешнаFR_NO_FILE- файлът не е намеренFR_DISK_ERR- грешка на дискаFR_NOT_ENABLED- дискът не е монтиран
Върнати стойности:FR_OK (0)- връща се, ако функцията е била успешнаFR_DISK_ERR- дискова грешкаFR_NOT_OPENED- файлът не е отворенFR_NOT_ENABLED- дискът не е монтиран
FRESULT pf_write(const void* buff, WORD btw, WORD* bw)- функцията ви позволява да записвате данни в отворен файл. За да работи функцията във файла pffconf.h, трябва да напишете#define _USE_WRITE 1
Параметри:void* buff— указател към буфера, който искаме да напишем, нулева стойност финализира записаWORD btw— брой байтове, които искаме да напишемWORD* bw— указател към променлива, която съхранява броя байтове, които сме успели да напишем. Като анализирате тази променлива, можете да разберете дали краят на файла е достигнат.
Върнати стойности:FR_OK (0)- връща се, ако функцията е била успешнаFR_DISK_ERR- дискова грешкаFR_NOT_OPENED- файлът не е отворенFR_NOT_ENABLED- дискът не е монтиран
Поради факта, че библиотеката е предназначена за микроконтролери с малък обем памет, тази функция има редица ограничения:
- не можете да създавате нови файлове и можете да пишете само в съществуващи
- размерът на файла не може да бъде увеличен
- забранено еактуализирайте клеймо за време
- операцията по запис може да бъде стартирана/спряна само на граница на сектор
- файловият атрибут само за четене не може да забрани записите
За да разберете предпоследната точка, трябва да знаете, че паметта на картата е разделена на блокове (сектори) от 512 байта изаписът може да започне само от началото на сектора. Така, ако искаме да запишем 1000 байта, тогава първият сектор ще бъде записан изцяло, а във втория ще бъдат записани само 488 байта, а останалите 24 байта ще бъдат запълнени с нули.
За да пишете в отворен файл, направете следното:
- задайте показалеца към границата на сектора, ако не е зададен към границата, показалецът ще бъде закръглен към долната граница на сектора
- извикайте функцията за запис необходимия брой пъти
- финализирайте записа, като извикате функцията с нулев указател
За да се даде пример за работата на функцията за запис, е необходимо да се разгледа още една функция.
FRESULT pf_lseek(DWORD offset)- задава указателя за четене/запис в отворения файл. Можете да зададете показалеца с абсолютно или относително отместване; за абсолютно отместване трябва да подадете число към функцията
за относителна, прехвърлете стойността на указателя към текущата позицияfs.fptrи стойността на отместването
За да работи функцията във файла pffconf.h, трябва да напишете#define _USE_LSEEK 1
Параметри:DWORD offset- броят байтове за изместване на указателя.
Върнати стойности:FR_OK (0)- връща се, ако функцията е била успешнаFR_DISK_ERR- грешка на дискаFR_NOT_OPENED- файлът не е отворен
Можете да запишете данни във файл по следния начин.
Тук също оставям парченаистина работещ код, който използва всички гореописани функции.
FRESULT pf_opendir(DIR* dp, const char * path)— функцията отваря съществуваща директория и създава указател към обект от типа DIR, който ще се използва за получаване на списък с файлове в отворената директория. За да работи функцията във файла pffconf.h, трябва да напишете#define _USE_DIR 1
Параметри:DIR *dp— указател към променлива от тип DIR.
const char * path— указател към низ, съдържащ пътя към директорията, директориите са разделени с наклонена черта
Връщани стойности:FR_OK (0)- връща се, ако функцията е била успешнаFR_NO_PATH- не може да намери пътяFR_NOT_READY- неуспешно инициализиране на дискаFR_DISK_ERR- грешка на дискаFR_NOT_ENABLED- дискът не е монтиран
FRESULT pf_readdir(DIR* dp, FILINFO* fno)— функцията позволява четене на съдържанието на директория. За да направите това, отворете директория с функцията pf_opendir() и извикайте pf_readdir(). При всяко извикване на функцията тя ще върне името на обекта (папка/файл), намиращ се в посочената директория. Когато премине през всички обекти, ще върне нулевия низ в елемента на масива fno.fname[]. За да работи функцията във файла pffconf.h, трябва да напишете#define _USE_DIR 1
Параметри:DIR *dp- указател към променлива от тип DIR, която трябва да бъде предварително декларирана
FILINFO *fnoе указател към променлива от тип FILINFO, която трябва да бъде предварително декларирана.
Върнати стойности:FR_OK- успешно завършване на функциятаFR_DISK_ERR- грешка на дискаFR_NOT_OPENED- директорията не е отворена