Почему SPI на STM32 сам выключается и становится ведомым?
Обновлено Редакция GAW
В режиме ведущего у SPI на STM32 вывод NSS — не только выход выбора ведомого. По умолчанию это вход защиты от конфликта: если другой ведущий опустит NSS, этот должен немедленно уступить шину. Поэтому низкий уровень на внутреннем NSS ведущего — ошибка режима MODF, и аппаратура сама превращает устройство в ведомое.
Три варианта управления NSS у ведущего
| SSM | SSOE | Как работает NSS | Когда MODF |
|---|---|---|---|
| 1 | — | внутренний NSS задаёт бит SSI, вывод свободен | если SSI = 0 |
| 0 | 1 | вывод — выход, низкий при SPE = 1 | не возникает |
| 0 | 0 | вывод — вход защиты от второго ведущего | при низком уровне на выводе |
Типичная ошибка — 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 включён, поэтому он годится только для одного ведомого. Для нескольких устройств на шине используют отдельные выводы выбора, как описано в термине «Выбор кристалла».
Источники
- 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
- 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
- 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
Нашли ошибку?
Смотрите также
- SPISCLK, MOSI, MISO, CS, режимы 0–3, daisy chain, частота, SPI в AVR
- Выбор кристаллаВход, которым выбирают одну микросхему на общей шине: CS, SS, CE
- STM32F7Cortex-M7 до 216 МГц: F72x/F73x, F74x/F75x, F76x/F77x — линейки, память, загрузка и распиновки
- Почему SPI читает только 0xFF?Ведомый не выбран, нет тактов, ведущий стал ведомым
- Делитель SPI STM32BR[2:0], шина APB, предел SCK по даташиту, режимы и код