Интерфейс SPI

 
SPI_logo
 

Кратко о SPI

 

Serial Peripheral Interface или SPI — последовательный периферийный интерфейс, служит для связи периферии и микроконтроллера. Например, в качестве периферии может быть: дисплей, различные датчики, FLASH память, SD карта (да, да, SD карта или «флешка» которую вы используете в телефонах и фотоаппаратах общается с внешним миром с помощью интерфейса SPI) и т.д.

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

 

О том что такое SPI читайте в статьях википедии

http://ru.wikipedia.org/wiki/Serial_Peripheral_Interface
http://en.wikipedia.org/wiki/SPI_bus

 

В SPI всегда есть один ведущий и один/несколько ведомых.

Передачу данных всегда инициализирует ведущий.

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

  • MOSI или SI — выход ведущего, вход ведомого (англ. MasterOutSlaveIn). Служит для передачи данных от ведущего устройства ведомому.
  • MISO или SO — вход ведущего, выход ведомого (англ. MasterInSlaveOut). Служит для передачи данных от ведомого устройства ведущему.
  • SCLK или SCK — последовательный тактовый сигнал (англ. SerialClock). Служит для передачи тактового сигнала для ведомых устройств.
  • CS или SS — выбор микросхемы, выбор ведомого (англ. Chip Select, Slave Select).

 

P.S. Для обеспечения односторонней связи с одним устройством, достаточно использовать SCLK, MOSI (в случае если ведомое устройство только принимает) или SCLK, MISO (в случае если ведомое устройство ничего не принимает, а только передает информацию). На входе CS ведомого устройства должна быть установлена единица, иначе ведомый не будет работать.

P.S. Если ведомое устройство и передает и принимает, то можно ограничиться тремя проводами – MISO, MOSI, SCLK, на вход CS ведомого устройства также необходимо установить 1-цу.

 

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

Для передачи данных к ведомому устройству, нужно в сдвигающий регистр MASTER-а (на изображение сдвигающий регистр мастера — «8 BIT SHIFT REGISTER») записать байт передаваемой информации. При этом автоматически на SCK начнет генерироваться синхросигнал. Это и есть аппаратная реализация.

 

SPI_principle

 

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

 

 

Различия в реализациях интерфейса SPI

 

Ведомые микросхемы могут по разному «интерпретировать» принятый сигнал по SPI, отличие может заключается в следующих моментах:

 

  • в размере передающих данных или размер пакета, обычно это 8 бит, но бывает и больше
  • в порядке следования бит, сначала старший бит или сначала младший бит
  • по какому уровню синхросигнала передаются данные (по логической единицы (HIGH) или логическому нулю (LOW))
  • по какому фронту импульса происходит синхронизация (по подъему или спуску), кратко это называют «фазой синхронизации»

 

Комбинация «уровня синхронизирующего сигнала» и «фазы синхронизации» определяется в спецификациях как режимы работы SPI. Их всего 4-е:

 

Режим Уровень сигнала (CPOL) Фаза (CPHA)
0 0 0
1 0 1
2 1 0
3 1 1

 

В столбце «Уровень сигнала» 1-ца, означает, что бит данных, принимаются ведомым устройством, когда по линии синхронизации передается ноль, другими словами — ведомое устройство ожидает и не принимает данные, когда на SCK установлена логическая 1-ца.

 

В столбце «Фаза» 1-ца, означает, что сигнал синхронизации определяется по спадающему фронту синхроимпульса, а логический 0-ль по нарастающему фронту синхроимпульса.

 

P.S. Причем если в столбце «Уровень сигнала» установлена 1-ца, то спадающий и нарастающий фронт если изобразить на диаграмме будет «вверх ногами».

 

На диаграммах, данные 4-е режима можно изобразить следующим образом:

 

SPI_mode

 

Более подробно о принципах работы SPI вы можете прочесть в статье

http://www.kit-e.ru/articles/interface/2009_03_53.php

 

 

Реализация SPI на микроконтроллерах ATmega серии AVR (ATmega328P) и «ранних» МК фирмы Motorola

 

