Підключення sd карти до мікроконтролера
В одній з минулих статей, ми виводили картинку на дисплей з sd картки, але в ній були втрачені деякі моменти, перший - підключення самої картки, другий - була розглянута лише частина функцій бібліотекиPetit FatFs, давайте зупинимося на цих моментах докладніше.
Спілкування з карткою можливе за одним із двох інтерфейсів,SPIабоSD.




Треба сказати, що інтерфейс SD може працювати в однобітному і чотирибітному режимах.
Схема підключення картки по SPI стандартна і виглядає наступним чином, висновки картки, що не використовуються, потрібно за допомогою резистора 10К підтягнути до живлення.

Але в аматорських конструкціях часто нехтують резисторами, що підтягують, спрощуючи схему підключення.
Треба відзначити, що при підключенні по SPI картка дуже вимоглива до напруги живлення і невелика просадка напруги живлення призводить до непрацездатності картки, це перевірено на особистому досвіді, з приводу SD інтерфейсу сказати нічого, ще не пробував. Це все писав до того, що з харчування обов'язково ставити конденсатори. Що стосується дроселя, він має бути розрахований на струм до 100мА, але ставити його необов'язково.
На схемах, зображених вище видно, що з роботи картці необхідно 3.3 вольта, відповідно, лініях передачі напруга має виходити за діапазон 0 – 3.3 вольт і виникає питання, що робити якщо МК живиться від 5 вольт? Ответ простий , Треба узгодити лінії передачі даних, а зробити це можна за допомогою звичайного резистивного дільника.


З підключенням розібралися, тепер розглянемо як користуватися бібліотекоюPetit FatFs, яка призначена для 8-бітових мікроконтролерів з малим розміром пам'яті.
Бібліотека складається з 5 файлів:integer.h- заголовний файл, в якому описані основні типи даних.
diskio.h- заголовний файл, в якому оголошено прототипи низькорівневих функцій для роботи з диском та статусні коди, які вони повертають.
diskio.c- у цьому файлі мають бути реалізовані низькорівневі функції, спочатку там "заглушки".
pffсonf.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- не відкрита директорія