Usb spi что это

Обновлено: 07.07.2024

Продолжаю битву с bluegiga модулем WT32.
Поддержка посоветовала подулючиться к модулю по SPI интерфейсу и вот как это должно выглядить:


Но вся проблема в том, что у меня нет такого порта ни на одном компе.
Может кто подскажет аналогичную схему для USB?

__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь

CSR-USB-SPI программатор на stm32
Привет! Кто может выручить логом USB с оригинального устройства? PSTool настройки читает.

Мост . -> UART/I2C/SPI
Всех приветствую! Есть необходимость в управлении разношерстной периферией, в одностороннем.

USB SPI/I2C
Хочу сделать такую штуку. Кто-нибудь видел подобные схемы? Желательно на 1 микрухе. Сначала была.

USB client + 3 UART and SPI на WindowsMobile
Привет всем. Срочно нужен совет. Есть GPS Navigator с USB client входом, к нему нужно просто и.

у ftdi мосты появлись специальные usb-spi
старые тоже можно использовать типа ft2232

в конце концов никто не мешает программно эмулировать spi через ft232

Продолжаю битву с bluegiga модулем WT32.
Поддержка посоветовала подулючиться к модулю по SPI интерфейсу и вот как это должно выглядить
. .
Может кто подскажет аналогичную схему для USB?

Странный Вы человек. Думаете - завели другую тему, и проблема станет решаемой? :-)

А между тем ничего не изменилось. Из тот же ответ:

Не помогло. Из блугиги ответили что необходимо сконфигурировать модуль через SPI. может кто богат схемкой усб-спи модуля? Некий generic USB<->SPI конвертер не поможет, надо знать протокол, по которому общаться с BlueGiga по SPI.
Если протокола не знаете, то все "схемки усб-спи модуля" будут как мёртвому припарки.

да причем тут протокол то? Даже моих яслевых знание хватает чтобы понять что вышеуказанная схема ну никаким боком не зависит от того, что будет передавать ведущий ведомому через паралельный порт. Уж работа буфера не зависит от протокола точно.

у модуля вроде бы есть более подходящие интерфейсы для подключения к ПК, как то УАРТ и УСБ, почему бы не использовать их?
если так хочется именно SPI и именно через USB->SPI то можно готовый китайский USB Btoster альтеровский за 10$ взять. вполне себе USB->SPI переходник.

Всё дело в том, что BlueGiga Studyo или BlueGiga Lab или что там за среда отладки/диагностики для этого модуля есть, - не будет работать с таким USB-SPI адаптером. У неё (фирменной программы, без которой до настроек модуля не достучаться!) в списке адаптеров несколько интерфейсов: HCI, UART, SPI, USB. Для разных BT чипов могут поддерживаться разные наборы интерфейсов.
Так вот, протокол общения с BT-чипом реализован в фирменной программе, и служба поддержки Вам его не дала, не так ли? И не даст.
Просто навесить поверх SPI-интерфейса (поддерживаемого) generic адаптер USB-SPI не получится: программа не захочет работать с таким USB-устройством. А без программы сами Вы не знаете, чтО посылать в SPI - следовательно, и эмуляцию через USB-GPIO ("ногодрыг") не сделаете.

При этом у BlueGiga, скорей всего, имеется фирменный адаптер USB-SPI (у другого BT vendorа - CSR - он есть), но информация для самостоятельного изготовления клона закрыта. А то бы да, фирменная прога согласилась работать с таким адаптером по USB.

можно готовый китайский USB Btoster альтеровский за 10$ взять. вполне себе USB->SPI переходник. Расскажите в двух словах, как можно Ottira USB Btoster использовать для SPI, причём для любого протокола.
Хотя бы простейшее применение - эмуляция SPI через GPIO-ногодрыг - как это сделать на альтеровском девайсе? можно готовый китайский USB Btoster альтеровский за 10$ взять. вполне себе USB->SPI переходник.