В микроконтроллере ATmega328P (микроконтроллер фирмы Atmel серии AVR) можно управлять следующими параметрами SPI:

 

  • тип устройства (какую роль выполняет микроконтроллер, в качестве ведущего или ведомого)
  • порядок следования бит при передачи данных, сначала старший или младший бит
  • режим работы SPI (один из 4-ех указанных выше), с помощью комбинации 2-ух параметров — «полярность синхросигнала» и «фаза синхронизации».
  • частоту обмена данными по SPI

 

Для настройки и управлением SPI интерфейсом используют три регистра:

  • Регистр управления — SPCR
  • Регистр состояния — SPSR
  • Регистр данных — SPDR

 

Подробнее о каждом из них …

 

Регистр управления  – «SPCR» (адрес в ATmega328P для чтения 0x2C, адрес для записи 0x4C, если у вас другой МК, то найти адреса вы можете в документации)

 

SPI_SPCR

 

— Логическая единица в 7-ом бите (имя бита SPIE) – разрешить прерывания от SPI (прерывание будет в том случае если установлен бит глобального разрешения прерываний регистра SREG (7-й бит)). После окончания передачи байта будет сгенерировано прерывание.

 

— Логическая единица в 6-ом бите (имя бита — SPE) — подключить SS, MOSI, MISO и SCK к портам микроконтроллера ATmega328P — PB2,PB3,PB4,PB5.

 

— Логическая единица в 5-ом бите (имя бита DORD) – определит, что по SPI сначала передается младший разряд, а потом старший – режим «LSB».   Логический ноль, наоборот, что сначала передается старший разряд, а далее младший – режим «MSB».

 

— Логическая единица в 4-ом бите (имя бита — MSTR) — режим ведущий включить, ноль – включить режим ведомого

 

— Логическая единица в 3-ем бите (имя бита CPOL) (полярность сигнала синхронизации или уровень синхронизации) – синхронизация ведется по отсутствию импульса (по логическому нулю) или тактовый сигнал в состоянии ожидания равен 1-цы. Логический ноль — синхронизация ведется по присутствию импульса (по логической единицы) или тактовый сигнал в состоянии ожидания равен 0-лю . По какому фронту (спад или подъем) ведется синхронизация определяется в 2-ом бите (CPHA).

 

— Логическая единица в 2-ом бите (имя бита CPHA) (фаза синхронизации) – определяет, что сигнал синхронизации определяется по спадающему фронту SCK, а логический ноль по нарастающему фронту SCK. Причем если в CPOL установлена 1-ца, то спадающий и нарастающий фронт если изобразить на диаграмме «вверхногами».

 

1-ый и 0-ой бит совместно с битом SPI2x в регистре SPSR определяют скорость передачи данных по SPI (или скорость тактовый сигналов по SCK). Данные биты имеют смысл только для ведущего, для ведомого они бессмысленны, т.к. скорость приема зависит от частоты SCK ведущего.

 

SPI2X

 

Где fosc тактовая частота задающего генератора SPI (обычно она равна частоте тактирования процессора).

 

 

Регистр состояния – «SPSR» (адрес в ATmega328P для чтения 0x2D, адрес для записи 0x4D, если у вас другой МК, то найти адреса вы можете в документации)

 

SPI_SPSR

 

 

  7-ой бит регистра «SPIF» : SPI Interrupt Flag

В бит устанавливается единица, когда передача байта данных по MOSI закончена. Если установлен бит разрешения прерывания SPI (бит SPIE) в регистре SPCR, то установка флага SPIF приводит к генерации запроса на прерывание.

 

6-ой бит регистра «WCOL»: Write COLlision Flag

Бит конфликта записи в регистр SPDR. В бит устанавливается единица, если во время передачи данных выполняется попытка записи в регистр данных SPDR.

 

— с 5-ого по 1-ый бит – зарезервированные биты, их значение всегда равняется 0-лю

 

0-ой бит «SPI2X»: Double SPI Speed Bit

