Arduino + SD + FAT16
Добавлено: Вс май 28, 2017 4:39 pm
Коллеги, для одной из своих задумок пишу читалку файлов с SD карточки отформатированной в FAT16.
Так как полноценные библиотеки для чтения SD и FAT достаточно объемные, я реализовал лишь некоторые необходимые функции.
По SD картам
1. Инициализация SD по SPI
2. Минимальный обмен позволяющий читать одиночные сектора по 512 байт (пока только для старых карт)
По FAT16
1. Чтение необходимой информации для поиска файлов в корневой директории
2. Поиск файла в корневой директории по имени
3. Чтение найденного файла блоками по 512 байт
Заточено под Arduino Pro Mini.
Ограничения - только FAT16, файлы только 8.3, файлы размещаются только в корневом каталоге (512 штук максимум)
Размер кода вместе с достаточно объемным отладочным выводом - порядка 4.5 килобайт. После уборки мусора и оптимизации будет меньше.
В общем вопрос - выкладывать код?
Использовано:
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); и последовательно менять в сторону увеличения.
Так как полноценные библиотеки для чтения SD и FAT достаточно объемные, я реализовал лишь некоторые необходимые функции.
По SD картам
1. Инициализация SD по SPI
2. Минимальный обмен позволяющий читать одиночные сектора по 512 байт (пока только для старых карт)
По FAT16
1. Чтение необходимой информации для поиска файлов в корневой директории
2. Поиск файла в корневой директории по имени
3. Чтение найденного файла блоками по 512 байт
Заточено под Arduino Pro Mini.
Ограничения - только FAT16, файлы только 8.3, файлы размещаются только в корневом каталоге (512 штук максимум)
Размер кода вместе с достаточно объемным отладочным выводом - порядка 4.5 килобайт. После уборки мусора и оптимизации будет меньше.
В общем вопрос - выкладывать код?
Часть первая, подключение и чтение блоков.UPDATE:UPDATE:UPDATE:UPDATE:UPDATE:UPDATE:UPDATE:UPDATE:UPDATE:UPDATE:UPDATE
Использовано:
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); и последовательно менять в сторону увеличения.