SPI Arduino – подключение устройств к ардуино. Что такое SPI-интерфейс Модули для работы по spi интерфейсу

Синхронный последовательный интерфейс SPI предназначен для ввода- вывода данных в интерфейсах "точка-точка" с одним ведущим (SPI-master) и одним ведомым (SPI-slave) устройством (рис. 1.24). Схема управления SPI- master формирует тактовые импульсы SCK, по которым одновременно производится передача сигналов на выходе MOSI и прием сигналов на входе MISO. Эти же тактовые импульсы SCK, поступая в SPI-slave, управляют приемом сигналов на его входе MOSI и формированием сигналов на его выходе MISO. Раздельные сигнальные цепи MOSI и MISO позволяют легко реализовать полнодуплексный режим обмена данными.

Форматы данных, параметры сигналов, временные характеристики и т.п. в интерфейсе не регламентируются, например, скорость обмена данными определяется только частотой тактовых импульсов SCK, формируемых SPI- master. Максимальное расстояние зависит от уровня искажения сигналов в линиях связи, предполагается, что надежный обмен данными возможен при расстояниях до нескольких метров.

По-существу, полноценным интерфейсом даже для физического уровня не является. Фактически, SPI реализует стандартную процедуру ввода-вывода данных в регистрах сдвига, никаких алгоритмов контроля работы, контроля передаваемых данных не предусмотрено. Все необходимые процедуры контроля должен выполнять SPI-master. Это, с одной стороны, требует применения дополнительных средств контроля, а с другой стороны, максимально упрощает средства реализации самого интерфейса SPI. SPI- slave – это стандартный регистр сдвига с требуемым числом разрядов данных.

Например, микроконтроллеры семейства AVR фирмы ATMEL поддерживают ввод-вывод данных в режиме и SPI-master, и SPI-slave. Стандартный цикл обмена предполагает одновременную передачу в обоих направлениях по одному байту данных (рис. 1.24). При передаче многобайтовых сообщений SPI-slave должен содержать регистр сдвига соответствующей разрядности, а SPI-master должен производить управление обменом требуемой последовательности байтов данных, обрабатывая каждый байт после очередного стандартного цикла работы интерфейса и обеспечивая запуск следующего стандартного цикла обмена.

применяется не только для обмена данными между микроконтроллерами, но и для сопряжения микроконтроллеров с внешними АЦП (ADC) и ЦАП (DAC), микросхемами памяти – SRAM, FRAM, SEERAM и многими другими устройствами. Благодаря последовательному формату данных и простой логической организации интерфейса SPI эти микросхемы производятся в компактных 8 – 16 выводных корпусах. В табл. 1.6 приведены примеры микросхем различного функционального назначения и разных производителей с интерфейсом SPI. Эти примеры показывают, что последовательный формат интерфейса позволяет существенно сократить требуемое число линий ввода-вывода.

Таблица 1.6

Тип микросхемы

Основные параметры

Тип корпуса

Производитель

24-Bit, Delta-Sigma, 15 Гц

24-Bit, Delta-Sigma, 41 кГц

16-Bit, SAR, 100 кГц

16-Bit, PulSAR, 500 кГц

12-Bit, U-out, 2.5 мкс

16-Bit, U-out, 10 мкс

14-Bit, I-out, 0.04 мкс

12-Bit, I-out, 0.6 мкс

16-Bit, U-out, 1 мкс

www.maxim- ic.com

Тип микросхемы

Основные параметры

Тип корпуса

Производитель

16 кБит, 1 трлн

4 кБит, неогр.

64 кБит, неогр.

256K, 32768×8, 0.1млн Cycles

8К, 1024×8, 0.1млн Cycles

16K, 8192×8, 0.1млн Cycles

128K, 16384×8, 0.1млн Cycles

256K, 32768×8, 0.1млн Cycles

Termosensor

13-bit, -40 to +150 C o (±0.5C o)

Одна из проблем, которую часто приходится решать в средствах автоматизации, связана с ограниченным числом линий ввода-вывода микроконтроллеров. Обычно количество передаваемых сигналов существенно превышает возможности параллельных портов, но алгоритмы обработки большинства передаваемых сигналов допускают дополнительные временные задержки, связанные с их передачей в последовательном формате. В этих случаях эффективно применение стандартных последовательно-параллельных регистров.

Например, интерфейс SPI может оказаться полезным для считывания информации о состоянии большого числа двухпозиционных датчиков или для ввода многобитовых данных, поступающих в параллельном формате. Для этих целей удобно использовать отдельные регистры с параллельной записью и последовательным считыванием (8-Bit Parallel-In/Serial-Out Shift Register), например CD74HCT166 (рис. 1.25).

Схема подключения шестнадцати двухпозиционных датчиков (S1 – S16) через SPI-интерфейс микроконтроллера показана на рис. 1.26. Следует отметить, что перед стартом работы SPI-интерфейса необходимо сформировать сигнал записи информации в регистры с параллельных входов D0-D7. Для 38 этого можно использовать один из выходов микроконтроллера, в данном примере PC0.

Рис. 1.25. Функциональная схема регистра CD74HCT166

Рис. 1.26. Подключение двухпозиционных датчиков к SPI-интерфейсу

Рис. 1.27. Подключение шестиразрядного индикатора к SPI-интерфейсу