Бит «двойная скорость передачи данных». Если в бит записана единица, то скорость передачи данных удвоенная. С помощью сочетания данного бита и 1-ого и 0-ого бита (SPR1, SPR0) регистра SPCR, определяют скорость передачи данных по SPI. См. таблицу выше.

 

 

Регистр данных – «SPDR» (адрес в ATmega328P для чтения 0x2E, адрес для записи 0x4E, если у вас другой МК, то найти адреса вы можете в документации)

 

Размер регистра, как и выше указанных — 8 бит. Данный регистр используется для передачи и чтения данных по SPI. Помещая данные в него, вы запускаете процесс передачи.

 

 

Рассмотрим 3-и примера работы с интерфейсом SPI на ATmega328P в средах:

 

— Arduino

 

— CodeVisionAVR или в AVR Studio

 

— На чистом СИ в среде WinAVR

(т. е. компилятор AVR GCC , компоновщик GNU Binutils и программатор Avrdude)

 

 

Обобщение по работе с SPI для любого микроконтроллера

 

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

 

Если не использовать библиотечные функции по работе с SPI и работать с регистрами напрямую то алгоритм работы примерно такой:

 

1. Cначала иницилизируют интерфейс SPI через регистр управления (для ATmega он SPCR)

  • отключаем SPI от выходов микроконтроллера (обнуляют бит) или выключаем модуль SPI
  • обнуляем регистр управления SPI
  • конфигурируем интерфейс SPI, т.е:
    • если позволяет микроконтроллер то подключаем вывод синхронизации и вывод данных (в ATmega такой возможности нет, вывод синхронизации и данных используется всегда)
    • если позволяет микроконтроллер, то выбираем какой регистр сдвига мы будем использовать, 8-битный, 16-и битный. т.е. какими данными мы будем обмениваться по SPI: 8, 16 и т.п. битными.
      (В ATmega такой возможности нет, по умолчанию используются 8 бит).
    • разрешаем или запрещаем прерывания по spi (?)
    • определяем режим работы SPI (о режимах)
    • определяем как передаются биты, сначала старший разряд или младший
    • определяем полярность сигнала синхронизации.
    • определяем по какому фронту определяется сигнал синхронизации (по спадающему или нарастающему).
    • определяем скорость передачи данных (определить делитель)
    • устанавливаем на вывод SS единицу и иницилизируем как выход (единица означает «ведомому сигнал не принимать», ноль «ведомому сигнал принимать»)
    • иницилизируем на выход выводы MOSI и SCK, а выход MISO на вход (если это не делает автоматически микроконтроллер, для ATmega328p это приходиться делать «вручную»
    • включаем режим ведущего
    • подключит SPI к выходам микроконтроллера или включить модуль SPI

2. Работа интерфейса

  • устанавливаем на SS логической ноль (зависит от микроконтроллера, в одних это надо делать самим программно (ATmega), т.е. мы устанавливаем 0-ль перед передачей и 1-цу после, а в других, выход SS устанавливается в 0-ль автоматически после записи данных в регистр передатчика и 1-цу по окончанию передачи)
  • записываем данные в регистр данных передатчика, тем самым запускаем их передачу по MOSI
  • ожидаем окончание передачи через цикл while пока в регистре состояния SPI не будет выставлен бит прерывания (для ATmege это бит «SPIF» регистра SPCR)
  • устанавливаем на SS логическую единицу

3. Отключить SPI от выхода микроконтроллера или отключить модуль SPI




Буду признателен если вы поделитесь данным постом

Комментарии
  1. Владимир пишет:

    Закралась ошибка в ваше предложение на страничке (http://s-engineer.ru/interfejs-spi/)?

    P.S. Для обеспечения односторонней связи с одним устройством, достаточно использовать SCLK, MISO (в случае если ведомое устройство только принимает) или SCLK, MOSI (в случае если ведомое устройство ничего не принимает, а только передает информацию).

    MISO — мастер принимает
    MOSI — мастер передает

  2. admin пишет:

    Спасибо Владимир, подправил опечатку в посте.



Ваш комментарий


Ответ в цифрах

 
© s-engineer.ru, 2012-2017 | Все права защищены