[Home] [Donate!] [Контакты]

SPI в STM32. Управление передачей данных

Оглавление
SPI в микроконтроллерах STM32. Основы
SPI в STM32. Работа в ведомом и ведущем режимах
SPI в STM32. Управление передачей данных
Процессы передачи и приёма данных
Управление передачей и приёмом данных
Вычисление CRC
Флаги состояния
Флаги ошибок
Прерывания
Правильное отключение SPI
SPI связь с использованием DMA (прямого доступа к памяти)
Источники и дополнительная информация
Регистры SPI
Использование SPI при работе с микроконтроллерами STM32F100xx
Примеры программ

Процессы передачи и приёма данных

Tx и Rx буферы

В процессе приёма, полученные данные сохраняются во внутреннем буфере Rx (сначала принимаемые биты накапливаются в сдвигающем регистре, а когда фрейм полностью получен, он копируется в Rx). Содержимое буфера Rx может быть получено путём чтения регистра данных SPI_DR. При передаче, прежде чем данные будут отправлены, они сначала записываются во внутренний буфер Tx, запись в Tx происходит при записи в SPI_DR.

Запуск обмена данными в ведущем режиме

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

Запуск обмена данными в ведомом режиме

* В двунаправленном режиме используется только одна линия данных, которая в случае ведомого устройства подключается к выводу MISO.

Управление передачей и приёмом данных

В микроконтроллерах STM32 устройства SPI имеют набор флагов (аппаратно устанавливаемых битов) в регистре SPI_SR, значения которых дают информацию о текущем состоянии устройства. Наиболее важны для организации процесса пересылки данных флаги TXE, RXNE.

TXE флаг (Tx buffer empty, Tx буфер пуст) устанавливается, когда данные пересылаются из буфера Tx в сдвигающий регистр. Установка данного флага показывает, что внутренний буфер Tx освободился и готов для загрузки в него новых данных. Также этот флаг установлен вначале работы (до любой записи в SPI_DR). При установке флага генерируется прерывание, если установлен разрешающий бит TXEIE в регистре SPI_CR2. Сброс флага TXE происходит при записи в регистр SPI_DR.

Примечание. Перед записью в SPI_DR, программа должна убедиться в том, что флаг TXE установлен в 1. В противном случае возможна перезапись предыдущих данных в буфере Tx, которые ещё не были загружены в регистр сдвига.

RXNE флаг (Rx buffer not empty, Rx буфер не пуст) устанавливается после копирования принятых данных из сдвигающего регистра в буфер Rx. Установка флага является признаком того, что готовы данные для чтения из регистра SPI_DR. При установке флага генерируется прерывание, если установлен разрешающий бит RXNEIE в регистре SPI_CR2. Сброс бита RXNE происходит при чтении из регистра SPI_DR.

В некоторых случаях может использоваться флаг BSY для ожидания завершения последней передачи данных.

Поведение основных флагов SPI в процессе передачи данных в режиме ведущего устройства при полнодуплексной связи, (BIDIMODE=0 и RXONLY=0), непрерывная передача. Настройки тактирования: CPOL=1, CPHA=1.
Рис. %img:mfdtc1

Рисунок %img:mfdtc1 изображает процессы при передаче данных, прежде всего изменение состояния основных флагов для ведущего устройства. Рассматривается непрерывная передача, т.е. без пауз между фреймами, что достигается за счёт того, что программа поставляет передаваемые данные достаточно быстро, новые данные помещаются в буфер до завершения передачи текущего фрейма. Предполагается использование полнодуплексной связи (BIDIMODE = 0 и RXONLY = 0), настройки тактового сигнала: CPOL = 1, CPHA = 1.

