SPI в STM32F0 как не сесть в лужу или правильная инициализация и отправка данных. Часть 1

   Довольно странные и неочевидные вещи творятся с SPI в микроконтроллерах STM32. Конечно, если Вы используете SPL или HAL, то Вам не о чем беспокоиться, там все уже сделано за Вас. А вот если Вы пытаетесь разобраться с микроконтроллером на более низком уровне и, возможно, уже наткнулись на некоторые странности в работе интерфейса, то продолжайте читать, возможно Вы найдете ответы на свои вопросы в моей статье.
   Хорошее правило - при настройке SPI в режиме отладки всегда проверяйте бит MODF (mode fault) в регистре статуса (SR). При наличии ошибок в настройках SPI бит MODF будет установлен в 1.
   А теперь о распространенных ошибках в настройках и неочевидных деталях:

  • Подача тактового сигнала на интерфейс SPI

   Многие забывают подать тактовый сигнал, но сейчас не об этом. Если Вы подаете тактовый сигнал на интерфейс SPI и настраиваете его в одной и той же функции, то правильным решением будет подождать 1 такт шины APB прежде чем писать в регистры конфигурации SPI. Самый простой способ - это создать временную переменную и прочитать в нее один из регистров шины APB.
   volatile uint32_t tmp;
   RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
   tmp = RCC->APB2ENR;
   (void)tmp;

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

  • Включение SPI
   Включать интерфейс SPI стоит только после полной настройки, иначе рискуете получить MODF и неработоспособный интерфейс. Под "включением" подразумевается установка бита SPE в регистре CR1 в 1. Изменять многие настройки тоже нельзя без отключения, иначе опять получите MODF.

  • Использование Chip Select (управляется железом)
   Если Вы хотите использовать CS в автоматическом режиме (чтобы SPI сам его дергал при передаче байта), то необходимо правильно это дело настроить. Будем считать, что Вы правильно сконфигурировали GPIO на работу в режиме альтернативной функции (MISO, MOSI, SCK и NSS) (NSS - это Chip select), иначе получите установленным бит MODF в регистре статуса SR.
   За работу NSS отвечают несколько бит:
- бит NSS в регистре CR1 должен быть сброшен в 0. Это позволит интерфейсу SPI управлять ногой NSS (CS) в автоматическом режиме.
- бит SSOE в регистре CR1 должен быть установлен в 1. Эта настройка установит сигнал на ноге NSS в 0 при включении SPI (при этом NSS будет всегда включен пока включен SPI, даже если данные не передаются).
- бит NSSP в регистре CR2 при установке в 1 будет выставлять на ноге NSS высокий уровень между передаваемыми данными (между каждым байтом в режиме 8 бит). Но эта настройка не будет работать, если бит CPHA в регистре CR1 установлен в 1.
  Мне кажется, что автоматический режим слишком урезан и может приводить к сбоям в работе SPI, если на линии будут присутствовать помехи, поэтому я не советую его использовать.

  • Использование Chip Select (управляется пользователем)
   Если Вы хотите использовать любой вывод GPIO в качестве CS, то можете столкнуться со следующей проблемой. Представьте, что Вы сконфигурировали GPIO интерфейса SPI (MOSI, MISO, SCK) в режим альтернативной функции, а вывод CS берете из любого доступного GPIO. При настройках SPI по умолчанию (ну т.е. Вы настроили только то, что Вам нужно) получите MODF. Это связано, в первую очередь с тем, что при настройках по умолчанию интерфейс SPI хочет взять под контроль свой CS (NSS), но не может.
   Поэтому стоит установить правильные настройки:
- бит SSM в регистре CR1 необходимо установить в 1. Это включит режим управления ногой CS (NSS) пользователем.
- бит SSI в регистре CR1 установленный в 1 позволит использовать ногу NSS (CS интерфейса SPI по умолчанию) в режиме GPIO.
    После этих настроек можно ногу NSS или любой другой доступный GPIO в качестве CS. При этом, если вы планируете использовать родную ногу NSS интерфейса SPI, ее необходимо сконфигурировать не в режим альтернативной функции, а в режим GPIO.

  • TXE и BSY в регистре статуса SPI
   Очень часто возникает путаница с битами TXE и BSY в регистре статуса SR. Это происходит особенно когда необходимо решить, что использовать для проверки опустошения регистра с данными для отправки и управления ногой CS.
   Интерфейс SPI в микроконтроллерах STM32 содержит два регистра - регистр данных (DR, в который мы отправляем данные для передачи) и сдвиговый регистр (регистр, непосредственно из которого данные передаются на шину). Бит TXE устанавливается в 1 тогда, когда регистр DR свободен и мы можем записать в него новые данные. Бит BSY устанавливается в 1 тогда, когда занят сдвиговый регистр (то есть все время, пока данные передаются). 
   Из всего этого следует, что при записи данных в регистр DR, внутренняя логика интерфейса SPI проверят, свободен ли сдвиговый регистр. И если он свободен (бит BSY сброшен в 0), то на следующем такте данные из DR передаются в сдвиговый регистр (устанавливая бит TXE в 1).
   По этому для проверки возможности записать новые данные в DR необходимо дождаться освобождения регистра DR (установки бита TXE в 1), а для отключения CS следует дождаться окончания передачи (сброса бита BSY в 0).

Комментарии

Популярные сообщения из этого блога

Разборка ноутбука Xiaomi Mi notebook pro 15.6 (сушим клавиатуру)

Использование UART + DMA при заранее неизветном количестве принимаемых символов (STM32)

Как запрограммировать STM32 без программатора