Применяя регистры с последовательной записью и параллельной выдачей информации (8-Bit Serial-In, Parallel-Out Shift Register) – SN74HC595 , SPI-интерфейс можно использовать и для многобайтовой параллельной выдачи информации. В качестве примера на рис. 1.27 приведена схема подключения шестиразрядного семисегментного индикатора к микроконтроллеру. В отличие от предыдущей схемы, сигнал параллельного вывода (PB1) необходимо сформировать после окончания передачи данных интерфейсом SPI средствами, выходящими за рамки интерфейса. Например, алгоритм взаимодействия с интерфейсом должен предусматривать контроль количества переданных байтов данных, а после завершения передачи последнего байта необходимо дополнительно передать сигнал параллельного вывода.

Интерфейс SPI — это один из самых популярных на сегодняшний день последовательных интерфейсов. Он был придуман фирмой Motorola и очень быстро завоевал популярность благодаря своей исключительной простоте и высокой скорости. При этом, SPI, наверное, нельзя назвать в полной мере интерфейсом, скорее это просто принцип связи, поскольку всё, что подразумевается под SPI, — это логика передачи данных между двумя устройствами («Ведущий»-«Ведомый»), физике же уделяется гораздо меньшее внимание , она реализуется, можно сказать, «по обстоятельствам», а никакого протокола нижнего уровня вообще нет, тут каждый производитель придумывает что-то своё.

Ну что ж, — с главного и начнём. Итак, в чём же тут логика? Логика в том, что данные передаются последовательно, побитно, при этом считывание и установка данных разделены во времени с помощью специального синхросигнала на специальной шине. Эта шина называется шиной тактирования (или шиной синхронизации), а суть разделения заключается в том, что считывание и установка данных происходят по противоположным фронтам генерируемых на шине синхроимпульсов. Такое, чётко разделённое во времени, чередование установок и считываний даёт возможность использовать один и тот же регистр и для приёма, и для передачи данных. Ранее (когда память была маленькой и дорогой, операционки хранились на дискетах, а по полям бегали мамонты ) это было серьёзным преимуществом, более того, именно под это на самом деле изначально и затачивался SPI, однако сейчас никаких проблем с обьёмом памяти нет и большинство устройств спокойно могут позволить себе иметь отдельные входной и выходной регистры.

Устройство, управляющее шиной тактирования (то есть генерирующее на ней синхроимпульсы), является «Ведущим» или «Мастером». Собственно, «Master» управляет всем обменом данными, — он решает: когда начинать обмен, когда заканчивать, сколько бит передать и т.д. Второе устройство, участвующее в обмене, является «Ведомым» или «Slave». В SPI, в отличии от, например, того же I2C, «Slave» совсем бесправен, он вообще никак не может влиять на шину тактирования и никак не может сообщить мастеру, что не успевает или, наоборот, что уже готов к обмену. То есть «Мастер» сам должен знать: когда, что и на какой скорости спросить у «Слэйва», чтобы тот смог ему ответить.

Всего, для полнодуплексного обмена (в обе стороны одновременно), в интерфейсе SPI используются 4 линии (смотрим рисунок): SCLK, MOSI, MISO и SS.

  1. SCLK — шина тактирования (на этой линии мастер генерирует синхроимпульсы)
  2. MOSI (M aster O ut, S lave I n) — выход ведущего, вход ведомого (по этой линии мастер передаёт данные слэйву)
  3. MISO (M aster I n, S lave O ut) — вход ведущего, выход ведомого (по этой линии мастер принимает данные от слэйва)
  4. SS (S lave S elect) — выбор ведомого (с помощью этой линии мастер управляет сеансами обмена)

«1» и «0» кодируются уровнем напряжения на шинах данных (MOSI, MISO) в обычной положительной логике, то есть высокий уровень напряжения на шине соответствует «единице», а низкий уровень соответствует «нулю». При этом, то, каким образом организуется установка на шинах этих уровней, — нигде не оговаривается, то есть выходы передатчиков могут быть как «push-pull», так и «с открытым коллектором». Высокий уровень обычно соответствует напряжению питания микросхемы (то есть если мы имеем дело с пятивольтовыми микрухами, то высокий уровень — это напряжение, близкое к пяти вольтам, если речь идёт о микрухах, питающихся от 3,3В, то высокий уровень — это напряжение, близкое к 3,3В).

Сигнал SS отмечает начало и конец сеанса обмена. Этот сигнал обычно инверсный, то есть во время сеанса обмена данными мастер должен устанавливать на линии SS низкий уровень, а при отсутствии обмена — высокий. Наличие сигнала SS позволяет мастеру организовать подключение к нескольким слэйвам, используя один и тот же синхросигнал и одни и те же шины данных, без каких-либо дополнительных протоколов (вариант такого подключения показан на рисунке слева). Правда тут есть один минус: в этом случае мастеру придётся к каждому слэйву подключаться по отдельной линии SS (чтобы управлять сеансами обмена с каждым слэйвом независимо друг от друга), что увеличивает общее количество используемых проводов.

Названия линий, в общем-то, не являются каким-то стандартом и могут отличаться в зависимости от производителя (например, вместо MOSI, MISO и SCLK линии могут называться DI, DO и SC, или SI, SO и CLK, линия SS может называться CS или RESET).