Для получения/передачи данных используется следующая процедура.

  1. Включить SPI, установив бит SPE в 1.
  2. Записать первый элемент данных в регистр SPI_DR (байт или двойной байт в зависимости от настроек). В результате произойдёт сброс флага TXE.
  3. Дождаться, пока снова установится флаг TXE (ждать до выполнения условия TXE == 1), после чего записать следующий элемент данных в регистр SPI_DR. Затем ждём установки флага RXNE в 1, после чего считываем полученные данные из SPI_DR (это сбрасывает флаг RXNE). Повторяем этот пункт, пока не будут переданы/получены n - 1 элементов данных.
  4. Дожидаемся установки флага RXNE (RXNE == 1), после чего считываем полученные данные (это будет последний полученный фрейм).
  5. Дождаться выполнения условия TXE == 1, а затем BSY == 0, прежде чем отключить SPI.

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

Поведение основных флагов SPI в процессе передачи данных в режиме ведомого устройства при полнодуплексной связи, (BIDIMODE=0 и RXONLY=0), непрерывная передача. Настройки тактирования: CPOL=1, CPHA=1.
Рис. %img:mfdtc2

На рис. %img:mfdtc2 изображены процессы для аналогичной ситуации, но при работе в режиме ведомого устройства. По диаграмме легко проследить за изменением состояния флагов SPI в процессе передачи/приёма данных. Отметим, что флаг BSY, который у ведущего устройства при непрерывной передаче остаётся установленным на протяжении всего процесса передачи данных, в ведомом устройстве сбрасывается в 0 на один период тактового сигнала SPI между фреймами при непрерывной передаче.

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

Непрерывная и прерывистая передача данных

Если ведущее устройство передаёт данные, и при этом программное обеспечение реагирует достаточно быстро, сразу же записывая в регистр SPI_DR новые данные в ответ на каждую установку флага TXE (или, по крайней мере, успевает сделать запись до завершения текущей передачи фрейма), то такая передача может быть названа непрерывной. В этом случае тактовый сигнал генерируется непрерывно, без остановок между фреймами; флаг BSY ведущего устройства не сбрасывается между пересылками смежных фреймов.

Наоборот, если программа реагирует недостаточно оперативно, могут возникнуть паузы между передачами фреймов. На время, пока отсутствуют данные для передачи, останавливается генерация тактового сигнала SPI; флаг BSY сбрасывается (рис. %img:mfdtd).

Прерывистая передача данных по интерфейсу SPI.
Рис. %img:mfdtd

В ведущем режиме "только приём" (RXONLY = 1) передача данных всегда непрерывная и флаг BSY всегда имеет значение 1. В руководстве описывается исключение, когда BSY остаётся сброшенным на всём протяжении процесса обмена данными, это происходит в ведущем режиме с двунаправленной связью по одной линии при работе на приём (MSTR = 1, BIDIMODE = 1, BIDIOE = 0), флаг остаётся сброшенным в процессе получения данных.

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

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

Вычисление CRC

Возможность вычисления CRC реализована для обеспечения контроля достоверности передаваемых данных. Имеются отдельные вычислители CRC для передаваемых и принимаемых данных. CRC вычисляется с использованием запрограммированного полинома последовательно для каждого бита данных. Вычисления производятся по фиксирующему фронту тактового сигнала (передний или задний, зависит от битов CPHA и CPOL в регистре SPI_CR1).

Примечание. В зависимости от выбранной длины фрейма, при включении контроля CRC будет вычисляться CRC8 или CRC16.

Вычисление CRC включается установкой в 1 бита CRCEN регистра SPI_CR1. Это действие сбрасывает регистры CRC (SPI_RXCRCR и SPI_TXCRCR). При полнодуплексной связи или в режиме "только передача", когда имеет место программное управление пересылкой, необходимо выполнить запись в бит CRCNEXT сразу же после того, как последние данные для передачи будут записаны в регистр SPI_DR. Тогда после того, как будут переданы все данные (и буфер Tx станет пустым), автоматически перешлётся содержимое регистра SPI_TXCRCR. На время передачи CRC, вычисление CRC отключается, для того чтобы передача кода не изменила значение регистра CRC.

В режиме "только приём" необходимо записать бит CRCNEXT после получения предпоследнего фрейма данных, чтобы подготовить SPI к фазе получения CRC после завершения приёма последнего фрейма данных. На время приёма CRC вычисление CRC прекращается. При обнаружении ошибки, устанавливается флаг CRCERR в регистре SPI_SR.