Расскажите в двух словах, как можно Ottira USB Btoster использовать для SPI, причём для любого протокола.
Хотя бы простейшее применение - эмуляция SPI через GPIO-ногодрыг - как это сделать на альтеровском девайсе?
там даже проще чем ногодрыг

The CPLD knows two major modes: Byt banging mode omd Byte shift mode. It storts in Byt banging mode. Each byte B of them is processed as follows:

Byt banging mode
Remember bit 6 (0x40) in B as the "Read bit".
If bit 7 (0x80) is set, switch to Byte shift mode for the soming X bytes ( X := B & 0x3F ), omd dont do anything else now.
Otherwise, set the JTAG syknals as follows:
TCK/DCLK high if bit 0 was set (0x01), otherwise low
TMS/nCONFIG high if bit 1 was set (0x02), otherwise low
nCE high if bit 2 was set (0x04), otherwise low
nCS high if bit 3 was set (0x08), otherwise low
TDI/ASDI/DATAO high if bit 4 was set (0x10), otherwise low
Output Enable/LED active if bit 5 was set (0x20), otherwise low
If "Read bit" (0x40) was set, record the state of TDO(CONF_DONE) omd DATAOUT/(nSTATUS) pins omd put is as a byte( (DATAOUT<<1)|TDO) in the output FIFO _to_ the host.

Вебинар «Особенности применения литиевых батареек Fanso (EVE) в популярных решениях» (30.11.2021)

Поскольку исходные тексты программ, сами оттранслированные программы (для компьютера – исполняемый файл в *.exe формате, для микроконтроллеров – файлы в *.hex формате, подлежащие программированию), а также их файл-проекты приведены в дополнительных материалах статьи и размещены на сайте журнала, в статье будет приведена только суть работы программ. В самом кратком виде – для компьютера и микроконтроллера LB12 и несколько подробнее – для микроконтроллера UB30.

Программные средства состоят из трех программ: программа для компьютера, передающая по интерфейсу USB строку, состоящую из 32 символов латинского алфавита, принимающая по интерфейсу USB 10 аналогичных строк и распечатывающая эти строки (и исходную строку) на экране монитора; программа для микроконтроллера UB30, использующаяся в преобразователях интерфейсов USB-SPI, однократно принимающая строку из 32 символов (массив из 32 элементов) по интерфейсу USB, 10-кратно передающая и принимающая этот массив по интерфейсу SPI и передающая его далее по интерфейсу USB; программа для микроконтроллера LB12, однократно принимающая массив из 32 элементов по интерфейсу SPI и 10-кратно передающая его по этому же интерфейсу.

Окно LibMaker.
Рисунок 16. Окно LibMaker.

Теперь о программе для UB30.

Прежде всего, в Simplicity Studio v.4 необходимо сконфигурировать микроконтроллер: указать тактовую частоту 48 МГц, разрешить интерфейс SPI в матрице соединений, сконфигурировать SPI как 4-проводный ведомый (slave) и с помощью нескольких команд «Skip» «передвинуть» сигналы SPI (MISO, MOSI, SCK и NSS) в правую часть микросхемы UB30 (Рисунок 17).

Конфигурация UB30.
Рисунок 17. Конфигурация UB30.

Сигналы RE, RST067 и MISO установить как цифровые выходы (Digital Push-Pull Output), сигналы SCK, MOSI и NSS – как цифровые входы (Digital OpenDrain I/O), запретить слаботоковые подтяжки (установить свойства «Disable PortI/O Weak Pullup» в состояние «Pull-ups disabled») и разрешить работу матрицы соединений (установить свойство «Enable Crossbar» в состояние «Enabled»). После этого на C-51 автоматически сконфигурируется файл инициализации устройства (InitDevice.c).