Более того, линий не обязательно должно быть четыре, — иногда их может быть только три, например, если данные передаются только в одном направлении или вместо двух однонаправленных шин данных используется одна двунаправленная. Очевидно, что в последнем случае возможен только полудуплексный обмен, то есть в один момент времени можно только передавать или только принимать данные (а передавать и принимать одновременно — нельзя).
То есть, ни по названию линий, ни по уровням напряжения на них, ни даже по их количеству, однозначно идентифицировать SPI нельзя, зато это отлично можно сделать по самому методу передачи данных, по тому как происходит их установка на шину и считывание.

Как я уже упоминал, — данные передаются побитно, а установка и чтение данных происходит по противоположным фронтам сигнала тактирования. Момент чтения данных в англоязычной литературе называется latch (фиксация, защёлкивание), а момент установки данных на шину — shift (сдвиг). Сдвигом момент установки называется в силу особенностей большинства последовательных интерфейсов. Обычно никто не передаёт данные по одному биту, как правило, их посылают пачками по 8 и более бит (размер пачки чаще всего всё же кратен восьми). В связи с этим, на выходе передатчика делают сдвиговый регистр, куда загружают сразу всю пачку передаваемых бит, при этом значение младшего или старшего бита этого сдвигового регистра устанавливается на шине данных (смотря как передаём — младшим или старшим битом вперёд), а для установки на шине следующего передаваемого бита — достаточно «сдвинуть» этот регистр. Так устроены передатчики и в SPI, и в I2C, и в привычном RS232, и много где ещё (так просто аппаратно удобнее). Ну, ладно, — вернёмся к нашему SPI.

Логический уровень сигнала на шине тактирования в неактивном состоянии (когда нет передачи данных) называют полярностью и обозначают CPOL (то есть, если при отсутствии передачи на шине SCLK низкий уровень, то CPOL=0, а если в это время на шине SCLK высокий уровень, то CPOL=1). Порядок чередования считываний и сдвигов называют фазой и обозначают CPHA (если по первому фронту на SCLK происходит считывание, то CPHA=0, а если по первому фронту на SCLK происходит сдвиг, то CPHA=1).

В зависимости от сочетания значений CPOL и CPHA различают 4 режима работы интерфейса SPI, которые так и обозначают Mode0 , Mode1 , Mode2 и Mode3 . Ниже приведена картинка, иллюстрирующая как происходит установка и чтение данных, в зависимости от выбранного режима.

Хотелось бы подчеркнуть, что SS — это именно линия управления сеансом обмена, а не просто линия выбора слэйва. Разница тут в том, что если считать SS просто линией выбора слэйва, то при подключении мастера к одному единственному слэйву возникает соблазн этой линией не управлять, а жёстко закоротить её на общий провод (типа чтоб слэйв всегда был выбран). Однако, логика слэйва обычно такова, что начало сеанса сопровождается различными подготовительными процедурами, такими как загрузка данных в выходной сдвиговый регистр и сброс счётчика импульсов, а выполнять какие-то действия (в соответствии с принятыми по SPI командами от мастера) слэйв начинает только после завершения сеанса обмена. Кроме того, вам ведь вполне может понадобиться несколько сеансов общения (например, если в первом сеансе вы посылаете команды, а в следующем хотите получить отчёт о результате их выполнения). Думаю понятно, что если жёстко притянуть линию SS к общему проводу, то ни о каком распознавании начала и конца сеанса обмена (начало распознаётся по спаду на линии SS, а конец — по подъёму) не может быть и речи, соответственно весь обмен данными будет нарушен. Так что важность сигнала SS не стоит недооценивать.

Ну и напоследок скажу, что наиболее популярными являются режимы Mode0 и Mode3.

Более подробно о том, как происходит обмен, что должен уметь SPI-мастер и как это программно реализовать на микроконтроллере (на примере контроллеров PIC и AVR) можно почитать в статье

SPI - Serial Peripheral Interface - последовательный

периферийный интерфейс

SPI - последовательный синхронный стандарт передачи данных между микросхемами в режиме полного дуплекса.

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

Интерфейс SPI, наряду с I2C, относится к самым широкоиспользуемым интерфейсам для соединения микросхем. Его наименование является аббревиатурой от “Serial Peripheral Interface” (англ. , SPI bus -

шина SPI), что отражает его предназначение - шина для подключения внешних устройств. Шина SPI организована по принципу "ведущийподчиненный". В качестве ведущего шины обычно выступает микроконтроллер, но им также может быть программируемая логика, DSPконтроллер или специализированная ИС. Подключенные к ведущему шины внешние устройства образуют подчиненных шины. В их роли выступают различного рода микросхемы, в т.ч. запоминающие устройства (EEPROM, Flash-память, SRAM), часы реального времени (RTC), АЦП/ЦАП, цифровые потенциометры, специализированные контроллеры и др.

Главным составным блоком интерфейса SPI является обычный сдвиговый регистр, сигналы синхронизации и ввода/вывода битового потока которого и образуют интерфейсные сигналы. Таким образом, протокол SPI правильнее назвать не протоколом передачи данных, а протоколом обмена данными между двумя сдвиговыми регистрами, каждый из которых одновременно выполняет и функцию приемника, и функцию передатчика.

1. Электрическое подключение

В отличие от стандартного последовательного порта (англ. standard serial port ), SPI является синхронным интерфейсом, в котором любая передача синхронизирована с общим тактовым сигналом, генерируемым ведущим устройством (процессором). Принимающая периферия (ведомая) синхронизирует получение битовой последовательности с тактовым сигналом. К одному последовательному периферийному интерфейсу ведущего устройства-микросхемы может присоединяться несколько микросхем. Ведущее устройство выбирает ведомое для передачи, активируя сигнал «выбор кристалла» (англ.chip select ) на ведомой микросхеме. Периферия, не выбранная процессором, не принимает участие

