---
# System prepended metadata

title: 17. SPI

---

# 17. SPI
## Объяснение на русском языке
https://www.youtube.com/watch?v=ceXdmGyizRw

### Краткий конспект
Нельзя просто передать сигнал от одного устройства к другому, так как есть помехи, сигнал на старте устройств, и пр. Нужно какое-то вторичное отображение того, что сейчас идёт передача сигнала
После начала реального действия сигнала должен поступить некий импульс который идёт До окончания его реального действия. Приёмник должен успеть увидеть этот импульс, отреагировать на него.  Импульс  - clock или serial clock.
Если приёмник медленный, то действие сигнала нужно искуственно продлить
Можно работать как по фронту, так и по уровню импульса. Это настраивается в программе
Самый надёжный вариант, когда импульс синхронизации полностью находится внутри действия сигнала и определение идёт по уровню
Последовательный интерфейс, когда данные большого размера передаются по маленькому каналу последовательно (разбиваются и кусками передаются) 
Проблема в том, что когда подаётся цепочка из нескольких байт/бит можно
1) пропустить первые несколько байт/бит, и получить искаженную информацию
2) из-за помех пропустить какой-нибудь синхроимпульс, из-за чего также полученные данные будут сильно отличаться

Для того чтобы решить проблему для каждого такого сообщения (состоящего из нескольких маленьких) так же подаётся синхроимпульс. Лучше чтобы синхроимпульс был длинее, что позволяет определять длительность посылки. Его называют CS, или SS (slave seiver) с черточкой сверху. Чаще всего инвертирован (0 означает сигнал) 
Практически сразу после приёма 1 еденицы информации на возврат подаются свои значения, так что мастер должен спустя некоторое время после инициализации clock ждать ответа по ещё 1 линии
Соответственно такой последовательный интерфейс имеет 4 линии передач и является двунаправленным
схема, которая на рисунке ниже, есть в объяснении. 
Здесь: по первой линии идет информация, по второй сериал клок, по третьей SS, по 4 ответ
![](https://i.imgur.com/hNgs393.png)


При передаче данных на передатчике используем слвигающий регистр, который отдаёт биты по одному. При каждом таком сдвиге получаем синхроимпульс
Входные данные заносятся в тот же сдвигающий регистр, но уже в его конец. 
На приёмнике данные тоже записываются в битовый регистр. clock является тактовым сигналом к тому, чтобы записались данные и произошёл сдвиг
￼
Кто из устройств является master, а кто slave определяется только тем, кто генерирует тактовые сигналы, так что они могут каждый байт меняться ролями
Если мы допустим хотим из одного устройства подать запрос на другой, то в случае отсутствия соединения (тактовые сигналы не воспринимаются), нам придёт пустой байт. Если соединение есть, то при первом тактовом импульсе приёмник заполнит свой регистр сдвига данными

Можно связываться с несколькими слейв устройствами одновременно, для этого нужно просто подавать на каждый из них свой SS. А все остальное общее

Регистры и флаги. 
Data order - определяет, подаются ли данные слева направо или справа налево (сначала 0 или сначала 7 бит) 
В ролике 1:20 начинается разбор регистров
1:27 примеры кода

## Cхема на английском
![](https://i.imgur.com/HtTcol0.png)

Объясняем слева сверху
XTAL - тактовый импульс процессора. Обрабатывается предделителем, который делит эту частоту на 2/4/8...128.
С помощью мультиплексора и флагов SPR0,SPR1,SPI2x задаем нужную частоту для работы в моде мастера. Эта частота подается на блок clock logic. Туда же подается информация из пинов SCK, SS, если мы работаем в режиме слейв. Чтобы clock logic понял мастер мы или слейв туда же подается MSTR. Чтобы определить способ распознавания clock закидываем CPOL, CPHA. Если мы мастер, то эта информация уйдет к pin control logic, откуда потом они перейдут на SCK, SS
Если мы слейв - то полученная информация уйдет на блок SPI control (который потом перезапишет инфу в регистр статуса SPI), и вызовет интеррапт (погуглить как это писать). В любом случае информация с clock logic уйдет на блок с регистрами сверху, чтобы они начали работать
С частотой закончили.
SPDR на схеме не нарисован, но он идет от internal data bus снизу. Он идет наверх к readDataBuffer. Оттуда данные переносятся в шифт регистр сразу же, если мы мастер, а если мы слейв, то ждем пока шифт регистр заполнится, и закидываем в readDataBuffer. 8 бит shift регистер сдвигает все данные слева направо (или справа налево, в зависимости от DORD) когда на него приходит clock. 
Биты, которые вырабатывает шифт регистр идут на пин контрол logic. Pin control logic знает слейв мы или мастер. Мы ему данные подаем сразу на порты слейва и мастера, а он уже сам поймет, куда ему смотреть. Также и с получением данных.
Там они отправляются на MOSI и приходят на MISO. А если наоборот, данные принимаются на MISO, а идут из MOSO.
MOSI, MISO, SCK, SS это все пины атмега.
С передачей закончили
В левом нижнем углу есть SPI Control. Кстати, к нему идет еще какая-то информация из clock logic и pin cotrol logic. К controll logic идет без стрелочек, так что возможно в обе стороны.
По получению данных он обновляет регистр статуса (SPIF - прерывание, WCOL - ошибка). Помимо уже названных битов, приходящих на spi controll туда приходят SPE (разрешает прерывания), SPIE (разрешает работу SPI).



## Схема на русском
![](https://i.imgur.com/ffxkYvo.png)



**Serial Peripheral Interface**
Последовательный периферийный интерфейс (SPI) обеспечивает высокоскоростную синхронную передачу данных между ATmega16 и периферийными устройствами или между несколькими устройствами AVR.
В отличие от стандартного последовательного порта, SPI является синхронным интерфейсом, в котором любая передача **синхронизирована с общим тактовым сигналом**, генерируемым ведущим устройством (процессором).
включает в себя следующие функции:
• [Полнодуплексная](/onA8_sLUSYWhMZUIMEkoZQ) трехпроводная синхронная передача данных 
• Ведущий или ведомый режим (Master slave)
• Передача данных с первым младшим битом или с первым старшим битом
• Семь программируемых битрейтов *(количество бит, используемых для передачи/обработки данных в единицу времени)*
• Флаг прерывания окончания передачи (End of Transmission Interrupt Flag)
• Защита флажка записи при столкновении (Write Collision Flag Protection)
• Выход из режима ожидания (Wake-up from Idle Mode)
• Двухскоростной (CK/2) режим Master SPI

Выводы шины:
**SS (chip select)** — это ножка выбора устройства. Если на ведомом устройстве на данной ножке установится низкий уровень, то данное устройство будет откликаться и обмениваться информацией по шине SPI, если высокий, то не будет.

**MOSI** (master output slave input) — это ножка выхода ведущего устройства и входа ведомого устройства.

**MISO** (master input slave output) — наоборот, выход ведомого, вход ведущего.

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

Эти выводы берутся с пинов: [15.Порты ввода/вывода](/mOXnuCxYSP-OA_Vh5FU9Uw) PB7-PB5

![](https://i.imgur.com/bEQqK7c.png)

Взаимосвязь между ведущим и ведомым ЦП с SPI показана на рис. 66.
Система состоит из двух [сдвиговых регистров](/evc2Ybg2Q6CRqvN6X5v1kg) и ведущего тактового генератора. Ведущее устройство SPI инициирует цикл связи, когда подает низкий уровень на вывод SS выбора ведомого устройства желаемого ведомого устройства. Ведущий и ведомый подготавливают данные для отправки в своих соответствующих регистрах сдвига, а ведущий генерирует необходимые тактовые импульсы на линии SCK для обмена данными. Данные всегда перемещаются от Master к Slave по линии Master Out – Slave In, MOSI, и от Slave к Master по линии Master In – Slave Out, MISO. При настройке в качестве ведущего интерфейс SPI не имеет автоматического управления линией SS. Это должно быть обработано пользовательским программным обеспечением до начала связи. Когда это сделано, запись байта в регистр данных SPI запускает тактовый генератор SPI, и аппаратное обеспечение сдвигает восемь битов в ведомое устройство. После сдвига на один байт тактовый генератор SPI останавливается, устанавливая флаг конца передачи (SPIF). Если бит разрешения прерывания SPI (SPIE) в регистре SPCR установлен, запрашивается прерывание. Мастер может продолжить сдвиг следующего байта, записав его в SPDR, или сигнализировать об окончании пакета, установив высокий уровень на линии выбора ведомого, SS. Последний входящий байт будет храниться в регистре буфера для последующего использования.
При настройке в качестве ведомого интерфейс SPI будет оставаться в спящем режиме с тройным состоянием MISO, пока на выводе SS установлен высокий уровень. В этом состоянии программное обеспечение может обновлять содержимое регистра данных SPI, SPDR, но данные не будут смещаться поступающими тактовыми импульсами на вывод SCK до тех пор, пока на вывод SS не будет подан низкий уровень. Поскольку один байт был полностью сдвинут, устанавливается флаг конца передачи SPIF. Если бит разрешения прерывания SPI, SPIE, в регистре SPCR установлен, запрашивается прерывание. Подчиненное устройство может продолжать размещать новые данные для отправки в SPDR перед чтением входящих данных. Последний входящий байт будет храниться в регистре буфера для последующего использования.

![](https://i.imgur.com/kLLD5nU.png)

Система имеет одинарную буферизацию в направлении передачи и двойную буферизацию в направлении приема. Это означает, что передаваемые байты не могут быть записаны в регистр данных SPI до завершения всего цикла сдвига. Однако при приеме данных принятый символ должен быть прочитан из регистра данных SPI до того, как следующий символ будет полностью вставлен. В противном случае первый байт будет потерян. В режиме SPI Slave логика управления будет выбирать входящий сигнал вывода SCK. Чтобы обеспечить правильную выборку тактового сигнала, минимальные низкие и высокие периоды должны быть:
Низкие периоды: более 2 тактовых циклов ЦП.
Высокие периоды: более 2 тактовых циклов ЦП.

:::warning
Судя по этой схеме в некоторых случаях направление портов на микроконтроллере должны задавать мы сами (НА ВЫВОД). Неприятно. по дефолту они вроде как входы.

![](https://i.imgur.com/EhwB6Hd.png)
:::