Перейти к содержанию

Почему SPI на STM32 сам выключается и становится ведомым?

Обновлено Редакция GAW

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

Три варианта управления NSS у ведущего

SSMSSOEКак работает NSSКогда MODF
1—внутренний NSS задаёт бит SSI, вывод свободенесли SSI = 0
01вывод — выход, низкий при SPE = 1не возникает
00вывод — вход защиты от второго ведущегопри низком уровне на выводе

Типичная ошибка — SSM = 1 и забытый SSI = 0: внутренний NSS «в нуле», и при первом же включении SPE флаг MODF сбрасывает MSTR и SPE. Второй частый случай — SSM = 0 и SSOE = 0 при выводе NSS, подтянутом к земле или переназначенном под другую функцию.

// Master with software NSS: internal NSS held high (RM0385, 32.5.5)
SPI1->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR | (3U << SPI_CR1_BR_Pos);
SPI1->CR1 |= SPI_CR1_SPE;
// chip selects of the slaves are ordinary GPIO outputs

Если MODF уже возник, его сбрасывают чтением SPIx_SR и последующей записью SPIx_CR1; пока флаг стоит, установить SPE и MSTR нельзя. Выбор ведомых обычными выводами описан в термине «Выбор кристалла», а остальные особенности шины — на странице SPI.

Если ведущий работает, но вместо данных приходит 0xFF, причина уже в ведомом или в линии MISO — это разобрано в ответе «Почему SPI читает 0xFF». Делитель частоты SCK подбирает калькулятор предделителя SPI STM32, регистры SPI STM32F7 — на странице STM32F7.

Похожие вопросы

Можно ли просто оставить вывод NSS неподключённым?

Только если NSS не участвует: при SSM = 0 и SSOE = 0 вывод работает как вход, и любой низкий уровень на нём — помеха, подтяжка к земле или чужой сигнал — вызовет MODF. Надёжнее перевести управление в программу (SSM = 1, SSI = 1) и выбирать ведомых обычными выводами GPIO.

Как вернуть SPI в режим ведущего после MODF?

Прочитать или записать SPIx_SR, пока MODF = 1, затем записать SPIx_CR1 — это сбрасывает флаг. После этого можно снова установить MSTR и SPE. В системе с несколькими ведущими RM0385 требует, чтобы на время сброса вывод NSS был в высоком уровне.

Подходит ли аппаратный NSS (SSOE = 1) для нескольких ведомых?

Нет: в этом режиме NSS становится низким при включении SPI и остаётся таким, пока SPI включён, поэтому он годится только для одного ведомого. Для нескольких устройств на шине используют отдельные выводы выбора, как описано в термине «Выбор кристалла».

Источники

  1. STMicroelectronics. RM0385: STM32F75xxx and STM32F74xxx advanced Arm-based 32-bit MCUs. Reference manual, Rev 9 — разд. 32.5.5: в режиме ведущего NSS — вход для защиты от конфликта ведущих или выход для одного ведомого; SSM = 1 — внутренний NSS задаёт бит SSI, вывод свободен; SSM = 0, SSOE = 1 — вывод NSS управляется аппаратно, низкий при SPE = 1, многоведущий режим невозможен; SSM = 0, SSOE = 0 — низкий уровень на NSS переводит ведущего в состояние ошибки и в режим ведомого; разд. 32.5.7: SSM и SSI настраивают до MSTR, избегая конфликта на NSS; разд. 32.5.11: MODF — флаг ставится при низком внутреннем NSS у ведущего, сбрасываются SPE и MSTR; сброс флага — чтение или запись SPIx_SR при MODF = 1, затем запись в SPIx_CR1; пока MODF = 1, аппаратура не даёт установить SPE и MSTR
  2. STMicroelectronics. RM0377 Reference manual: Ultra-low-power STM32L0x1 advanced Arm-based 32-bit MCUs, Rev 10 — разд. 26.3.5 и 26.3.13: та же логика NSS и ошибки MODF у SPI STM32L0 — MODF сбрасывает SPE и MSTR, сброс чтением SPI_SR и записью SPI_CR1
  3. STMicroelectronics. cmsis-device-f7, Include/stm32f746xx.h (commit 2352e88) — SPI_CR1: MSTR — бит 2, SPE — бит 6, SSI — бит 8, SSM — бит 9; SPI_CR2: SSOE — бит 2, NSSP — бит 3; SPI_SR: MODF — бит 5

Нашли ошибку?