в передаче по SPI.

В SPI используются четыре цифровых сигнала:

MOSI (англ. Master Out Slave In )- выход ведущего устройства (альтернативное обозначение DO, SDO, DOUT) , вход ведомого устройства последовательного приема данных (альтернативное обозначение DI, SDI, DIN). Служит для передачи данных от ведущего устройства ведомому.

MISO (англ. Master In Slave Out ) - вход ведущего устройства последовательного приема данных (альтернативное обозначение DI, SDI, DIN), выход ведомого устройства последовательной передачи данных (альтернативное обозначение DO, SDO, DOUT). Служит для передачи данных от ведомого устройства ведущему.

SCLK (англ. Serial Clock ) - последовательный тактовый сигнал (альтернативное обозначение DCLOCK, CLK, SCK). Служит для передачи тактового сигнала для ведомых устройств.

CS или SS - выбор микросхемы, выбор ведомого устройства

(англ. Chip Select, Slave Select).

Существует три типа подключения к шине SPI, в каждом из которых участвуют четыре сигнала. Самое простое подключение, в котором участвуют только две микросхемы, показано на рисунке 1.

Рис. 1. Простейшее подключение к шине SPI

Здесь, ведущий шины передает данные по линии MOSI синхронно со сгенерированным им же сигналом SCLK, а подчиненный захватывает переданные биты данных по определенным фронтам принятого сигнала синхронизации. Одновременно с этим подчиненный отправляет свою посылку данных. Представленную схему можно упростить исключением линии MISO, если используемая подчиненная ИС не предусматривает ответную передачу данных или в ней нет потребности. Одностороннюю передачу данных можно встретить у таких микросхем как ЦАП, цифровые потенциометры, программируемые усилители и драйверы. Таким образом, рассматриваемый вариант подключения подчиненной ИС требует 3 или 4 линии связи. Чтобы подчиненная ИС принимала и передавала данные, помимо наличия сигнала синхронизации, необходимо также, чтобы линия SS была переведена в низкое состояние. В противном случае, подчиненная ИС будет неактивна. Когда используется только одна внешняя ИС, может возникнуть соблазн исключения и линии SS за счет жесткой установки низкого уровня на входе выбора подчиненной микросхемы. Такое решение крайне нежелательно и может привести к сбоям или вообще невозможности передачи данных, т.к. вход выбора микросхемы служит для перевода ИС в её исходное состояние и иногда инициирует вывод первого бита данных.

При необходимости подключения к шине SPI нескольких микросхем используется либо независимое (параллельное) подключение (рис. 2), либо каскадное (последовательное) (рис. 3).

Рис. 2. Независимое подключение к шине SPI

Рис. 3. Каскадное подключение к шине SPI

Независимое подключение более распространенное, т.к. достигается при использовании любых SPI-совместимых микросхем. Здесь, все сигналы, кроме выбора микросхем, соединены параллельно, а ведущий шины, переводом того или иного сигнала SS в низкое состояние, задает, с какой подчиненной ИС он будет обмениваться данными. Главным недостатком такого подключения является необходимость в дополнительных линиях для адресации подчиненных микросхем (общее число линий связи равно 3+n, где n-количество подчиненных микросхем). Каскадное включение избавлено от этого недостатка, т.к. здесь из

нескольких микросхем образуется один большой сдвиговый регистр. Для этого выход передачи данных одной ИС соединяется со входом приема данных другой, как показано на рисунке 3. Входы выбора микросхем здесь соединены параллельно и, таким образом, общее число линий связи сохранено равным 4. Однако использование каскадного подключения возможно только в том случае, если его поддержка указана в документации на используемые микросхемы. Чтобы выяснить это, важно знать, что такое подключение по-английски называется "daisy-chaining".

2. Протокол передачи

Протокол передачи по интерфейсу SPI предельно прост и, по сути, идентичен логике работы сдвигового регистра, которая заключается в выполнении операции сдвига и, соответственно, побитного ввода и вывода данных по определенным фронтам сигнала синхронизации. Установка данных при передаче и выборка при приеме всегда выполняются по противоположным фронтам синхронизации. Это необходимо для гарантирования выборки данных после надежного их установления. Если к этому учесть, что в качестве первого фронта в цикле передачи может выступать нарастающий или падающий фронт, то всего возможно четыре варианта логики работы интерфейса SPI. Эти варианты получили название режимов SPI и описываются двумя параметрами:

CPOL - исходный уровень сигнала синхронизации (если CPOL=0, то линия синхронизации до начала цикла передачи и после его окончания имеет низкий уровень (т.е. первый фронт нарастающий, а последний - падающий), иначе, если CPOL=1, - высокий (т.е. первый фронт падающий, а последний - нарастающий));

CPHA - фаза синхронизации; от этого параметра зависит, в какой последовательности выполняется установка и выборка данных (если CPHA=0, то по переднему фронту в цикле синхронизации будет выполняться выборка данных, а затем, по заднему фронту, - установка

данных; если же CPHA=1, то установка данных будет выполняться по переднему фронту в цикле синхронизации, а выборка - по заднему).