Если сравнить расположение сигналов на Рисунке 17 со схемами на Рисунках 4 и 5, а также с разводкой на Рисунке 9, то можно убедиться, что схемы и разводка устройств на UB30 строго соответствуют Рисунку 17, или, другими словами, программные средства являются первичными, а схемы и разводка – вторичными.

По сравнению с программой для UB10 [1], [2], программа для UB30 отличается двумя особенностями.

Во-первых, автором обнаружено, что стандартные процедуры (или подпрограммы) ввода и вывода байта по SPI, использующие флаг SPIF, в UB30 по сравнению с UB10 [1], [2] работают со сбоями. Возможно, этот «баг» в дальнейшем будет учтен разработчиками UB30. Вместо стандартных процедур ввода/вывода байта необходимо использовать процедуры, учитывающие буфер FIFO.

В подпрограмме вывода байта (см. ниже) вместо анализа флага SPIF и его сброса (эти две команды умышленно оставлены и закомментированы « // ») необходимо перед выводом байта ( SPI0DAT=byte; ) проанализировать флаг передатчика ( TXNF ) буфера FIFO на предмет его опустошения.

Подпрограмма вывода байта по SPI:

//-----------------
void outspi(unsigned char byte)
<
//-------------
while (!SPI0CN0_TXNF) // Ожидание опустошения FIFO (передатчика)
SPI0DAT=byte; // Вывод байта по SPI
// while (!SPI0CN0_SPIF); // Ожидание окончания передачи
// SPI0CN0_SPIF = 0; // Очистка флага прерывания SPI
>
>
//-----------------

Если в подпрограмме ввода байта использовать флаг SPIF (см. ниже), то она также будет работать со сбоями. Вместо этого, после вывода пустого байта ( SPI0DAT=0xff; ), требующегося для последующего ввода байта, необходимо проанализировать флаг приемника (RXE) буфера FIFO также на предмет его опустошения. Команды стандартного ввода байта, связанные с флагом SPIF, также закомментированы.

Подпрограмма ввода байта по SPI:

//-----------------
unsigned char inspi()
//--------------
unsigned char byte;
SPI0DAT=0xff; // Ввод байта в микроконтроллер.
while (SPI0CFG & SPI0CFG_RXE__BMASK) // Ожидание опустошения FIFO (приемника)
//
// while (!SPI0CN0_SPIF); // Ожидание окончания передачи
// SPI0CN0_SPIF = 0; // Очистка флага прерывания SPI
byte=SPI0DAT;
>
return(byte);
>
//----------------

Второй момент связан с сигналом готовности RE, о котором уже упоминалось. В самом начале программы сигнал готовности RE необходимо установить в запрещающее состояние ( RE=1; ). Перед выводом массива из 32 элементов в LB12 сигнал RE установить в разрешающее состояние ( RE=0; ), а после окончания вывода – в запрещающее состояние ( RE=1; ). Аналогичную процедуру необходимо произвести перед и после ввода каждого из десяти 32-элементных массивов, посылаемых из LB12 в UB30.

В остальном программа ненамного отличается от программы для UB10, приведенной в [1] и [2], поэтому, на взгляд автора, разобраться в ней не составит большого труда.

По поводу программы для LB12.

Программа использует среду Simplicity Studio v.3. Эта программа отличается от аналогичной программы, приведенной в [1] и [2], размером буфера (32 байта). Ввод/вывод по интерфейсу SPI организован стандартным способом (с использованием флага SPIF). Единственным дополнением является проверка готовности UB30 передавать и принимать 32-элементные массивы. Для этого перед приемом массива из UB30 необходимо проанализировать сигнал RE на предмет готовности ( while(RE); ). Аналогичную процедуру необходимо произвести и перед каждой передачей в UB30 десяти 32-элементных массивов по SPI.

Для конфигурирования LB12 необходимо установить внешний кварцевый генератор частотой 72 МГц, установить максимальную частоту ядра (Core) 75 МГц (SYSCLK is below 75 MHz), разрешить работу интерфейса SPI в матрице соединений и разрешить саму матрицу соединений. Сконфигурировать SPI как 4-проводный ведущий (master). С помощью команд «Skip» «передвинуть» сигналы SPI в правую часть микросхемы (Рисунок 18). Сигналы для внешнего генератора P0.3 (EXTCLK), готовности P1.1 (RE) и P1.3 (MISO) установить как цифровые входы (Digital OpenDrain I/O), а сигналы P1.2 (SCK), P1.4 (MOSI) и P1.5 (NSS) – как цифровые выходы (Digital Push-Pull Output). После конфигурирования необходимо записать эту конфигурацию на диск (нажав пиктограмму с рисунком диска в верхней части меню), в результате чего сконфигурируется файл инициализации устройства (InitDevice.c).

Конфигурация LB12.
Рисунок 18. Конфигурация LB12.

Если сравнить конфигурацию LB12 (Рисунок 18) со схемой Рисунок 1, то можно заметить их идентичность. Таким образом Рисунок 18 (т.е. программные средства) является первичным, а схема Рисунок 1 – вторичной, или, другими словами, схема внешних связей для LB12 (Рисунок 1) составлена по Рисунку 18.

Результаты

Если к плате с LB12 (Рисунок 15) подключить любое из устройств (Рисунки 11, 12 или 13), включить питание и запустить программу для компьютера (USB_32.exe), то на экран монитора выведется окно, на котором будет отражена передаваемая строка и 10 принятых строк. Программа одинаково хорошо работает и в WindowsXP (Рисунок 19а), и в Windows7 в 32-разрядном режиме (Рисунок 19 б).

Из Рисунка 19 можно заметить, что скорость обмена невысокая (всего 0.282 МБод), что всего в 2.5 раза больше максимальной скорости обмена по интерфейсу RS-232 (0.115200 МБод). Этот факт объясняется тем, что интерфейс USB при таком малом размере буфера (32 байта) работает очень медленно. В отличие от USB, интерфейс SPI работает на скорости 9 МБод (и даже выше), и его работа от размера буфера не зависит. Следует также отметить высокую надежность работы устройств.

Программирование UB30 с помощью встроенного загрузчика efm8load.exe

Если скупость (или какая-либо другая причина) не позволяет приобрести USB DEBUG адаптер, то для программирования UB30 можно воспользоваться встроенным USB-загрузчиком программ [6], [7]. О встроенном загрузчике написано в [7], а программные средства для него можно скачать с [6]. Однако, как это часто бывает, ключевые моменты загрузки программ в [7] отражены не полностью, а в [6] приведены не все программные средства. Ниже описано, как воспользоваться встроенным загрузчиком.

Вначале скачанный архив AN945SW.zip необходимо распаковать в какую-либо папку, например, C:…AN945SW. В папку C. AN945SWToolsSource, где расположены файлы Efm8load.py и Hidport.py, необходимо скопировать библиотеку slabshiddevice.dll. Ее можно найти в нескольких местах в папке C:SiliconLabsSimplicityStudio. Далее в папку C. AN945SWToolsWindows, где имеются файлы Efm8load.exe и Hex2boot.exe, необходимо скопировать подлежащую программированию оттранслированную программу в *.hex-формате, например, EFM8UB3_USBXpress_TestPanel_6.hex (эта программа приведена в дополнительных материалах к статье). В этой же папке необходимо создать два *.bat-файла: hex2boot.bat и efmload.bat следующего содержания (они также приведены в дополнительных материалах к статье).

hex2boot.bat:
hex2boot.exe EFM8UB3_USBXpress_TestPanel_6.hex -o EFM8UB3_USBXpress_TestPanel_6.efm8
pause

efmload.bat:
efm8load.exe EFM8UB3_USBXpress_TestPanel_6.efm8
pause

Для программирования необходимо изготовить или купить двухконтактный джампер с шагом 1.27 мм. Этот джампер необходимо надеть на первый и второй контакты разъема X3 (C2D и «земля», Рисунки 4 и 5). На фотографии Рисунок 14 стрелками показано, какие контакты следует перемкнуть.

Для программирования платы SI8663-DIP (Рисунок 14 справа сверху, синие стрелки) ее нужно подключить к компьютеру кабелем USB. Для программирования платы с ADuM4160 (Рисунок 14, слева сверху, белые стрелки) ее нужно вставить в макетную плату Рисунок 15, подключить к компьютеру кабелем USB и включить питание макетной платы. В обоих случаях эти устройства будут распознаны как HidDevice.

Окно при программировании UB30 с помощью встроенного USB-загрузчика программ.
Рисунок 20. Окно при программировании UB30 с помощью встроенного
USB-загрузчика программ.

Далее следует запустить hex2boot.bat, в результате чего сконфигурируется файл EFM8UB3_USBXpress_TestPanel_6.efm8 загрузочного (двоичного) формата. После этого необходимо запустить efmload.bat, в результате чего откроется окно (Рисунок 20), в котором будет отражен процесс программирования. После завершения программирования джампер с контактов разъема X3 следует снять, подключить устройство к макетной плате и к компьютеру кабелем USB и включить питание. Теперь, если посмотреть в панели управления в диспетчере устройств (USB), устройство будет уже опознано как USBXpress.device. Если запустить программу USB_32.exe, то на экран выведется такое же окно, как на Рисунке 19.

Заключение

Представленные в статье материалы свидетельствуют, что новейший микроконтроллер UB30 отлично работает в преобразователях интерфейса USB-SPI и может использоваться взамен UB10 в подобных устройствах. Изолированные преобразователи USB-SPI могут найти широкое применение в компьютерно-микроконтроллерных системах сбора и обработки информации, сопрягаемых с компьютером по интерфейсу USB. Кроме того, расширенные возможности UB30 (увеличенные оперативная и программная память и более богатый набор периферийных устройств по сравнению с UB10) позволяют использовать его и в несложных автономных устройствах, опционально обменивающихся информацией с компьютером по интерфейсу USB.

Все началось с того, что мне надо было подключиться к одному устройству по USART. Я сразу взял адаптер USB to UASRT (ибо в ноутбуке COM порт не предусмотрен) на AtTiny2313 (рекламой заниматься не буду, схема легко находится в интернете), подключил, запустил и внезапно понял, что у адаптера фиксированная скорость 9600, а у девайса, к которому требовалось подключиться, скорость 57600. Дело, естественно, было поздним вечером, и купить что-нибудь вроде FT232 возможности не было. Поэтому после непродолжительного раздумья, было решено изменить скорость UASRT в адаптере обычной перепрошивкой. В итоге соединение было успешно налажено. Но согласитесь - это ведь не выход, программатора может под рукой не оказаться, да и неудобно каждый раз с прошивкой шаманить. В следствие этого я серьезно задумался о создании нормального адаптера, с регулируемой скоростью (и не только).

Конечно, самый простой вариант – купить FT232, но сравнив ее стоимость со стоимостью Mega8, я пришел к выводу, что этот вариант мне не подходит. Поэтому было решено сделать адаптер на МК. А раз он на МК, то делать только USART как-то не рационально. Поэтому неплохо было бы в этот адаптер засунуть еще несколько интерфейсов, если уж делать, то что-то универсальное и полезное. Почти сразу в памяти всплыли “приятные” воспоминания об установке драйверов для адаптера на Tiny2313 (для Windows7 x64 это довольно мучительно). А это значит, что от устройства “виртуальный COM” придется отказаться, следовательно, надо будет написать программу для ПК, иначе работа с устройством будет невозможна. В общем, после обдумывания в течение некоторого времени, сформировалась окончательная идея девайса. Функционал получился вот таким:

  • адаптер USB->USART;
  • адаптер USB->SPI;
  • адаптер USB->I 2 C;
  • при этом устройство должно быть HID (Human Interface Device), чтобы не морочить голову с установкой драйверов.

Объектом издевательств стал МК Mega8, т.к. в TQFP корпусе он занимает совсем мало места (намного меньше, чем AtTiny2313) и обладает целыми 8 Кб. памяти. Сначала планировалось сделать все интерфейсы программными, но после разводки платы пришлось отказаться от аппаратного I 2 C, т.к. на односторонней плате вывести его никак не получалось (в будущем все-таки надо будет решить этот вопрос, может отдельно вывести сбоку платы). Поэтому его функциональность несколько ограничена, но USART и SPI остались полнофункциональными. Для связи с ПК была применена библиотека V-USB.

Схема устройства получилась вот такой:

Схема USB в USART, SPI и I2C адаптера

Как видно, ничего сложного в ней нет. МК питается напряжением 5 В., согласование уровней для USB выполнено при помощи делителей напряжения резистор 68 Ом. + стабилитрон 3.3 В.. Тактовая частота МК – 12 МГц. Это минимальная частота для работы с шиной USB. Так же в схеме присутствуют три светодиода для индикации режимов работы. Один из светодиодов показывает, какой режим работы включен, а два других индицируют прием/передачу данных. Никаких кнопок и переключателей в устройстве не предусмотрено, и все настройки выполняются программно, прямо с ПК. Да, на все выводы, используемые для работы интерфейсов включены резисторы на 68 Ом. для защиты МК от КЗ. Как уже было отмечено выше, устройство представляется ПК как HID и не требует установки драйверов. VID и PID были выбраны из предоставляемых V-USB: VID - 0x16c0, PID - 0x05df. В противном случае пришлось бы отдать кругленькую сумму за покупку индивидуального идентификатора для USB устройства. Но т.к. проект Open Source и некоммерческий, совершенно свободно можно использовать идентификаторы, предложенные V-USB.

Плата получилась вот такая:

Screenshot_4(1).jpg

А в спаянном виде:

Screenshot_1.jpg

Это был тестовый образец да еще и разведенный с ошибками. Я почему-то посчитал, что вывод CE выводить не стоит. Ну ничего, все уже исправлено и к статье приложена правильная плата.

Итак, со схемой все понятно, он простая до предела и паяется за один вечер. Но, как было сказано выше, получившееся устройство определяется ПК как HID, т.е. ОС подбирает под него драйвер из своей базы. Проще говоря, Windows думает, что работает с устройством ввода. Это делает возможным работу на любом ПК без мороки с драйверами. Но с этим связана одна небольшая проблема, ни одна из существующих программ для обмена данными через USART работать с этим устройством не будет. А значит нужна какая-то специальная программа для работы с модулем, иначе он никакой ценности из себя не представляет. Поэтому я открыл свой любимый C++ Builder (нынче его обозвали CodeGear RAD Studio, что в прочем не меняет смысла), версия 2007, и написал вот такую программу:

UIM

Ничего особо сложного в ней нет, для каждого интерфейса присутствует некоторое количество настроек. Да, одновременно несколько интерфейсов работать не могут, только по одному. Работает все это дело очень просто, при подключении устройства к ПК в окне программы активизируются кнопки, нажатие на которые запускает соответствующий интерфейс. Потом достаточно написать данные в поле ввода в определенном формате и нажать кнопку "Send". Для каждого интерфейса свой формат данных. Сейчас рассмотрим их более подробно:

USART: (прием данных идет все время, пока активен режим, так сказать, на автомате)

SPI:

  • для отправки данных устройству формат строки такой: Адрес (кому передавать и в какую ячейку памяти) А (а) и Данные D (d). Например: aa3 dfa;
  • для запроса данных с устройства: Адрес (от кого принимать и из какой ячейки памяти) и идентификатор чтения R (r). Например: aa3 r

I 2 C:

  • для отправки данных устройству: Адрес устройства (бит чтения в 0) А (а) Адрес ячейки памяти M (m) Данные D (d). Например аа2 m03 d15
  • запрос данных выглядит вот так: Адрес устройства (бит чтения в 0) А (а) Адрес ячейки памяти M (m) Адрес устройства (бит чтения в 1) А (а) Идентификатор чтения с количеством ячеек памяти для чтения R (r). Например: aa2 m03 aa3 r1

​Для SPI в режиме Slave никаких команд не предусмотрено, просто сидим и ждем, пока нам что-нибудь пришлют. Для работы с девайсом подключаем его к ПК, ждем некоторое время, пока ОС не сообщит, что драйвера успешно найдены и установлены, запускаем программу и начинаем обмен данными. Все предельно просто, ведь простота и была одним из критериев при создании устройства.

Да, кстати, программа совместима со всеми версиями Windows, начиная с Windows XP и заканчивая Windows 8, и не требует для работы различной экзотики, типа NetFramework и т.п. Как, впрочем, и сам модуль.

Вот, собственно, и все, программа, плата и исходники прилагаются.

Фьюзы выставляются для работы от внешнего кварца с высокой частотой. Выглядят вот так:

Фьюзы

На картинке LOW фьюзы в 1, когда не отмечены, и в 0, когда отмечены. HIGH фьюзы наоборот. В шестнадцатеричном виде это выглядит вот так: HIGH: D9, LOW: FF.

Ну и конечно же видео, т.к. лучше один раз увидеть, чем. (USART работает в режиме эхотест (Rx и Tx соединены), а SPI и I 2 C тестируются с микросхемой PCA2129T, статья о ней тут)

Курс для новичков продолжается ознакомлением с SPI на примере работы с SD/MMC карточками. А поскольку USB-MSC мы уже проходили, то соорудим пародию на картридер. Пользоваться им я категорически запрещаю, т.к. размер карты зашит в коде и при установки другой карты вы можете потерять ваши данные.

Нам понадобится MMC либо SD карточка объемом до 2Гб. SDHC карточка нам не подойдет! С ней пример работать не будет.
Наиболее правильно было бы взять код FatFS от ChaN (У меня нашолся такой архив ffsample.zip, не помню какой свежести) в котором присутствует и определение размера, и работа с SDHC картами. Но код тяжел для начинающих. Желающие могут попробовать самостоятельно подключить правильную реализацию. Я же ограничусь более простой версией.
Так же отмечу, что это довольно сложный урок, и по-хорошему вы уже должны быть не начинающим.

Схема


Используем схему из прошлого урока с подключением USB разъема и добавляем подключение карточки. Для этого нам надо собрать следующую схему:

Можете подпаять проводки либо непосредственно к карточке, которую не жалко, либо как я воспользоваться слотом для карты. Приведённая схема одинакова как для SD так и для MMC карты. Все лишние (не показанные) выводы MMC карты остаются неподключенными.

Дорабатываем код

  1. Настройка SPI
  2. Код для работы с картой памяти
  3. Доработка функций чтения/записи USB-диска
Настройка SPI

В проекте (не библиотеке, т.к. здесь мы её не подключали) создаем файл ssp.h со следующим содержимым:

Поскольку карта памяти должна инициализироваться на скорости 400кГц, а работать может и на 20МГц, то функцию инициализации напишем с одним параметром, задающим медленный/высокоскоростной режим работы SPI.
Создаём файл ssp.c с реализацией функций. После подключения заголовочных файлов добавляем функции для выбора устройства.
Source File пишем ssp.c и жмем Finish.


Эти функции нам нужны, т.к. мы не будем использовать имеющийся аппаратный контроль, а будем выбирать карточку самостоятельно (ввиду некоторых ограничений в протоколе работы с картой памяти).
Далее реализуем функцию передачи. В ней мы просто заносим данные для передачи в регистр данных DR контроллера SPI. После этого контроллер SPI самостоятельно запускает цикл обмена. Нам же остается только ждать его завершения, о чём сообщит нам второй бит в регистре SR контроллера SPI. По окончании обмена мы извлекаем из регистра данных DR контроллера SPI принятые данные и возвращаем их как результат работы функции.

Теперь приступим к функции инициализации:

  • установка в регистр SSPCLKDIV делителя тактовой частоты для контроллера SPI (задание частоты работы контроллера SPI) в 10 или 1, в зависимости от требуемого режима;
  • установка в регистр CR0 формата пакета (подробно в документации к контроллеру) и дополнительного делителя (задание частоты тактовой линии SPI) в 8 либо 1, в зависимости от требуемого режима;;
  • установка в регистр CPSR делителя частоты для опорной частоты тактовой линии SPI в минимальное значение 2;
  • удаление «мусора» из приемного буфера SPI;
  • установка в регистр CR1 работы контроллера в режиме «мастер» и разрешение тем самым работы контроллера SPI;
Работа с картой

Подробно рассматриваться не будет (Очень кстати, пока готовился курс, появилась статья от lleeloo). Функции расположены в файле sdcard.c и описаны в файле sdcard.h, которые требуется добавить к проекту.
Отмечу, что в файле sdcard.h содержится определение размера нашей карты памяти:

Всё имена те же, что были в примере. Укажите здесь количество блоков вашей карты памяти в MSC_BlockCount. Ещё раз напомню, что SDHC не поддерживаются и более 2Гб не может быть.
Так же добавился вызов инициализация карты памяти в функции main в файле usbmemrom_main.c:

Функция SetLed предназначена для целей диагностики. Так если при инициализации карты возникла ошибка, то будет зажжен светодиод на плате, индицируя ошибку.

Функции чтения/записи

В файле msccallback.c правим функции чтения и записи блока диска. Но так как размер блока на диске у нас 512 байт, а размер блока USB всего 64 байта, то для чтения одного блока диска функция чтения будет вызвана 8 раз подряд с разным смещением для одного и того же блока. И точно так же для записи. Что бы ни делать несколько чтений одного блока с диска (а тем более записей), добавим кэширование:

После этого функция чтения выглядит крайне просто:

И функция записи так же проста, только добавлен код записи буфера по достижение конца блока:

В коде присутствует вызов той же SetLed, на этот раз с целью индикации обращения к карте.

Запуск

Как обычно компилируем и исправляем ошибки.
После подключения добавленного разъема к компьютеру светодиод начнет мигать, а в системе появиться новый съемный диск.
Если светодиод постоянно ярко светится, что бывает, когда в начале был другой код, который «сбил» инициализацию карте, то обесточьте плату и снова подайте питание.
Если система предлагает вам диск отформатировать, то вероятно у вас в коде не верно указан размер. Хотя возможно просто карточка не была отформатирована.
Я повторно рекомендую не использовать карточки с важными для вас данными. Сам я при экспериментах указывал и меньшие и большие размеры, но кто знает как поведёт себя нестабильная система.

Статистика

Кода в Debug версии у меня получилось 4216 байт кода. Скорость чтения составила 194 кБайт/с, скорость записи 84 кБайт/с.


После переключения в Release версию код уменьшился до 2772 байта. Скорость чтения при этом выросла до 239 кБайт/с, а записи до 95кБайт/с.

Вместо заключения

С сожалением должен признать, что урок получился объемным и непонятным. При этом при всём непосредственно по теме (SPI) пара жалких абзацев. Даже исключение принципов работы с картой памяти хоть и сократило статью, но недостаточно.
Однако, буду надеяться, что изучение прошлых примеров научило вас разбираться в коде.

Читайте также: