Подключаем SD карту памяти к STM32 по SPI
«Много информации не бывает —
бывает мало места для её хранения»
какая-то реклама в каком-то популярном
компьютерном журнале 90-х годов.
Если в проекте нужно выводить или получать большие объемы данных то на помощь придут различные flash микросхемы памяти. Если же нежно получать или выводить ОГРОМНЫЕ объемы данных, то стоит задуматься о более вместительном хранилище информации. На роль такого вместилища подходит SD карта памяти. Это – огромный носитель информации, по сравнению с обычными микросхемами памяти, объём которых редко превышает 64Мбита.
Подключение SD карты к STM32vlDiscovery
В статье рассмотрим подключение и диалог SD карты памяти с микроконтроллером STM32, через SPI. Без использование файловой системы.
В качестве контроллера и платы выступит демонстрационная плата STM32vlDiscovery с контроллером STM32F100RB на борту. Диалог с платой будет производиться по UART, точнее, через преобразователь USB-UART будем общаться через COM терминальную программу AL Terminal. Связь с картой памяти будет осуществляться через SPI.
Подключение карты памяти к STM32F100RB установленному в Discovery будет выглядеть следующим образом:
Схема
Контроллер установлен на демонстрационной плате и его подключение расписывать не буду. Преобразователь USB-UART описан в статье — USB-UART на cp2102 , можете применить и любой другой, например ft232 . Карта памяти подключается напрямую к микроконтроллеру, т.к. напряжение питание и логические уровни сигналов, в 3.3В, у них одинаковые.
Распиновка SD карты в SPI режиме
С подключением ничего сложного нет, переходим к коду.
Проект написан в Keil с использованием CMSIS и Standard Peripheral Library. Из SPL применены GPIO, RCC И USART библиотеки. Библиотеку для работы с картой памяти воспользовался готовой, взял с сайта «My Controller» — http://mycontroller.ru/category/vneshnie-ustroystva/karta-pamyati-sd/ .
Возможности библиотеки:
SD_init() – инициализация SPI и карты памяти
в случае удачи возвращает 0.
SD_sendCommand(cmd, arg) – посылка команды SD карте
Где: cmd – команда, arg – аргумент
Основные команды:
GO_IDLE_STATE 0 – программная перезагрузка
SEND_IF_COND 8 – для SDC V2 — проверка диапазона напряжений
READ_SINGLE_BLOCK 17 – чтение указанного блока данных
WRITE_SINGLE_BLOCK 24 – запись указанного блока данных
SD_SEND_OP_COND 41 – начало процесса инициализации
APP_CMD 55 – главная команда из ACMD команд
READ_OCR 58 – чтение регистра OCR
Команд для работы с картой памяти на самом деле гораздо больше, но в библиотеки задействованы только эти, чего для минимальной работы достаточно.
SD_ReadSector(BlockNumb,*buff) – прочитать сектор
в случае неудачи возвращает 0
Где: BlockNumb – адрес блока карты памяти, *buff – ссылка для буфера
SD_WriteSector(BlockNumb,*buff) – записать сектор
в случае неудачи возвращает 0
Где: BlockNumb – адрес блока карты памяти, *buff – ссылка для буфера
На основе библиотеки написал небольшую оболочку для ознакомления с картой памяти:
unsigned long address,i; unsigned char c; init(); // инициализация переферии if(SD_init()==0) // инициализация SD карты памяти { send_Uart_str(USART1,"init sd ok\n"); } else { send_Uart_str(USART1,"init sd fail\n"); } send_Uart_str(USART1,"alex-exe.ru"); // выводим сообщение в UART while(1) { send_Uart_str(USART1,"\n----------------------------\n"); send_Uart_str(USART1,"Read or write sd card r/w = "); c=getch_Uart(USART1); // читаем байт с uart while(getch_Uart(USART1)!=13){} // дожидаемся ввода enter с uart send_Uart_str(USART1,"\nPress enter address = "); buff_clear(); // очистка буфера address=read_int_uart(USART1); // читаем число с uart, адрес сектора на sd карте send_Uart_str(USART1,"\nAddress = "); send_int_Uart(USART1,address); // выводим для проверки введенное число send_Uart(USART1,'\n'); if(c=='w') // проверка на запись или чтение карты памяти { send_Uart_str(USART1,"Press enter data blok (max 512B), to exit press enter\n"); read_str_uart(USART1,Buff); // читаем строку с uart, окончание enter i=0; while((i < 512)&&(Buff[i]!=0))i++; // ищем конец текстовой строки send_Uart_str(USART1,"Length text data = "); send_int_Uart(USART1,i); // выводим длину текстового послания send_Uart(USART1,'\n'); if(SD_WriteSector(address, Buff)==0) // запись буфера на SD карту { send_Uart_str(USART1,"write sd ok\n"); } else { send_Uart_str(USART1,"write sd fail\n"); } } else { if(SD_ReadSector(address, Buff)==0) // чтения SD карты в буфер { send_Uart_str(USART1,"read sd ok\n"); } else { send_Uart_str(USART1,"read sd fail\n"); } for(i=0;i < 512;i++) // вывод содержимого буфера в терминал { send_Uart(USART1,Buff[i]); } } // на последок мигнём светодиодом GPIO_SetBits(GPIOC, GPIO_Pin_8); // включить синий светодиод на PC8 delay(1000000); GPIO_ResetBits(GPIOC, GPIO_Pin_8); // выключить синий светодиод на PC8 }
В коде реализована возможность чтения и записи блоков карты памяти через терминал.
Эксперименты проводил с картами памяти SD Transcend 2 GB и SDHC Qumo 8GB.
В статье использовались материалы с сайта «My Controller» — http://mycontroller.ru/category/vneshnie-ustroystva/karta-pamyati-sd/.
Схема обновлена 2 октября 2013 года
Alex_EXE | 14.08.2013 | STM32 |
Alex_EXE пишет 14.08.2013 в 14:13 #
P.S. кто поможет найти оригинальную картинку той рекламы в лучшем качестве — буду благодарен.
Игорь пишет 16.09.2013 в 02:52 #
Скачал исходник.
Вывалились ошибки:
stm32 nok1100 disp.axf: Error: L6218E: Undefined symbol USART_Cmd (referred from main.o).
stm32 nok1100 disp.axf: Error: L6218E: Undefined symbol USART_GetFlagStatus (referred from main.o).
stm32 nok1100 disp.axf: Error: L6218E: Undefined symbol USART_Init (referred from main.o).
stm32 nok1100 disp.axf: Error: L6218E: Undefined symbol USART_ReceiveData (referred from main.o).
stm32 nok1100 disp.axf: Error: L6218E: Undefined symbol USART_SendData (referred from main.o).
Добавил в проект библиотеку для работы с USART — скомпилилось (неплохо было бы все же об этом упомянуть в статье, а?), но карта не инициализируется. Пробовал менять местами выводы MISO и MOSI — результат нулевой…
Alex_EXE пишет 16.09.2013 в 23:53 #
В проекте использую Standard Peripheral Library + заметно упоминание в тексте и коде об UART’е, думал это само собой влечет использование USART библиотеки. Используемые библиотеки из SPL перечислил. Чуть позже думаю выложить проект целиком.
Есть ли диалог по UART? Что за карта? Она живая? Пробовали ли другие карты?
Игорь пишет 17.09.2013 в 18:19 #
Ситуация — человек, ни разу ДО того не сталкивавшийся с STM32, находит в интернете Ваши статьи, начинает их читать. Ставит необходимый софт и читает Ваши статьи, последовательно одну за другой, попутно компилируя примеры и проверяя работоспособность на плате STM32VL Discovery (как это у Вас в первой статье сказано). В первом примере все разжевано и разложено по полочкам — какие файлы библиотек куда положить, как структуру проекта оформить, какие опции в свойствах проекта включить/выключить. Все понятно, все прекрасно. Статья для новичков. В статье про подключение SD-карт — полная противоположность, как в той песне — «догадайся, мол, сама…». Мало того — на схеме подключения карты указаны пины процессора, хотя по идее должны быть указаны пины разъемов платы STM32VL Discovery (коли уж повествование началось на ее базе). Думаю, что в статьях должна прослеживаться некая преемственность, раз уж начали опираться с первой статьи на STM32VL Discovery — на ее базе и остальное повествование продолжайте. Так будет намного проще для читающих Ваши статьи.
По УАРТу данные в терминалку падают, в обратную не пробовал.
В процессе написания ответа взял другую карту — не инитится. Поменял местами выводы MISO и MOSI на разъеме дискавери — заработало. Так что в схемке ошибочка наблюдается. Кстати, вот тут http://mycontroller.ru/stm32-sd-card-podklyuchenie/ схема подключения правильная. Подключение карты к плате STM32VL Discovery получается таким: карта пин 1 — PA4, карта пин 2 — PA7, карта пин 5 — PA5, карта пин 7 — PA6. Заработала одна старая карточка (16 Мб) и новая (2 Гб). Старая карточка 8 Мб (раритет, однако 😉 ) от видеокамеры JVC инициализироваться не захотела.
Пожелание: если не затруднит, описывайте подробнее добавления/изменения в проекте и т.п.. Опытным товарищам это можно и не читать, а неопытным будет ясно и не будут возникать всякие глупые вопросы. 🙂
Игорь пишет 17.09.2013 в 18:27 #
ЗЫ. Блоки данных пишутся/читаются на/с карты. Спасибо за статью!
Alex_EXE пишет 17.09.2013 в 18:35 #
Там идет специальная обучающая серия и она пронумерована, вот в ней пытаюсь максимально разжевать. Обычные же статьи могу быть, как обзорные/поверхностные, т.е. самое основное, т.к. материала очень много и всего не упомянуть, а могут быть так же развернутыми. К примеру: эта статья появилась раньше, чем рассказал об UART’е и SPI, не откладывать же материал на потом? да и когда будет этот потом и будет ли вообще?
За замечание насчёт перепутанных выводов спасибо, как выйду на работу с больничного перепроверю (SD карты у меня там остались).
Ответ на пожелание — постараюсь.
Alex_EXE пишет 01.10.2013 в 09:04 #
В схеме ошибка подтвердилась, вечером информацию обновлю. Спасибо, что заметили.
DroN пишет 03.10.2013 в 04:59 #
Спасибо, все отлично работает на F103RB, кингстон сдхц на 4гб скушалась без приреканий. Правда я не сразу заметил, что у меня на плате PA4 — это слейв-селект не для карточки, отладка слегка затянулась ))
Сергей пишет 15.10.2013 в 18:15 #
Вы написали что : SD_init() – инициализация SPI и карты памяти
в случае неудачи возвращает 0.
Разве не наоборот, в случае успешной инициализации, возвращается ноль, иначе — единица ?
Alex_EXE пишет 16.10.2013 в 00:53 #
Ошибся, исправим. Спасибо, что заметили.
Сергей пишет 18.10.2013 в 22:14 #
А вы пробовали SDHC карту? Она инициализируется но не получается не прочитать не записать, плюс не понятно как ее адресовывать,что то в интернете толком ни чего не нашел
Alex_EXE пишет 18.10.2013 в 22:45 #
Пробовал SDHC Qumo 8GB — чтение успешно, запись не помню проверял ли. Другие карты не пробовал.
Сергей пишет 18.10.2013 в 23:30 #
странно, у меня кингстон SDHC на 2гб не пишется и не читается
Alex_EXE пишет 20.10.2013 в 23:27 #
Ещё может от карточки зависеть, т.е. повезет — не повезет.
Scorpion_ak107 пишет 06.12.2013 в 01:35 #
Скажите, пожалуйста, а можно ли как-то прочитать данные, записанные на sd карту (без файловой системы), с компьютера. Я имею ввиду использование каких-либо программ для восстановления данных с флешек и пр? Дело в том, что с FatFS постоянно возникают проблемы (с низкоуровневыми функциями, скорее всего). Или чинить их или искать программы.
Alex_EXE пишет 09.12.2013 в 23:39 #
Такого ПО не искал — на примете нечего нет.
Там в инструкциях к библиотеки есть описание и замечания по её критическим участкам, например, на время каких операций лучше запретить прерывания и прекращение каких приведет к повреждению данных.
adam пишет 03.01.2014 в 23:14 #
Было бы куда интереснее найти/сочинить универсальный драйвер для картридеров которые есть сейчас в любом буке для использования слотов CD/MMC вкачестве универсального SPI интерфейса / программатора , естественно с эмуляцией СОМ порта потому как практически весь софт программаторов работает через СОМ/LPT и практически все железки теперь имеют биос/загрузчики через SPI или общается через него , вот тогда бы вам народ памятник поставил (хотя бы виртуальный).
Удивляюсь почему до сих пор никто такого драйвера не написал , не думаю что это невозможно или архи сложно — «хардвару обходим сфтварой а софтвару — хардварой» , однако сколько не рыл в инете такого драйвера не нашел , а самому писать — слабо .
wr пишет 23.01.2014 в 15:20 #
Хорошая статья! Можно увидеть весь проект с описанной инициализацией карточки ?
Alex_EXE пишет 27.01.2014 в 00:49 #
А к статье разве он не прикреплен?
SlovachevskyDV пишет 29.12.2014 в 03:58 #
Ссылка на сайт MyController битая. Выложите, если есть возможность библиотеку работы с SD или проект целиком.
Alex_EXE пишет 29.12.2014 в 12:21 #
Хм… думал все основные файлы проекта выложил, вечерком постараюсь добавить.
На счёт сайта — да, печаль, хороший был ресурс, но уже, как с год помер и полноценной копии материалов с того ресурса нигде найти не могу.
Тот сайт, по библиотеке FatFS, на самом деле занимался переводом аналогичного ресурса, библиотеку можете скачать от туда — FatFs — Generic FAT File System Module , плюс там есть ещё её обновление от 14 ноября текущего года.
SlovachevskyDV пишет 29.12.2014 в 15:01 #
Спасибо.
Alex_EXE пишет 30.12.2014 в 00:38 #
Все основные файлы проекта выложены, остаётся только standard peripheral library поставить.
MaxKorj пишет 14.03.2015 в 21:08 #
Добрый вечер!
Интересует вопрос создания и записи данных в текстовый файл на флешке с периодичностью в 100кГц.
ДАНИЛ пишет 30.03.2015 в 17:59 #
Есть камера DCR-DVD203E ПИШИТ на мини сд диск …задача убрать сд и установить блок записываюший на флеш карту 32-64 ГБ.. ЕСТЬ ВНАЛИЧИИ НО КАК СДЕЛАТЬ ???? ВОПРОС— СМОГЛИ БЫ СДЕЛАТЬ И ЦЕНА ВОПРОСА
Alex_EXE пишет 31.03.2015 в 13:25 #
По обоим вопросам не чем помочь не смогу.
Дмитрий пишет 14.12.2015 в 12:41 #
«Если вы обнаружили, что обратная связь не работает, просьба сообщить об этом через комментарии».
Сообщаю 😉
Alex_EXE пишет 14.12.2015 в 13:15 #
Сайт работает исправно, всё что приходит вижу. Это меня завалило работой по всем фронтам. И поэтому уже с пару недель на сайт не отвечаю. Скоро одни дела завершу и на недели со временем должно будет быть чуть посвободнее, отвечу на всё, что накопилось.
1. В идеале лучше использовать простые карты памяти, не HD. Но статистики по картам у меня нет.
2. Перепроверьте распиновку карты памяти по другим ресурсам в интернете, кто-то когда то замечал у меня ошибку, не помню подтвердил её и исправил или нет.
Дмитрий пишет 14.12.2015 в 14:45 #
Понятно, извиняюсь за нетерпение 🙂
Спасибо за ответ, если найду ошибку — напишу в чем было дело.
Дмитрий пишет 14.12.2015 в 16:20 #
Хм, проблема оказалась в интересном месте. На одном форуме нашел статью человека, у которого была схожая проблема. На ножках, задействованных в SPI1, также висит JTAG. Так вот оказалось, что он включается автоматически после Reset, несмотря на то, что я нигде его не включаю как альтернативную функцию. В статье предлагалось решение этой проблемы (http://we.easyelectronics.ru/STM32/na-traktore-cherez-zasady-stm32spi-sd.html), я же просто использовал другой SPI. После чего стало возможным отослать 74 синхроимпульса.
P.S. Правда дальше все равно не заработало 🙂 После отсылки запроса на программный сброс(с пустым аргументом) ответа на команду не приходит 🙁 Будем искать еще ошибки.
Дмитрий пишет 15.12.2015 в 17:53 #
И это снова я. И опять ошибка возникала из-за неправильной работы ножки. В качестве ножки SlaveSelect я выбрал ту, которая указана в ДШ как NSS для SPI2. Настроил ее на ее на управление программно. Сброс/установку ножки осуществлял с помощью функции SPI_NSSInternalSoftwareConfig() (так написано в библиотеке SPL). Так вот ножка не изменяла своего значения! Более того, когда я перестал использовать эту функцию и стал напрямую менять бит через регистр порта BSRR, то ножка все равно постоянно была выставлена! Причины я не знаю. Возможно, что все дело в режиме программного управления NSS. Поэтому когда я стал использовать для SlaveSelect другой пин, то все заработало — ответы стали приходить.
P.S. Правда дальше все равно не заработало….Опять… 🙂
Поэтому снова обращение за советом к уважаемому автору (когда он разгребётся с работой) 🙂
Ситуация такая: на команду SEND_IF_COND приходит ответ 0x01 — значит флешка v2 — вроде бы логично — флешка куплена неделю назад и навряд ли она v1. Идем дальше: отсылаю ACMD41, т.е. APP_CMD (получаю ответ 0x01 — вроде тоже все норм) и APP_SEND_OP_COND — получаю ответ 0x05. Имеем illegal command error, значит флешка не воспринимает такую команду. Решил попробовать отослать просто CMD1(вдруг карта версии v1), т.е. SEND_OP_COND — получаю ответ 0x01. Т.е. карточка никак не хочет инициализироваться, т.к. ждем 0x00. Может ли быть еще другие варианты последовательности инициализации?
Дмитрий пишет 16.12.2015 в 14:51 #
Решил проблему 🙂 Долго гуглил, находил различные решения (причем некоторые были противоположны друг другу :О ) но ничего не помогало. Увидел вот эту ссылку http://stackoverflow.com/questions/2365897/initializing-sd-card-in-spi-issues — решил что это не поможет и стал дальше искать, а зря…. Так как позже, отчаявшись, решил пробовать все решения и добавил несколько команд spi_read(); в начале функции SD_sendCommand() и карточка наконец инициализировалась 🙂
P.S. В той же ссылке есть другой совет — «send ACMD41 with the bit set for the voltage you’re supplying the card with», и этот человек утверждает, что ему это помогло, хотя в Physical Layer Simplified Specification Version 4.10 говорит про аргумент ACMD41 так:
Argument [31]Reserved bit [30]HCS [29:0]Reserved bits
Command Description — Sends host capacity support information and activates the card’s initialization process. Reserved bits shall be set to ‘0’
что явно противоречит выше сказанному. Так что не всем советам стоит верить. Возможно, что и моим тоже 🙂
Дмитрий пишет 23.12.2015 в 16:31 #
И снова здравствуйте! 🙂 В ходе использования карточкой возник вопрос: а как отследить что мы пишем в неверный сектор? Я имею ввиду, например, на карте 1000000 секторов, а мы пытаемся записать в 1000001. Карта это спокойно воспринимает — присылает valid-ный R1-response на команду (0x00) и valid-ный Data-response после приема данных (0xE5, но это тоже самое что 0x05, ведь значимые только младшие 7 бит).
P.S. Причем при попытке считать из неверного сектора R1-response 0x40, т.е. Parameter Error.
Alex_EXE пишет 27.12.2015 в 01:14 #
stm32f103 контроллер? У них столкнулся с подобной проблемой, только в другом ключе и использовал не SPI. Решение проблемы нашел, в рамках одного из будущих материалов опишу его на сайте.
По остальным вопросам отправил Вам письмо.
Дмитрий пишет 28.12.2015 в 19:38 #
Alex_EXE, благодарю за письмо. Всеми ссылками, которые Вы указали, активно пользовался и до этого 🙂 Кроме первой 🙂 Но она тоже выглядит полезной и ее стоит добавить в закладки. Я так понимаю Вы давали ссылку в этой статье на нее, но только на нерабочую версию, поэтому решил добавить ее в комментарии: http://mycontroller.ru/old_site/category/vneshnie-ustroystva/karta-pamyati-sd/default.htm
Теперь по поводу чем дело кончилось:) К сожалению, ответа на него я не нашел 🙁 Нет, проблему-то я решил, правда другим способом, но мне кажется что это лишние действия и было бы лаконичнее и красивее, если бы карта выдавала Parameter Error на попытку записать в неверный сектор. Возможно, где-то в закоулках даташита, все-таки скрывается ответ и его нужно просто очень внимательно прочитать 🙂 А вот об этом речь пойдет дальше, в следующем комменте 🙂
Дмитрий пишет 28.12.2015 в 20:40 #
Так вот. Как я думал решить проблему. Чтобы не писать в несуществующий сектор нужно просто знать их количество и проверять не вышли ли мы за предел 🙂 Знаю, банально, но решать проблему как-то надо 🙂
Есть такой регистр CSD (The Card-Specific Data register) В нем определенные биты отвечают за размер карты C_SIZE, при чём : memory capacity = (C_SIZE+1) * 512KByte. Т.е. отсюда можно посчитать количество секторов. Читается он с помощью CMD9 (SEND_CSD). Нашел наверно с десяток ссылок (например https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Attachments/18065/stm32_eval_spi_sd.c) в которых был написан один и тот же(по смыслу, а не скопипащенный 🙂 ) алгоритм чтения этого регистра. Суть сводилась к следующему:
Reading the contents of the CSD register in SPI mode is a simple read-block transaction (при чем в даташите есть точно такая же строка, но абзац на этом не заканчивается, но видимо дальше никто не читает 🙂 ). В итоге, во все ссылках такая последовательность действий:
CS в ноль -> шлем команду CMD9 с пустым аргументом -> ждём R1(0x00) -> ждём Data Token(0xFE) -> читаем 16 байт регистра -> читаем 2 байта CRC -> CS в единицу. Всё, данные получили, осталось только их распарсить.
ОК, пишу код, запускаю. На команду отвечает R1(0x00), всё норм. Вместо Data Token(0xFE) приходит 0x7F, а дальше идут 0xFF. Приехали. Начинаю гуглить, искать что означает 0x7F и кто с этим сталкивался. Вообщем потратил кучу времени и всё в пустую. Потом смотрю на свой код команды чтения сектора и стоп! — в CMD17 сначала шлем команду, а потом CS в ноль, а тут наоборот почему-то, хотя везде сказано что что CMD9 та же самая CMD17. Думаю дай-ка попробую так. Ииии…нет 🙁 всё равно не получаем 0xFE. НО, если раньше дальше шли 0xFF, то теперь какие-то непонятные байты. Странно, непонятно…И тут у меня появилась мысль и полез я в даташит. И что же я там увидел, в следующей части абзаца, после строки про simple read-block transaction. А вот что:
The card will respond with a standard response token followed by a data block of 16 bytes suffixed with a 16-bit CRC.
Т.е. в даташите для команды CMD9 ни про какой Data Token не сказано! Т.е. сразу после R1(0x00) идут байты регистра! Вот что значат эти непонятные байты. Проверил — действительно, 18 байт (16 + CRC), а потом уже пошли 0xFF. Распарсил байты и проверил провел по даташиту все сходится, это он — CSD. И размер карты тоже сошелся. Ну дальше дело техники посчитать количество секторов.
Так что вот, мой так сказать опыт по этому вопросу, может кому пригодится, чтобы не трать (как мне дурачку) такое количество времени на поиски ошибок на пустом месте 🙁
P.S. Мне вот что интересно. У людей, которые выкладывали приведенный выше алгоритм, действительно работает? И если да, то почему ? 🙂 Ведь это противоречит даташиту.
Алексей пишет 08.02.2016 в 17:45 #
Может кто подскажет как к данному проекту прикрутить FatFs. Бьюсь неделю и ничего не выходит. Среда разработки CooCox.
Андрей пишет 13.10.2016 в 08:32 #
Не знаю еще актуальна эта эта или нет, хотелось бы считывать изображение с SD карты и выводить его на дисплей. Загрузил пример от сюда http://cxem.net/mc/mc335.php (кстати в Cocox) но он почему-то нее «пошел» О чем и написал автору (без ответа). Там-же в примере есть и «прикрутка» FatFs. Посмотрите, может вам удастся разобраться в проблеме.
И может напишите еще одну статью.
Alex_EXE пишет 22.10.2016 в 20:28 #
Сейчас нет времени разбираться, по той же причине снова временно прекратил написание статей; сейчас методички на работе пишу, они хорошо удовлетворяют желание что-либо писать.
По FatFs — ни раз уже упомнила 2 хороших сайта:
http://mycontroller.ru/old_site/category/vneshnie-ustroystva/karta-pamyati-sd/rabota-s-ffatfs/default.htm
http://microsin.net/programming/file-systems/index.html
источник библиотеки http://elm-chan.org/fsw/ff/00index_e.html
Сергей пишет 05.11.2017 в 20:20 #
Кто знает, эта библиотека подойдет чтобы подключить к discovery флешку от mxic 25l на 32Мб?