Ведущая и подчиненная микросхемы, работающие в различных режимах SPI, являются несовместимыми, поэтому, перед выбором подчиненных микросхем важно уточнить, какие режимы поддерживаются ведущим шины. Аппаратные модули SPI, интегрированные в микроконтроллеры, в большинстве случаев поддерживают возможность выбора любого режима SPI и, поэтому, к ним возможно подключение любых подчиненных SPI-микросхем (относится только к независимому варианту подключения). Кроме того, протокол SPI в любом из режимов легко реализуется программно.

Табл. 1. Режимы SPI

Временная

диаграмма

синхрониза

3. Cравнение с шиной I2 C

Как уже упоминалось, для стыковки микросхем не меньшей популярностью пользуется 2-проводная последовательная шина I2 C. Ниже можно ознакомиться с преимуществами, которая дает та или иная последовательная шина.

Преимущества шины SPI

Преимущества шины I2C

Предельная простота протокола

передачи на физическом уровне

обуславливает высокую надежность и

быстродействие передачи. Предельное

быстродействие шины SPI измеряется

Шина I2 C остается двухпроводной,

десятками мегагерц и, поэтому, она

независимо от количества

идеальна для потоковой передачи

подключенной к ней микросхем.

больших объемов данных и широко

используется в высокоскоростных

ЦАП/АЦП, драйверах светодиодных

дисплеев и микросхемах памяти

Все линии шины SPI являются

однонаправленными, что существенно

Возможность мультимастерной

упрощает решение задачи

работы, когда к шине подключено

преобразования уровней и

несколько ведущих микросхем.

гальванической изоляции микросхем

Протокол I2C является более

стандартизованным, поэтому,

Простота программной реализации

пользователь I2C-микросхем более

протокола SPI.

защищен от проблем

несовместимости выбранных

компонентов.

4. Производные и совместимые протоколы

MICROWIRE.

Протокол MICROWIRE компании National Semiconductor полностью идентичен протоколу SPI в режиме 0 (CPOL = 0, CPHA = 0).

3-проводной интерфейс компании Maxim

Отличие этого интерфейса состоит в том, что вместо полнодуплексной передачи по двум однонаправленным линиям здесь выполняется полудуплексная передача по одной двунаправленной линии DQ.

QSPI

Более высокоуровневый протокол, чем SPI, позволяющий автоматизировать передачу данных без участия ЦПУ.

Кроме того, интерфейс SPI является основой для построения ряда специализированных интерфейсов, в т.ч. отладочный интерфейс JTAG и интерфейсы карт Flash-памяти, в т.ч. SD и MMC.

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

0. Вместо введения

Что это за статья?
Эта статья представляет собой компиляцию информации из различных источников, вольный перевод некоторых частей документации, а также мои собственные комментарии, дополнения и описания возникших проблем.

Для кого эта статья?
В первую очередь, для новичков, каковым являюсь и я. На форумах по embedded Linux очень часто можно встретить вопрос: «А как на этой плате работать с SPI?». Именно на него я и попытаюсь дать ответ. В качестве примера, я приведу код написанный для работы с моим тестовым SPI устройством.

Структура статьи
По причине того, что информации получилось достаточно много, статья разбита на несколько подразделов:

  1. Что такое SPI?
  2. Обзор SPI подсистемы в Linux
  3. Разработка userspace протокольного SPI драйвера с использованием spidev
  4. Разработка протокольного SPI драйвера уровня ядра
  5. Документация
Первые два пункта войдут в первую часть статьи, оставшиеся во вторую.

Первый подраздел описывает работу шины SPI, данная часть статьи конкретно к Linux никак не привязана, поэтому её можно читать тем, кому Linux не интересен, а нужно лишь получить информацию об этом интерфейсе.

Второй подраздел описывает структуры и механизмы лежащие в основе работы с SPI в Linux, его нужно прочесть для понимания того, о чём пойдёт речь в третьей и четвёртой частях.

Если вас не интересует мои переводы и дополнения, можете смело переходить сразу к пятой части, там можно найти информацию о том, где получить всю необходимую информацию по данному вопросу.

Ошибки
Я не волшебник, я только учусь. Если найдёте какие-либо ошибки или неточности, пожалуйста, сообщите мне.

1. Что такое SPI?

Аббревиатура SPI означает «Serial Peripheral Interface» или в русском варианте «последовательный периферийный интерфейс». Название говорит само за себя, данный интерфейс используется для работы с различными периферийными устройствами. Например, это могут быть различные ЦАП/АЦП, потенциометры, датчики, расширители портов ввода/вывода (GPIO), различная память и даже более сложная периферия, такая как звуковые кодеки и контроллеры Ethernet.

С технической точки зрения SPI - это синхронная четырёхпроводная шина. Она представляет собой соединение двух синхронных сдвиговых регистров, которые является центральным элементом любого SPI устройства. Для соединения используется конфигурацию ведущий/ведомый. Только ведущий может генерировать импульсы синхронизации. В схеме всегда только один ведущий (в отличие от той же шины I2C, где возможен вариант с более чем одним ведущим), количество ведомых может быть различно. В общем случае выход ведущего соединяется со входом ведомого, и наоборот, выход ведомого соединяется со входом ведущего. При подаче импульсов синхронизации на выход SCK, данные выталкиваются ведущим с выхода MOSI, и захватываются ведомым по входу MISO. Таким образом если подать количество импульсов синхронизации соответствующее разрядности сдвигового регистра, то данные в регистрах обменяются местами. Отсюда следует что SPI всегда работает в полнодуплексном режиме. А вот нужны ли нам данные, полученные от устройства при записи какого-либо параметра, это уже другой вопрос. Часто бывает что данные полученные от устройства при записи в него данных являются мусором, в таком случае их просто игнорируют, но мы их получим вне зависимости от нашего желания.