Связь по SPI с контролем CRC осуществляется следующим образом:

  1. Задаём значения для CPOL, CPHA, LSBFirst, BR, SSM, SSI и MSTR.
  2. Задаём полином в регистре SPI_CRCPR (после сброса регистр содержит полином по умолчанию).
  3. Включаем вычисление CRC установкой бита CRCEN в регистре SPI_CR1, при этом автоматически сбрасываются регистры SPI_RXCRCR и SPI_TXCRCR.
  4. Включаем SPI установкой бита SPE в регистре SPI_CR1.
  5. Выполняем пересылку данных пока все байты или полуслова не будут отправлены и получены. В соответствующий момент (как пояснено выше) устанавливаем бит CRCNEXT в регистре SPI_CR1.
  6. После пересылки последнего байта или полуслова данных, SPI передаёт CRC код, вычисленный для отправленного блока данных. Также одновременно SPI получает CRC код для принятых данных от противоположной стороны обмена данными и сопоставляет со значением в регистре SPI_RXCRCR (где содержится значение, вычисленное в процессе получения данных). Если значения не совпадают, устанавливается флаг CRCERR в регистре SPI_SR, а также, при установленном бите ERRIE регистра SPI_CR2, генерируется прерывание.
Примечания.
Когда SPI находится в ведомом режиме, следует быть осторожным при включении вычисления CRC. Включать вычисление CRC можно только после перехода получаемого тактового сигнала в стабильное состояние (неактивный уровень). В противном случае может произойти ошибочное вычисление CRC. Фактически вычислитель CRC начинает воспринимать сигнал на входе SCK после установки бита CRCEN при любом значении бита SPE.
Бит CRCNEXT должен быть установлен до завершения передачи/приёма последней порции данных. Особенная внимательность к этому моменту требуется при высоких скоростях передачи данных.
При высоких скоростях передачи рекомендуется использовать DMA для предотвращения снижения пропускной способности SPI из-за издержек, связанных с пересылкой данных посредством CPU. При программном управлении пересылкой на высокой скорости, существует риск не успеть установить бит CRCNEXT до момента завершения передачи последнего фрейма данных, что приведёт к ошибке.
Когда устройство сконфигурировано как ведомое и используется аппаратный выбор ведомого устройства сигналом NSS, необходимо, чтобы сигнал на входе NSS сохранял низкий уровень между фазами пересылки данных и CRC.

Когда SPI сконфигурирован в ведомом режиме с включённой функцией CRC, вычисление CRC выполняется даже при высоком уровне на входе NSS. Это следует учитывать, когда имеется несколько ведомых устройств на одной шине.

Между отменой выбора ведомого (высокий уровень на входе NSS) и повторным выбором (низкий уровень NSS), следует сбросить регистры CRC как на стороне ведущего, так и на стороне ведомого устройства для того, чтобы синхронизировать процессы вычисления CRC.

Сброс CRC производится следующей процедурой:

  1. Отключить SPI (SPE = 0).
  2. Сбросить бит CRCEN.
  3. Установить бит CRCEN.
  4. Включить SPI (SPE = 1).

Флаги состояния

Для контроля за состоянием SPI используются следующие флаги, устанавливаемые аппаратно.

TXE (Tx buffer empty flag, Tx буфер пуст)
Когда флаг установлен, это является признаком того, что буфер Tx пуст и в него можно загружать новые данные, предназначенные для передачи (путём записи SPI_DR). При записи в регистр SPI_DR происходит сброс флага TXE.

RXNE (Rx buffer not empty, Rx буфер не пуст)
Когда флаг установлен, это является признаком того, что в буфере Rx имеются принятые данные, которые можно получить чтением из SPI_DR. Флаг сбрасывается при чтении из регистра SPI_DR.

BSY (BUSY flag, флаг занятости)
Флаг отображает состояние коммуникационного уровня SPI. Если флаг установлен, это является признаком того, что SPI занят пересылкой данных. Имеется исключение: в ведущем режиме с двунаправленной связью по одной линии при работе на приём (MSTR = 1, BIDIMODE = 1, BIDIOE = 0), флаг остаётся сброшенным в процессе получения данных.

