Как использовать SPI интерфейс и DMA

Опубликовано: 6.11.2015 Автор: Александр

SPI или Serial Peripheral Interface, или последовательный  периферий интерфейс, представляет собой синхронный интерфейс передачи данных, т.е. можно одновременно передавать и принимать данные. Такая передача называется полнодуплексной (fullduplex), но возможно также только передавать или получать данные.

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

Рассмотрим использование этого интерфейса с контроллерами серии STM32F10x с использованием DMA.  

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

В сети устройств одновременно может быть одно ведущее устройство  и несколько ведомых.

Итак, интерфейс использует 4 линии:

  • MOSI (Master Output, Slave Input) – линия данных от ведущего (мастера) к ведомым (слейвам, да, к нескольким сразу).
  • MISO (Master Input, Slave Output) – линия данных от ведомого (слейва) к ведущему (мастеру).
  • SCK (Slave Clock) – линия тактовых импульсов. Импульсы генерирует ведущий (мастер) для ведомых устройств.
  • CS (Chip Select) или SS (Slave Select) – линия выбора ведомого устройства, с которым будет происходить обмен данными.

Именно наличие линии CS позволяет использовать несколько ведомых одновременно при параллельном подключении линий данных и тактовой линии:

SPI интерфейс

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

Перейдем к сути темы. Далее рассмотрим настройку SPI интерфейса на STM32F10x и настройку DMA для передачи и получения данных.

С SPL настройка ведущего устройства (мастера) может выглядеть следующим образом:

Если нужен ведомый (слейв), то:

Передача байта через SPI интерфейс:

Получение байта, переданного через SPI интерфейс:

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

Теперь мы знаем как передавать данные. Но что если у нас большой проект и контроллер выполняет множество действий, один из которых – передача или прием большого объема данных через SPI? Прием данных мы можем сделать через прерывание, где в обработчике полученное значение будет записываться во входной буфер, но что делать с передачей? При передаче нужно дождаться, когда будет передан байт и только потом передавать следующий. А это значит, что в этом месте программа “зависнет”. Но нам хотелось бы, чтобы “оно само” передавалось.

Для решения этой задачи нужно использовать DMA в STM32 – возможность прямого доступа память-к-памяти, память-к-периферии, периферия-к-памяти. Если говорить проще, то мы указываем связь между одной областью памяти и другой. Например, с помощью DMA можно скопировать один блок памяти в другой, получится аналог memcpy, или цикла:

Если мы используем этот цикл, то мы “зависнем” тут. Если используем DMA, то программа продолжает выполняться, но при этом аппаратно копируется информация.

Учитывая, что любая периферия в STM32 находится в общем адресном пространстве, то есть возможность использовать DMA для связей: память-к-периферии и периферия-к-памяти.

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

Настроим передачу данных через SPI используя DMA. В этом случае код настройки может выглядеть так:

Теперь обработчик по завершению передачи:

Функция передачи:

Принимать можно, как писалось выше, через прерывания SPI, но можно также и используя DMA, при этом мы указываем размер массива данных, и как только этот массив будет получен – произойдет прерывание DMA. Настроим DMA на прием:

Обработчик окончания приема:

Итого. Мы кратко рассмотрели настройку SPI интерфейса на STM32F10x, настройку и обработку прерываний DMA. Все что писалось выше использует SPL, если вы используете HAL, то всю настройку сделают за вас.

По аналогии можно настроить SPI с использованием DMA на STM32F4, только DMA там чуть более навороченный.

Upd. Спасибо Михаилу за уточнение по настройке интерфейса.

 

 

 

 

В рубриках: Электроника
Метки: , , ,
Поделиться записью:

2 Комментариев к “Как использовать SPI интерфейс и DMA”

  1. Михаил:

    SPI_NSSInternalSoftwareConfig тут избыточно для рядового случая, лаконичнее при инициализации
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;