Контроллер SPI, как правило, реализуется периферийным блоком в MCU или eMPU. В большинстве чипов он может работать как в режиме ведущего, так и в режиме ведомого. Но на данный момент Linux поддерживает только режим ведущего (Master).

Существует несколько способов включения SPI устройств.

Простейший из них вы видите на рисунке выше (спасибо Wikipedia за рисунки под свободной лицензией GFDL). В данном случае к ведущему все ведомые подключаются параллельно, за исключением сигнала выбора ведомого (~CS). Для каждого ведомого необходим отдельный сигнал выбора ведомого (на рисунке они обозначены как SSx). Для сигналов выбора ведомого могут использоваться как специально предназначенные для этого выходы SPI-контроллера, так и порты ввода/вывода общего назначения (GPIO) микроконтроллера.

Два проводника используются для передачи данных, один для подачи тактовых импульсов и по одному сигналу выбора ведомого для каждого из ведомых.
Описание используемых сигналов:

  • MOSI - Master Output, Slave Input (выход ведущего, вход ведомого). Данный сигнал предназначен для последовательной передачи данных от ведущего к ведомому. Также может называться SDO, DO и т.п.
  • MISO - Master Input, Slave Output (вход ведущего, выход ведомого). Данный сигнал предназначен для последовательной передачи данных от ведомого к ведущему. Может называться SDI, DI и т.п.
  • SCK - Serial Clock (сигнал синхронизации). Используется для синхронизации при передаче данных. Также может иметь название SCLK, CLK и др.
  • ~CS - Chip Select (выбор микросхемы). С помощью данного сигнала происходит активация ведомого устройства. Обычно он является инверсным, то есть низкий уровень считается активным. Иногда его называют ~SS (Slave Select, рус. «выбор ведомого»).

Частным случаем независимого подключения является вариант с одним единственным ведомым. В таком случае может возникнуть желание подтянуть сигнал ~CS к земле, чтобы устройство всегда было в активном состоянии. Но делать это крайне не рекомендуется, так как ведомое устройство может использовать сигнал CS для инициализации или для других служебных целей.

Основное неудобство при независимом подключении ведомых в том, что для каждого из ведомых необходим отдельный сигнал ~CS. Каскадная схема подключения, в зарубежной литературе называемая «daisy-chain» (можно перевести как «гирлянда»), лишена такого недостатка.

Как видно из рисунка выше, здесь используется общий сигнал выбора ведомого для всех ведомых. Выход каждого из ведомых соединяется со входом следующего. Выход последнего ведомого соединяется со входом ведущего, таким образом образуется замкнутая цепь. При таком подключении можно считать что последовательно соединённые устройства образуют один большой сдвиговый регистр. Соответственно, данные можно записать во все устройства «за один присест», предварительно собрав нужный пакет, объединяющий данные для каждого из устройств в порядке соответствующем физическому порядку соединения. Но тут есть один тонкий момент. Во-первых, все микросхемы должны поддерживать такой тип подключения; во-вторых, ядро Linux не поддерживает такой тип подключения, так что если всё же захотите его использовать, то вам придётся модифицировать существующие драйвера, либо же написать собственные.

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

  • CPOL (Clock Polarity) - определяет начальный уровень (полярность) сигнала синхронизации.
    CPOL=0 показывает, что сигнал синхронизации начинается с низкого уровня, так что передний фронт является нарастающим, а задний - падающим.
    CPOL=1, сигнал синхронизации начинается с высокого уровня, таким образом передний фронт является падающим, а задний - нарастающим.
  • CPHA (Clock Phase) - фаза синхронизации, определяет по какому из фронтов синхронизирующего сигнала производить выборку данных.
    CPHA=0 показывает что необходимо производить выборку по переднему фронту, а
    CPHA=1 показывает что выборку данных необходимо производить по заднему фронту.
Эти два бита и образуют номер режима. CPOL является старшим битом, а CPHA - младшим. Иногда в документации к устройству явно не указывают номер режима, но его всегда можно легко определить по временным диаграммам. Также важно понимать, что выборка и установка данных всегда происходят по противоположенным фронтам синхронизирующего сигнала. Например, пусть наше устройство работает в режиме 0 (наиболее распространённый вариант), в таком случае ведомое устройство будет считывать бит данных со входа MOSI по переднему нарастающему фронту синхронизирующего сигнала, а ведущее устройство будет считывать данные от ведомого на входе MISO также по переднему нарастающему фронту. Для большей наглядности я приведу осциллограммы для всех четырёх режимов работы:

На этом рисунке показаны сигналы MOSI (синяя линия) и SCK (жёлтая линия). Во всех случаях передаётся число 0x64. Светлые вертикальные линии показывают момент выборки данных. Рассмотрим режим 2, для которого, как мы помним, CPOL=1, а CPHA=0. Таким образом мы видим что синхронизирующий сигнал изначально имеет высокий уровень, а выборка производится по переднему фронту (в данном случае спадающему). Так как осциллограф у меня имеет только два канала, сигналы ~CS и MISO не показаны. Но в данном случае они не так интересны, например, сигнал ~CS представляет собой просто «провал» на всём протяжении передачи данных.

