В одном из проектов потребовался код чтения данных с SD карт. Так как SD карточки успешно работают по SPI, реализованы пара функций для инициализации и чтения. В дальнейшем планирую дописать минимальную поддержку FAT16, но когда доберусь неизвестно. Почему сам, а не готовую библиотеку? А потому, что библиотека для работы с FAT слишком толстая и в Pro Mini не остается места ни на что другое.
Подключение карты и чтение блоков.
Использовано:
1. Arduino Pro mini - Atmega 328 5V 16MHz
2. Разъем для SD карты.
3. Карта Transcend 2GB (старая, это важно чуть ниже расскажу почему)
Подключение:
Выводы карточки в режме SPI
Соответственно соединяем выводы
Ардуино - карточка (у меня разъем)
5V - VCC (через понижалку в 3.3V)
GND - GND
11 - MOSI
12 - MISO
13 - SCK
9 - CS (можно поменять, смотреть в коде #define CS_PIN )
Качаем/Распаковываем скетч. Компилим, загружаем.
Основная функция SDRead. Читает по одному 512 байтному блоку за раз, в заранее объявленный буфер (512 байт длиной!).
Теперь про "старые"/"новые" карты. Дело в том, что на т.н. старых картах, до 2GB включительно, адресация блоков (по 512 байт) отличается от адресации на новых. На новых картах, блок адресуется просто по номеру. То есть 0 это нулевой блок, 1 первый и так далее. На старых, блоки адресуются по первому байту 512 байтного блока (i*0x200). Т.е. 0 блок - адрес 0, 1 блок - 0x200 (то есть адрес начала блока), 2 блок 0x400 и так далее.
Соответственно в SDRead нужно скармливать адреса в зависимости от типа карты.
Если в функции убрать комментарии, то при каждом чтении блока, в компорт будет выводиться содержимое считанного блока.
На указанной конфигурации, получена скорость чтения блоков (последовательно 2048 блоков, 4887400 микросекунд), что составляет примерно 1706 kbps.
В случае если сразу не заводится, имеет смысл поменять значение делителя SPI на самый маленький:
SPI.setClockDivider(SPI_CLOCK_DIV128); и последовательно менять в сторону увеличения.