Spi nss что это
SPI STM32.
Для передачи данных может использоваться четыре вывода:
Miso(Master In / Slave Out data) — в зависимости от режима вывод может быть настроен как вход или выход, вход в режиме Master и выход в режиме Slave
Mosi(Master Out / Slave In data) – тут наоборот, выход в режиме Master и вход в режиме Slave
SCK – тактовый сигнал, генерируемый Master.
NSS – вывод предназначен для выбора подчинённого устройства в режиме Slave, при подаче на его вход логического ноля, также с помощью этого вывода можно переключать режимы SPI (Master/Slave), в мультимастерной шине.
Итак, вывод NSS работает не совсем так, как привычный CS у AVR, и в режиме Master для выбора ведомого необходимо использовать GPIO.
В режиме Slave сигнал(Сhip Select) можно получить с вывода NSS или программно, зависит это от значения бита SSM, если он сброшен, то считывается состояние вывода NSS, иначе определяющим является состояние бита SSI. Для приёма данных в таком случае(при программном управлении) необходимо установить SSM = 1, SSI = 0.
В режиме Master, вывод необходимо подтянуть к питанию или включить программную подтяжку (SSM =1, SSI = 1). В случае программной подтяжки вывод можно использовать как обычный GPIO.
Возможен ещё один вариант SSM = 0, SSOE = 0, вывод NSS настроен как вход с подтяжкой к питанию, при появлении на нём низкого уровня, SPI модуль подумает что появился новый Master и сам станет Slave, такой вариант используется в мультимастерной шине.
Так выглядит подключение одного Master к Slave.
Шина SPI представляет собой два последовательно соединённых между собой сдвиговых регистра и по каждому тактовому импульсу данные в регистрах сдвигаются. То есть по каждому тактовому импульсу один бит уходит из регистра, остальные биты сдвигаются к выходу, а на входе появляется свободное место, его и занимает вновь пришедший бит.
Ниже представлена блочная диаграмма модуля SPI.
На диаграмме видно, что модуль состоит из двух регистров у правления и регистра статуса, давайте рассмотрим какой бит в регистрах за что отвечает. Хотелось отметить, что изменять состояние большинства битов можно только, когда SPI выключен(SPE = 0).
Регистр управления SPI_CR1:
BIDIMODE(Bidirectional data mode enable) — если записать в этот бит единицу данные будут передаваться в двух направлениях по одной линии(однопроводной режим), если ноль —по двум линиям. При двунаправленной передаче master использует вывод MOSI, а slave вывод MISO.
BIDIOE(Output enable in bidirectional mode) — этот бит используется для настройки однопроводного режима, 1 — данные только передаются, 0 — данные только принимаются.
CRCEN(Hardware CRC calculation enable) — запись единицы в этот бит, разрешает аппаратный подсчёт CRC, 0 – запрещает.
CRCNEXT(CRC transfer next) – если этот бит установлен, это говорит о том следующей будет передаваться контрольная сумма.
DFF(Data frame format) – этот бит определяет формат фрейма, 0 — 8 бит, 1 — 16 бит.
RXONLY(Receive only) – этот бит используется в двухпроводном режиме, его установка в единицу запрещает передачу и модуль SPI работает только на приём, иначе на приём и передачу.
SSM(Software slave management) — программное управление NSS, когда этот бит установлен вместо уровня на входе NSS контролируется состояние бита SSI, если сброшен — контролируется состояние вывода NSS.
SSI(Internal slave select) — этот бит имеет силу только при установленном SSM, его значение заменяет состояние на выводе NSS.
LSBFIRST(Frame format) — определяет формат фрейма, 1 — младшим битом вперёд, 0 — старшим битом вперёд.
SPE(SPI enable) — единица в этом бите включает модуль SPI, 0 – выключает.
BR[2:0](Baud rate control) — данные биты определяют скорость передачи данных.
MSTR(Master selection) — определяет режим работы, 1 —Master, 0 — Slave.
CPOL(Clock polarity) — определяет полярность в режиме ожидания, 0 — низкий уровень в режиме ожидания, 1 — высокий уровень в режиме ожидания.
CPHA(Clock phase) – задаёт фазу тактового сигнала, 0 — выборка данных производится по переднему фронту сигнала синхронизации, 1 — выборка данных производится по заднему фронту сигнала синхронизации.
Регистр управления SPI_CR2 :
TXEIE(Tx buffer empty interrupt enable) — единица в этом бите разрешает прерывание, когда буфер передачи пуст.
RXNEIE(RX buffer not empty interrupt enable) — единица в этом бите разрешает прерывание когда буфер не пуст.
ERRIE(Error interrupt enable) — единица в этом бите разрешает прерывание при возникновении ошибки, о которой сигнализируют биты CRCERR, OVR, MODF.
SSOE(SS output enable) — единица в этом бите, разрешает использовать вывод NSS в качестве выхода и модуль SPI сам управляет выводом NSS, но управляет ним по следующему алгоритму: при включении модуля SPI(SPE = 1) на NSS появляется низкий уровень и сохраняется пока модуль не будет выключен(SPE = 0), что в большинстве случаев не подходит, поэтому для этих целей использую GPIO, а на NSS в режиме Master программно выставляю единицу(SSM = 1, SSI = 1).
TXDMAEN(Tx buffer DMA enable) — разрешает/запрещает формировать запрос к DMA при появлении флага TXE(по завершении передачи).
RXDMAEN(Rx buffer DMA enable) — разрешает/запрещает формировать запрос к DMA при появлении флага RXE(по завершении приёма).
Регистр статуса SPI_SR:
BSY(Busy flag) — флаг занятости, предназначен для отслеживания состояния сдвигового регистра, устанавливается аппаратно во время обмена данными, а точнее с момента когда данные из регистра SPI_DR поступают в сдвиговый регистр, сбрасывается при опустошении сдвигового регистра, то есть когда все данные ушли в линию MOSI.
Производители не советуют проверять его при приёме и передаче, вместо этого советуют пользоваться флагами TXE и RXNE.
OVR(Overrun flag) – устанавливается при переполнении буфера, когда новые данные перезаписали старые, которые ещё не были прочитаны.
MODF(Mode fault) — устанавливается если в режиме Master на вход NSS поступает сигнал низкого уровня, и он становится Slave. Сбросить его можно с помощью специальной последовательности.
CRCERR(CRC error flag) – флаг ошибки контрольной суммы.
TXE(Transmit buffer empty) – устанавливается когда буфер передачи(регистр SPI_DR) пуст, очищается при загрузке данных
RXNE(Receive buffer not empty) — устанавливается когда приёмный буфер содержит данные, очищается при считывании данных.
SPI_DR (Data register) – регистр данных, фактически он состоит из двух буферов: приёма и передачи, но мы работаем только с регистром DR, поэтому для отправки данных пишем в регистр DR, для приёма читаем его же.
SPI_CRCPR (CRC polynomial register) – содержит полином для расчёта CRC, после сброса его значение равно 0x0007.
SPI_RXCRCR (Rx CRC register) – содержит вычисленную CRC принятых данных.
SPI_TXCRCR (Tx CRC register) – содержит вычисленную CRC передаваемых данных.
SPI (перевод из книги Mastering STM32)
Предисловие
Данный перевод сделан мною для группы переводчиков, которые осуществляют перевод книги Mastering STM32 (v0.21). К сожалению, ребята завязли в рутине и мы вряд ли в скором времени увидим перевод полностью, поэтому буду выкладывать свои куски перевода.
Описание SPI
Serial Peripheral Interface (SPI) — это последовательный, синхронный, полнодуплексный протокол передачи данных между главным (master) контроллером (обычно микроконтроллером или другими устройством с программируемой функциональностью) и несколькими ведомыми (slave) устройствами. Как мы увидим далее, SPI позволяет передавать данные как в полнодуплексном, так и в полудуплексном режиме. Спецификация SPI стандарт в протоколах передачи данных и была разработана в конце 70-х компанией Motorola и на данный широко используется как протокол передачи данных для многих цифровых микросхем. В отличие от протокола I2C, SPI не задает жестких условий в протоколе передачи данных по шине, давая ведомым (slave) устройствам полную свободу в структуре сообщений обмена данными.
Рисунок 1: Архитектура типовой SPI шины.
Типовая шина SPI содержит 4 сигнала, как показано на рисунке 1, даже, если возможно управлять некоторыми SPI устройствами, используя лишь 3 сигнала (в таком случае мы говорим о 3-проводном SPI).
Имея две раздельные шины данных, MOSI и MISO, SPI по сути является полнодуплексным интерфейсом передачи данных, таким образом ведомое (slave) устройство может отдавать данные главному (master) пока одновременно принимает данные от него же. В одноранговых шинах (когда одно главное (master) и одно ведомое (slave) устройства), сигнал SS может не использоваться, лишь достаточно его подтянуть к «земле» резистором на несколько килоом, линии MISO/MOSI соединяются в одно общую линию Slave In/Slave Out (SISO). В таком случае мы говорим о двухпроводном SPI, хотя по существу он конечно же трехпроводной.
Рисунок 2: Как передаются данные по шине SPI в полнодуплексном режиме
Каждая транзакция в шине начинается с подачи тактирования в линию SCK в соответствии с допустимой тактовой частотой ведомого (slave) устройства. В то же время главное (master) устройство устанавливает LOW уровень на линии SS и передача данных начинается. Обычно обмен данными подразумевает использование двух регистров (в основном 8-битные, хотя некоторые slave устройства поддерживают 16-битный размер слова), одного в главном (master) устройстве и один в ведомом (slave). Данные побитно сдвигаются в сдвиговом регистре, начиная со старшего бита, пока младший бит сдвигается в этот же самый регистр. В это же самое время, данные от ведомого (slave) устройства сдвигаются в младший бит регистра данных. Когда все биты регистра будут сдвинуты в одну и другую сторону обмен данными будет осуществлен. Если необходимо передать более одного слова данных, сдвиговые регистры обнуляются и процесс повторяется. Обмен данными может продолжаться сколько угодно большое количество циклов тактового генератора. Когда обмен завершен master выключает тактовый сигнал и линия SS возвращается в исходное состояние высокого логического уровня.
Рисунок 2 показывает процесс обмена данными в полнодуплексном режиме, рисунок 3 же демонстрирует процесс в полудуплексном режиме.
Рисунок 3: Как передаются данные по шине SPI в полудуплексном режиме
Полярность и фаза тактового сигнала (Clock Polarity and Phase)
В дополнение к настройкам тактирования шины, master и slave должны «договориться» о полярности и фазе тактового сигнала. SPI спецификация подразумевает две настройки CPOL и CPHA соответственно и многие производители микросхем заимствовали данные названия настроек.
Комбинации полярности и фазы тактового сигнала часто ассоциируют с режимами работы SPI, в таблице 1 можно увидеть данные комбинации. Наиболее общие и часто используемые режимы это 0 и 3, большинство ведомых (slave) устройств поддерживают как минимум пару режимов.
Таблица 1: Режимы работы SPI, соответствующие конфигурации CPOL и CPHA
Временная диаграмма показана на рисунке 4 и она дополнительно описана ниже:
Вот и все, CPHA=0 подразумевает, что выборка идет по первому фронту импульса тактовой частоты, CPHA=1 же подразумевает, что выборка осуществляется по второму фронту импульса тактовой частоты вне зависимости от того возрастающий ли фронт или спадающий. Необходимо помнить, что при CPHA=0 данные должны быть стабильны за пол цикла до начала первого импульса тактовой частоты.
Рисунок 4: Временная диаграмма для соответствующих настроек CPOL и CPHA
Управление сигналом Slave Select
Как говорилось ранее, ведомое устройство в SPI шине не имеет адреса, по которому его можно было бы идентифицировать, но оно начинает обмен данными и продолжает его пока сигнал Slave Select (SS) находится в низком логическом уровне LOW. STM32 микроконтроллеры предоставляют два режима управления сигналом SS или NSS, как он называется в документации ST. Давайте проанализируем их.
TI режим SPI
SPI интерфейс в микроконтроллерах STM32 поддерживает TI режим, когда микроконтроллер работает в режиме master и сигнал NSS настроен на аппаратный режим работы. В режиме TI полярность и фаза тактового сигнала SPI автоматически устанавливаются в соответствии с требованиями протокола Texas Instruments вне зависимости от того какие настройки были выбраны до этого. Управление сигналом NSS также специфично для протокола TI, NSS сигнал совершает серию импульсов в конце каждого передаваемого байта (с LOW уровня в HIGH в начале передачи младшего бита и с HIGH в LOW в начале передачи старшего бита). Для более подробной информации можете обратиться в референс мануалу соответствующего микроконтроллера.
Таблица 2: SPI периферия всех 16-ти плат Nucleo
Наличие SPI интерфейсов в микроконтроллерах STM32
В зависимости от семейства и корпуса, микронтроллеры STM32 могут иметь до шести независимых SPI интерфейсов. Таблица 2 демонстрирует наличие интерфейсов всех плат Nucleo, рассматриваемых в рамках этой книги.
Для каждого SPI интерфейса в таблице 2 показаны пины MOSI, MISO и SCK. Темными строками выделены альтернативные пины, которые могут быть использованы благодаря соответствующей разводке платы. Для примера, микроконтроллер STM32F401RE может использовать SPI1 с пинами PA7, PA6 и PA5, но возможно использовать также пины PB5, PB4 и PB3 как альтернативные с помощью ремаппинга. Стоит заметить также, что SPI1 использует одни и те же пины во всех микроконтроллерах STM32 в корпусах LQFP-64, что сделано для pin-to-pin совместимости различных семейств микроконтроллеров STM32.
Теперь мы готовы рассмотреть как использовать CubeHAL API для программирования данного интерфейса.
HAL_SPI модуль
Для программирования SPI HAL определяет С структуру SPI_HandleTypeDef:
Давайте проанализируем наиболее важные поля данной структуры.
Настройка SPI производится с использованием объекта структуры SPI_InitTypeDef:
Как обычно, для конфигурации SPI мы используем функцию:
которая принимает в качестве входного параметра указатель на объект структуры SPI_HandleTypeDef, рассмотренной выше.
Обмен сообщениями с использованием SPI
Как только SPI интерфейс сконфигурирован, мы можем начать обмен данными с ведомыми (slave) устройствами. Так как SPI спецификации не описывает конкретный протокол для передаваемых данных, то и нет особой разницы между master и slave при настройке через CubeHAL. Разница лишь в параметре режимов в структуре SPI_InitTypeDef.
Как обычно, CubeHAL предоставляет три режима настройки шины SPI: опрос, прерывание и режим DMA.
Для отправки нескольких байт в режиме опроса необходимо использовать функцию:
Параметры, принимаемые этой функцией не нуждаются в описании, т. к. они идентичны уже изученым ранее интерфейсам, например UART. Эта функция может быть использована, если SPI настроен как SPI_DIRECTION_1LINE или SPI_DIRECTION_2LINES. Для приема нескольких байт в режиме опроса мы используем функцию:
Эта функция может использоваться в любом из трех режимов Direction.
Если ведомое (slave) устройство поддерживает полнодуплексный режим, то соответственно можно использовать функцию:
которая отправляет несколько байт, одновременно принимая ответ. Функция может быть использована только, если параметр Direction настроен на SPI_DIRECTION_2LINES.
Для обмена данными с использованием прерываний CubeHAL предоставляет следующие три функции:
CubeHAL также позволяет передавать данные с DMA и функции похожи на три, представленные выше, лишь с префиксом _DMA в конце.
Используя прерывания или DMA, мы должны быть готовы к тому, что в конце передачи мы получим ассинхронный запрос об этом. Это значит, что мы должны принять этот запрос и обработать его, разрешив и настроив контроллер прерывания NVIC и определив функцию HAL_SPI_IRQHandler() обработчик прерывания. Возможно шесть различных вызовов перечисленных в таблице 3.
Когда SPI настроен на работу с DMA в циклическом режиме, можно использовать несколько функий для паузы, продолжения и отмены циклического режима отправки/приема DMA:
Также в данном режиме существуют следующие ограничения:
В этой главе не будет рассмотрено практическое применение SPI, но в последующих главах мы будем использовать SPI для программирования Ethernet контроллера.
Максимальная частота тактирования при использовании CubeHAL
Частота SCK производна от PCLK путем деления на соответствующий предделитель. Этот предделитель принимает значения от 21 до 28. Тем не менее, как уже несколько раз ранее было замечено, CubeHAL добавляет неизбежный расход ресурсов на управление периферией. И это также применимо и к SPI. Фактически, использование CubeHAL не дает возможности получить все возможные частоты SPI с различными режимами работы.
Инженеры ST четко прописали это в документации на CubeHAL. Если вы откроете файл stm32XXxx_hal_-spi.c, то в районе 60 строки вы можете увидеть две таблицы, в которых прописаны максимально-допустимые скорости передачи данных в зависимости от параметра Direction и способа обмена данными по SPI (опрос, прерывание или DMA).
Для примера, в микроконтроллерах STM32F4 мы можем получить частоту SCK, равную fPCLK/8, если SPI интерфейс работает в режиме ведомого (slave) и мы программируем с использованием прерываний в CubeHAL.
Использование CubeMX для настройки SPI
Для использования CubeMX в первую очеред необходимо включить необходимый SPI интерфейс. Далее выбрать необходимый режим работы, как показано на рисунке 5. Далее, необходимо настроить поведение сигнала NSS. После настройки этих двух параметров можно продолжить конфигурацию во вкладке Configuration CubeMX.
Рисунок 5: Как выбрать режим работы SPI в CubeMX
Если статья показалась вам полезной подписывайтесь на мой канал в telegram, чтобы не пропустить анонсы новых статей и другую интересную информацию для разработчиков.
STM32 с нуля. Интерфейс SPI. Описание и пример использования.
Сегодня мы будем помогать двум микроконтроллерам подружиться с помощью интерфейса SPI! Для начала обсудим, что же такое вообще SPI, а потом напишем программу для обмена данными между устройствами.
Так вот, этот интерфейс позволяет связать между собой два и более устройств. Большой плюс SPI — быстродействие, так что большой объем данных улетит влегкую. Но в SPI, в отличие, например от I2C, для подключения N устройств потребуется большое количество линий (N + 3), а не 2, как в I2C. На самом деле, есть и плюсы и минусы, как и во всем в нашей жизни, так что идем дальше 🙂
Существуют несколько типов подключения к шине, но в общем-то, алгоритм работы при любом подключении практически один и тот же. Ведущий генерирует тактовый сигнал с вывода SCLK и синхронно с этим сигналом передает данные по линии MOSI. В то же время подчиненное устройство передает данные в обратном направлении по линии MISO. Получается, что все сыты и довольны 🙂 Хотя используется также подключение, при котором подчиненный только кушает байты данных, а сам ничего не шлет. А при подключении нескольких устройств возможно два варианта — независимое и каскадное. При независимом требуется больше линий, но такое подключение используется чаще.
Что же нам предлагает STM32 в плане SPI?
В общем, все, что требуется, присутствует!
Список прерываний для SPI:
Давайте посмотрим, как можно настроить SPI для работы в нужном режиме. Как и раньше мы будем использовать Standard Peripheral Library. Лезем в библиотеку, находим и открываем файл stm32f10x_spi.h. Прямо в начале файла все, что нам понадобится:
Назначив всем этим полям структуры SPI_InitTypeDef определенные значения, мы настраиваем модуль SPI. Тут вроде бы все понятно, но давайте по традиции разберем для чего нужно каждое отдельное поле.
Все возможные значения для всех полей написаны все в том же файле stm32f10x_spi.h чуть ниже определения структуры. В другом файле из SPL — stm32f10x_spi.c — функции для работы с SPI, их мы рассмотрим по мере того как они нам понадобятся.
Итак, предлагаю написать небольшую программку для обмена данными между двумя контроллерами по SPI. Будем писать программу и для ведущего и для подчиненного. Что бы такое придумать, чтобы не просто гонять бесполезные данные…
Хм, давайте так: одному контроллеру на вход подается аналоговое напряжение. Он запускает АЦП и в зависимости от полученного значения выдает на шину SPI значение. Значения могут быть такими:
Второй контроллер в зависимости от принятых данных зажигает светодиоды. Если принимает 0х01 — зажигает один диод, если принимает 0х02 — зажигает два, ну дальше вы поняли 🙂
Небольшое лирическое отступление — тут мы будем пользоваться тем, что изучали ранее — вот тут про создание проекта, а здесь про использование АЦП.
Задача поставлена, начинаем реализовывать! Сначала напишем программу для ведущего (SPI Master). Создаем проект, не забыв добавить файлы из SPL для работы с SPI, и пишем следующий код:
Master готов, пишем программу для SPI Slave:
Важное дополнение — инициализация GPIO должна происходить после инициализации SPI, иначе могут возникнуть сбои в работе Slave.
Здесь вся работа с SPI в прерывании. Когда взлетает флаг, сигнализирующий о принятии байта, бежим в прерывание и читаем данные. Приняли данные — надо обновить состояние светодиодов — выставляем переменную needUpdate в единицу. В главном цикле после этого зажигаются нужные светодиоды.
Собственно, вроде бы вот и все, две программки написали, достаточно на сегодня! Конечно, это тестовые программы, просто для знакомства с интерфейсом, поэтому все так «в лоб» сделано 🙂 Наверное, в ближайшее время поковыряем еще и I2C, заодно сравним интерфейс с уже известным нам интерфейсом SPI, так что до скорых встреч!
Spi nss что это
Рис. %img:stm_c1. Типичный вариант подключения устройства по SPI.
Многие микроконтроллеры имеют аппаратную поддержку SPI, что существенно упрощает использование внешней периферии, подключаемой по данному интерфейсу. Благодаря интерфейсу, может быть существенно упрощена разработка устройства, если пойти по пути объединения готовых компонентов, обменивающихся данными по SPI.
Интерфейс SPI достаточно прост с точки зрения реализации. При наличии такого желания, интерфейс может быть без труда реализован как программно, так и аппаратно, в том числе на базе простейших логических схем.
Обобщённо, без привязки к конкретной реализации, данный интерфейс рассматривается в статье «SPI».
Здесь уделим внимание особенностям реализации SPI в микроконтроллерах STM, в том числе рассмотрим специфичные, редко используемые режимы работы. Для быстрого ознакомления с вопросами практического использования SPI, смотрите «Примеры использования SPI в STM32».
Введение
В микроконтроллерах STM32 имеется поддержка SPI, разработчику предоставлена масса возможностей по гибкому конфигурированию интерфейса.
Естественно, что SPI может быть сконфигурирован для работы в качестве ведущего или ведомого устройства (в режиме ведущего устройства SPI является источником тактового сигнала SCK для ведомого устройства; соответственно, ведомое устройство получает тактовый сигнал от другого устройства, работающего в режиме ведущего). Интерфейс допускает конфигурации с несколькими ведущими устройствами. Кроме обычной полнодуплексной синхронной передачи по двум линиям, предусмотрена возможность передачи данных в одну сторону по одной линии; поддерживается полудуплексная связь по одной двунаправленной линии. Имеются средства для поддержки надёжной связи (CRC контроль целостности данных).
Рассмотрим подробнее эти и другие возможности SPI в микроконтроллерах STM32.
Предупреждение. Некоторые выводы устройств SPI1, SPI3 и выводы интерфейса JTAG могут иметь привязку к общим внешним выводам в некоторых моделях микроконтроллеров. Тогда для использования такого SPI можно:
— отключить JTAG, а для отладки использовать интерфейс SWD;
— отключить как JTAG, так и SWD интерфейс для автономных, не требующих отладки приложений.
Основные характеристики
Интерфейс SPI в микроконтроллерах STM32F100xx имеет следующие основные возможности.
Устройство SPI
На рисунке %img:spi_bd изображена блок-схема SPI в микроконтроллерах STM32F100xx, а с учётом высокой степени совместимости разных семейств микроконтроллеров STM между собой, она применима и ко многим другим устройствам.
Рис. %img:spi_bd
Обычно для подключения внешнего устройства к SPI используется 4 вывода.
Вывод NSS ведущего устройства может быть входом (обычно используется при наличии нескольких ведущих устройств на шине) или выходом (только если на шине только одно ведущее устройство). Режим выхода для ведущего устройства включается установкой бита SSOE (регистр SPI_CR2). В таком случае, на выходе NSS ведущего устройства устанавливается низкий уровень, когда начинается обмен данными и остаётся на низком уровне до отключения SPI. NSS как выход довольно бесполезен: если ведомое устройство одно, зачастую можно обойтись вообще без сигнала NSS; если ведомых устройств несколько, в любом случае необходимо наличие у ведущего устройства нескольких выводов NSS. А поскольку аппаратный вывод NSS только один, то всё равно потребуется формирование нужного количества сигналов NSS программными средствами с использованием стандартных портов ввода-вывода.
Пример варианта соединения между единственным ведущим и единственным ведомым устройством изображён на рис. %img:inter2. Здесь у обоих устройств вывод NSS сконфигурирован как вход. Ещё проще настроить NSS ведущего устройства как выход и оставить его неподключённым.
Рис. %img:inter2
Типичный вариант подключения, когда задействованы все линии интерфейса, изображён на рис. %img:inter3. Здесь NSS является выходом у ведущего устройства и входом у ведомого, выбор ведомого осуществляется низким уровнем сигнала NSS.
Рис. %img:inter3
Как видно из рисунков, для подключения по SPI, одноимённые выводы объединяемых устройств подключаются вместе (выводы MOSI устройств соединяются вместе, выводы MISO соединяются вместе, выводы SCK соединяются вместе). Использование NSS зависит от того, каким образом сконфигурированы устройства.
Данные передаются между ведущим и ведомым устройством в последовательной форме, по одному биту. Обычно старший бит передаётся первым, но порядок можно программно настроить. Пересылку данных всегда инициализирует ведущее устройство. Когда ведущее устройство передаёт данные к ведомому через вывод MOSI, оно одновременно получает данные от ведомого устройства через вывод MISO. Таким образом реализуется полнодуплексная связь с синхронизацией и исходящих, и входящих данных одним и тем же тактовым сигналом, который формируется ведущим устройством на выводе SCK.
Преобразование данных из параллельной формы, в которой данные пересылаются по шине микроконтроллера, в последовательную форму для передачи через SPI, осуществляется с помощью регистра сдвига, Shift register на рис. %img:spi_bd. Данные, предназначенные для передачи через SPI, загружаются в этот регистр из буферного регистра Tx. Когда завершается передача-приём очередного фрейма по SPI и полученный фрейм оказывается в регистре сдвига, содержимое регистра сдвига помещается в буферный регистр Rx. Программный доступ к регистрам осуществляется посредством регистра SPI_DR: при записи в него, данные помещаются в Tx; при чтении из регистра, получаем данные из Rx.
Прежде чем выполнять запись в SPI_DR, следует убедиться в том, что установлен флаг TXE в регистре SPI_SR, который свидетельствует, что буфер Tx в данный момент пуст (помещённые в него ранее данные уже перемещены в регистр сдвига, либо никакие данные в него ещё не записывались). О том, что в регистре Rx содержатся новые данные, полученные по SPI, сигнализирует флаг SPI_RXNE.
Управление выбором ведомого устройства
Выбор ведомого устройства может осуществляться аппаратно или программно, в зависимости от значения бита SSM в регистре SPI_CR1.
Полярность и фаза тактового сигнала
Имеется четыре возможных варианта тактирования передаваемых данных, которые выбираются с помощью битов CPOL и CPHA в регистре SPI_CR1. Биты влияют на работу SPI как в ведущем, так и в ведомом режиме.
Бит CPOL контролирует полярность сигнала SCK, т.е. начальный (пассивный) уровень тактового сигнала, который он имеет до начала пересылки данных и в паузах между передачами. Этот уровень совпадает со значением бита: если бит сброшен, низкий уровень является начальным для тактового сигнала; если бит CPOL установлен, начальным является высокий уровень.
Бит CPHA контролирует фазу тактового сигнала. Если бит CPHA сброшен, то первый фронт сигнала на выводе SCK (нарастающий, если CPOL = 0; спадающий, если CPOL = 1) является первым стробирующим импульсом, по которому фиксируется первый передаваемый бит фрейма. Если бит CPHA установлен, то второй фронт на выводе SCK (спадающий, если CPOL = 0; нарастающий, если CPOL = 1) является первым стробирующим импульсом и фиксирует первый передаваемый бит данных.
Последующие биты фрейма также будут фиксироваться по нарастающим или спадающим фронтам тактового сигнала, в зависимости от комбинации битов CPOL и CPHA.
Для того чтобы была возможна связь между двумя устройствами, полярность и фаза тактового сигнала у них должны быть настроены одинаковым образом.
Рис. %img:transfer
Примечание. Изменять биты CPOL/CPHA допускается только при отключённом SPI (т.е. при сброшенном бите SPE). Поэтому, если необходимо изменить настройки тактового сигнала в процессе работы, сначала следует отключить SPI (о правильном отключении в разных режимах, без риска потери данных, смотрите: «Правильное отключение SPI»). Изменение настроек в процессе работы может потребоваться, например, если к одной SPI шине подключено несколько ведомых устройств, для которых необходимы разные варианты тактирования.
Хотя на рисунке показан случай, когда первым передаётся старший бит фрейма, установка бита LSBFIRST в регистре SPI_CR1 позволяет изменить порядок передачи битов (младший бит первым).
Имеется возможность выбора длины фрейма (8 или 16 бит) с помощью бита DFF в регистре SPI_CR1.
Понятно, что размер фрейма, порядок следования битов, а также параметры тактирования должны быть одинаковыми для ведомого и ведущего устройств, обменивающихся информацией. Скорость передачи настраивается только для ведущего устройства, для ведомого она определяется получаемым тактовым сигналом.