Флаг аппаратно устанавливается, когда начинается пересылка данных (кроме случая, соответствующего описанному выше исключению).

Флаг сбрасывается:

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

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

Примечание. Не рекомендуется использовать контроль флага BSY для управления передачей и приёмом данных, для этих целей лучше подходят флаги TXE и RXNE.

Флаги ошибок

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

MODF (Master mode fault, ошибка режима ведущего устройства)

Данная ошибка фиксируется, когда SPI работает в режиме ведущего устройства, его вывод NSS настроен как вход и на этом входе появляется сигнал низкого уровня. При обнаружении данной ошибки происходит следующее:

Для сброса бита MODF программа должна выполнить следующую последовательность действий:

  1. Выполнить доступ к регистру SPI_SR по чтению или записи пока бит MODF установлен.
  2. Выполнить запись в регистр SPI_CR1.

Во избежание возникновения конфликтов между ведомыми устройствами в системах, включающих в себя несколько микроконтроллеров, на выводе NSS должен удерживаться сигнал высокого уровня на протяжении всей последовательности действий по сбросу бита MODF. Биты SPE и MSTR могут быть возвращены в свои исходные состояния после выполнения последовательности действий по сбросу MODF. Из соображений безопасности, аппаратными средствами не допускается установка битов SPE и MSTR, пока установлен бит MODF.

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

OVR (Overrun flag, Overrun condition - состояние переполнения)

Переполнение возникает тогда, когда SPI получает очередной фрейм данных, в то время как буферный регистр Rx занят (бит RXNE ещё не был сброшен после его установки в результате получения предыдущих данных).

При переполнении, содержимое приёмного буфера не обновляется новыми получаемыми данными (все последние принятые данные будут потеряны). При чтении SPI_DR будет возвращён последний успешно принятый до переполнения фрейм.

Флаг OVR сбрасывается при чтении из регистра SPI_DR, выполняемого следом за чтением из регистра SPI_SR.

CRCERR (CRC error, ошибка CRC)

Флаг используется для контроля за безошибочностью принимаемых данных. Механизм контроля включается при установке бита CRCEN в регистре SPI_CR1. Флаг CRCERR устанавливается, если полученный CRC код не соответствует значению в регистре SPI_RXCRCR, который содержит локально вычисленный для принятых данных CRC.

Прерывания

Событие Флаг Разрешающий бит
Буфер передаваемых данных пуст TXE TXEIE
Приёмный буфер не пуст RXNE RXNEIE
Ошибка в ведущем режиме MODF ERRIE
Ошибка переполнения OVR
CRC ошибка CRCERR

Правильное отключение SPI

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

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

Ведущий или ведомый режим, полнодуплексная связь (BIDIMODE = 0, RXONLY = 0).

  1. Ждём, пока установится RXNE == 1 для получения последних данных.
  2. Ждём, пока установится TXE == 1.
  3. Затем ждём выполнения условия BSY == 0.
  4. Отключаем SPI (SPE = 0), после чего можно выполнить другие необходимые действия, например, перевести процессор в состояние Halt или отключить тактовый сигнал периферийного устройства (для уменьшения потребления энергии).

Ведущий или ведомый режим, однонаправленная связь, "только передача" (BIDIMODE = 0, RXONLY = 0) или двунаправленная связь, режим передачи (BIDIMODE = 1, BIDIOE = 1).

После того, как последние данные записаны в регистр SPI_DR:

  1. Ждём пока установится TXE == 1.
  2. Затем ждём выполнения условия BSY == 0.
  3. Отключаем SPI (SPE = 0) и выполняем прочие желаемые действия.