2. Обзор SPI подсистемы в Linux

Драйверы SPI в Linux делятся на две части. Первая - это драйверы SPI контроллеров, которые работают непосредственно с железом конкретно взятого контроллера. Такие драйверы определяют как настроить контроллер, какие действия предпринять при переходе в режим пониженного энергопотребления (suspend) и выходе из него(resume), выбор следующей передачи (spi_transfer) из очереди передач в сообщении (spi_message, об очередях чуть ниже) и отправка его непосредственно в порт, также определяется как активировать/деактивировать конкретное устройство посредством CS (функции cs_activate/cs_deactivate). В этой статье я не буду описывать данный тип драйверов. Как правило, они уже реализованы для тех MCU/eMPU на которые существует порт Linux, и лезть в них руками надо только в том случае, если вам нужна какая-то специфичная функция, вроде Chip Select Decoding, для возможности активации нужного ведомого устройства посредством внешней логики. Иногда это бывает полезно, например, в случае недостатка GPIO.

Вторая часть - это протокольные драйверы, используемые для работы с различными ведомыми устройствами, которые подключены к шине SPI. Данные драйверы называют «протокольными», потому что они лишь отправляют и получают различные данные от ведомых устройств, при этом не работая напрямую с каким-либо оборудованием. Именно данный тип драйверов нам наиболее интересен, так как позволяет добавить поддержку интересующего ведомого устройства в систему, его то мы и рассмотрим.

Большинство протокольных драйверов представляет собой модули ядра. Например, если устройство представляет собой аудиокодек подключаемый по SPI, то драйвер будет также использовать функции предоставляемые ALSA, а программы (например, madplay) смогут работать с ним посредством символьного устройства /dev/audio, не имея ни малейшего понятия о том как он аппаратно устроен и к какой шине подключен.

Также ядро предоставляет протокольный драйвер общего назначения, называемый spidev, с интерфейсом в виде символьного устройства. Он позволяет совершать полудуплексные обращения к ведомому SPI-устройству посредством стандартных системных вызовов read() и write(), устанавливать режим работы, а также производить полнодуплексный обмен данными посредством ioctl() вызовов.

Таким образом протокольные драйверы для SPI устройств можно разделить на два типа:

  • userspace драйверы, работающие в пространстве пользователя и представляющие собой обычные программы на любом языке, работающие с SPI устройством посредством чтения/записи соответствующего символьного устройства spidev.
  • драйверы, работающие в пространстве ядра и предоставляющие интерфейс для userspace посредством файлов устройств в каталоге /dev, либо с помощью атрибутов в каталоге устройства в sysfs.
Все обращения к SPI устройствам Linux ставит в очередь. Протокольные драйверы SPI оперируют явно или не явно сообщениями представленными структурой struct spi_message, которая является мультисегментной SPI транзакцией.
struct spi_message { struct list_head transfers; struct spi_device *spi; unsigned is_dma_mapped:1; void (*complete)(void *context); void *context; unsigned actual_length; int status; struct list_head queue; void *state; };
transfers - связанный список передаваемых сегментов в транзакции (передач);
spi - указатель на spi устройство, в очереди которого стоит данное сообщение;
is_dma_maped - если данный флаг «истина», то предоставлены оба, dma и cpu виртуальные адреса для каждого буфера передачи;
complete - обратный вызов, вызываемый для извещения об окончании транзакции;
context - аргумент для обратного вызова complete();
actual_length - полное число байт, которые были переданы во всех успешных предачах;
status - 0 в случае успеха, либо отрицательное значение с errno в случае ошибки;

Теги: Добавить метки

SPI (Serial Peripheral Interface, последовательный периферийный интерфейс, шина SPI ) - Это интерфейс для передачи данных на короткое расстояние, разработанный Motorola. Данные передаются в режиме полного дуплекса (в обе стороны) используя архитектуру ведущий - ведомый (master-slave). SPI также иногда называют четырёхпроводным (four-wire) интерфейсом.

Рис.1 стандартное общение по SPI

В шине SPI используются 4 цифровых сигнала:
  • MOSI : (Master Out Slave In) выход ведущего, вход ведомого.
  • MISO : (Master In Slave Out) вход ведущего, выход ведомого.
  • SCLK : (Serial Clock) тактовый сигнал.
  • CS или SS : (Chip Select, Slave Select) выбор микросхемы, выбор ведомого.

Возможны другие имена:

  • MOSI : SIMO, SDO, DO, DOUT, SI, MTSR;
  • MISO : SOMI, SDI, DI, DIN, SO, MRST;
  • SCLK : SCK, CLK;
  • SS : nCS, CS, CSB, CSN, nSS, STE, SYNC.
Шина SPI может работать с 1 ведущим (master) и несколькими ведомыми (slave) устройствами. Если используется одно ведомое устройство, то его вход SS можно заземлить, но только если он не работает по срезу сигнала.

Если использовать несколько ведомых устройств, то нужно повесить подтягивающие резисторы на каждый из выводов SS и убедиться что выходы MISO каждого из устройств подключены через буфер с высокоимпедансным состоянием (практически вывод считается отключённым), это может быть реализовано внутри микросхемы, нужно изучать документацию на конкретное устройство.