Ведущий режим, однонаправленная связь, "только приём" (MSTR = 1, BIDIMODE = 0, RXONLY = 1) или ведущий режим, двунаправленная связь, режим приёма (MSTR = 1, BIDIMODE = 1, BIDIOE = 0).

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

  1. Ждём получения предпоследнего фрейма: если общее количество фреймов, которые планировалось получить равно n, то ждём, когда установится RXNE == 1 в (n-1) раз.
  2. Затем ждём в течение одного периода тактового сигнала SPI (используя программный цикл) и отключаем SPI (SPE = 0).
  3. Ждём, когда установится RXNE == 1, т.е. будет получен последний ожидаемый фрейм, что будет свидетельствовать о завершении пересылки всех данных.

Примечание. В ведущем режиме с двунаправленной связью при работе на приём (MSTR = 1, BIDIMODE = 1, BIDIOE = 0), флаг BSY остаётся сброшенным в процессе получения данных.

Ведомый режим, "только приём" (MSTR = 0, BIDIMODE = 0, RXONLY = 1) или двунаправленная связь, режим приёма (MSTR = 0, BIDIMODE = 1, BIDOE = 0).

  1. Можно отключить SPI (записать SPE = 0) в любое время, текущая пересылка будет завершена и только после этого SPI будет в действительности отключён.
  2. Следует дождаться выполнения условия BSY = 0, прежде чем выполнять прочие действия, которые могут нарушить доставку данных (например, перевод процессора в режим "Halt", отключение тактирования SPI и пр.).

SPI связь с использованием DMA (прямого доступа к памяти)

Для достижения максимальной скорости SPI, необходимо своевременно поставлять данные для передачи и считывать принятые в Rx буфер данные во избежание переполнения. Решению этих задач может помочь поддержка DMA, реализующая простой протокол запрос/подтверждение. Для разрешения формирования запросов DMA используется регистр SPI_CR2.

Для работы с буферами Tx и Rx используются отдельные запросы.

Когда SPI используется только для передачи данных, может быть включён только SPI Tx канал DMA (для обслуживания запросов на передачу данных). В этом случае, в процессе пересылки данных будет установлен флаг OVR, так как не выполняется чтение из буфера принимаемых данных.

Когда SPI используется только для приёма данных, можно включить только канал SPI Rx DMA.

В режиме передачи, когда DMA система уже записала все данные, предназначенные для отправки (установлен флаг TCIF в регистре DMA_ISR), по флагу BSY можно определить момент фактического завершения пересылки данных по SPI. Это требуется, чтобы избежать потери последней передаваемой порции данных, если далее планируется отключить SPI. Приложение должно дождаться сначала пока установится TXE == 1, затем - BSY == 0.

Примечание. В процессе связи, когда осуществляется непрерывная передача данных, имеется задержка в 2 периода тактового сигнала APB между операцией записи в регистр SPI_DR и установкой флага BSY. Следовательно, обязательно, после записи всех данных, нужно ждать сначала до выполнения условия TXE == 1 и затем до BSY == 0.

Процессы отправки и получения данных с использованием DMA поясняются диаграммами на рис. %img:spi_dma_tx и рис. %img:spi_dma_rx соответственно.

Отправка данных через SPI с использованием DMA.
Рис. %img:spi_dma_tx

Получение данных через SPI с использованием DMA.
Рис. %img:spi_dma_rx

Пересылка данных через SPI с задействованным механизмом DMA совместима с аппаратным контролем CRC. При включённом контроле CRC и использовании DMA, отправка и получение CRC кода происходит автоматически, без установки бита CRCNEXT. После получения CRC кода, он должен быть прочитан из регистра SPI_DR для того, чтобы сбросить флаг RXNE.

После завершения пересылки данных и CRC кодов, происходит проверка достоверности полученных данных, и в случае обнаружения ошибки, устанавливается флаг CRCERR в регистре SPI_SR.

Источники и дополнительная информация

  1. "SPI Block Guide V04.01"; Motorola, Inc. (Freescale Semiconductor, Inc., http://www.freescale.com); 21 JAN 2000, Revised: 14 JUL 2004.
  2. "RM0041. Reference manual. STM32F100xx advanced ARM(R)-based 32-bit MCUs"; STMicroelectronics; Doc ID16188 Rev 5; June 2016
author: hamper; date: 2020-09-30
  Рейтинг@Mail.ru