Если внутри устройств не предусмотрен буфер, то линия MISO будет всегда в состоянии лог.0 или лог.1. (также она может сгореть). Чтобы проверить есть ли внутри нашего устройства буфер, можно прочитать документацию или подключить делитель напряжения, чтобы на линии MISO была половина напряжения питания, затем замерить настоящее напряжение. Если замеренное нами значение отличается (будет 0 В или напряжение питания), то буфера нет и его нужно поставить отдельной микросхемой.


Рис.3 Проверка присутствия внутреннего буфера

Передача данных


Ведущий и ведомый передают друг другу данные одновременно. Сперва нужно выбрать ведомое устройство выставив на его входе SS низкий логический уровень (может меняться в зависимости от производителя). Данные для передачи помещаются в сдвиговые регистры. Затем ведущий генерирует синхросигналы частотой около нескольких МГц, ведущий и ведомый начинают посылать друг другу информацию хранимую в сдвиговых регистрах бит за битом начиная со старшего разряда.

Рис.4 Передача данных по SPI
Всего используется 2 сдвиговых регистра, старший бит из одного устройства передаётся в младший бит другого устройства, после чего регистр сдвигает хранимую в нём информацию. Количество бит в 1 пакете данных зависит от конкретного устройства, некоторые производители добавляют возможность изменять длину пакета.

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

Для настройки интерфейса используются несколько регистров, Можно регулировать частоту, прерывания, порядок бит и многое другое, подробнее об этом можно узнать в документации от Motorola ee.nmt.edu , этот документ взят как стандарт для SPI . Но производители могут не использовать всех настроек описанных там, также биты могут быть расставлены в другой последовательности в отличии от описания Motorola. В любом случае нужно читать документацию на конкретное устройство.

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

В принципе, эти настройки можно понять из временной диаграммы:

  • CPOL = 0: сигнал синхронизации начинается с низкого уровня;
  • CPOL = 1: сигнал синхронизации начинается с высокого уровня;
  • CPHA = 0: данные записываются по переднему фронту сигнала синхронизации;
  • CPHA = 1: данные записываются по заднему фронту сигнала синхронизации.
Задний и передний фронты обозначают первое изменение синхросигнала, либо второе. Это не зависит от того в какое состояние переходит линия SCK , это может быть как спадающий так и нарастающий фронт.

В зависимости от состояния битов CPHA и CPOL , различают 4 режима работы SPI интерфейса (0, 1, 2 или 3). Но в зависимости от производителя они часто соответствуют разным состояниям битов, к примеру, у ARM и PIC32MX контроллеров ни 1 из режимов не совпадает.

Есть 2 популярных способа включения нескольких SPI, первый из них подключение "звезда" (daisy chain):

В этом случае ведущий выбирает, кому из ведомых устройств следует передать данные.

Может быть такое что ведомые устройства не совместимы друг с другом и им нужны разные настройки, к примеру различная длина пакета, в таком случае используют соединение типа "кольцо":

В данном случае все устройства включаются одновременно и данные передаются последовательно, для того чтобы передать информацию какому либо устройству, либо от него ведущему, необходимо пройти несколько циклов передачи.

Заключение


SPI интерфейс заслужил свою популярность благодаря простоте и дешевизне. Сейчас его можно встретить в огромном количестве устройств, С его помощью программируются МК, JTAG также реализован на основе SPI. он часто используется для общения с различными микросхемами: Flash память, EEPROM, LCD, SD карты, АЦП, ЦАП микросхемы и многое другое.

Хоть стандарт и описан Моторолой, нет чётких определений и границ для SPI , из-за чего можно встретить различные реализации этого интерфейса, может использоваться другое количество сигнальных линий, количество бит в пакете и другие способы настройки. Так что сперва нужно читать документацию на устройство с которым вы работаете.

Есть готовые реализации SPI "трансиверов" которые можно подключить к компьютеру, что может быть полезно для отладки различных проектов, также новые осциллографы и логические анализаторы могут расшифровывать SPI пакеты.

Преимущества

  • Полнодуплексная передача данных.
  • Более высокая пропускная способность по сравнению с I²C или SMBus.
  • Возможность произвольного выбора длины пакета.
  • более низкие требования к энергопотреблению по сравнению с I²C и SMBus;
  • возможно использование в системах с низко стабильной тактовой частотой;
  • ведомым устройствам не нужен уникальный адрес, в отличие от таких интерфейсов, как I²C, GPIB или SCSI.
  • Используется только четыре вывода, что гораздо меньше, чем для параллельных интерфейсов.
  • Однонаправленный характер сигналов позволяет при необходимости легко организовать гальваническую развязку между ведущим и ведомыми устройствами.
  • Максимальная тактовая частота ограничена только быстродействием устройств, участвующих в обмене данными.

Недостатки

  • Необходимо больше выводов, чем для интерфейса I²C.
  • Ведомое устройство не может управлять потоком данных.
  • Нет подтверждения приема данных со стороны ведомого устройства (ведущее устройство может передавать данные «в никуда»).
  • Нет определенного стандартом протокола обнаружения ошибок.
  • Отсутствие официального стандарта, что делает невозможным сертификацию устройств.
  • По дальности передачи данных интерфейс SPI уступает таким стандартам, как UART и CAN.
  • Наличие множества вариантов реализации интерфейса.
  • Отсутствие поддержки горячего подключения устройств.

Источники:
Документация от Motorola