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

Почему SPI читает только 0xFF?

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

В SPI ведомое устройство отвечает, только когда выбрано своим сигналом CS и получает такты от ведущего. Пока оно не выбрано, его выход MISO отключён, и на линии остаётся то, что задаёт подтяжка или соседнее устройство. Поэтому 0xFF и 0x00 в каждом байте — признак того, что обмена фактически нет, а не испорченных данных.

Что читаетсяВероятная причинаЧто проверить
0xFF всегдаведомый не выбран или не понял командуCS опускается на всё время транзакции, бит чтения в адресе
0x00 всегдаMISO прижата или выбраны два устройстваCS остальных ведомых в единице, нет замыкания
Данные сдвинуты на бит (0x7F вместо 0xFE)не тот режим CPOL/CPHAрежим по временной диаграмме даташита
Ведущий внезапно молчитнизкий уровень на SS/NSS ведущегоSS настроен выходом или NSS программный
Первый байт мусор, дальше верноэтот байт пришёл, пока передавалась команда или адреспропустить первый принятый байт

Ведущий должен тактировать

Ведущий выдаёт такты только во время передачи. В reference manual STM32 RM0008 сказано прямо: передача начинается записью байта в буфер передачи, а принятый байт одновременно попадает в буфер приёма. Чтобы прочитать байт, нужно отправить фиктивный.

Ведущий, ставший ведомым

У AVR и STM32 есть защита от двух ведущих на шине. Если у ATmega328P вывод SS настроен как вход и на нём ноль, модуль SPI сбрасывает бит MSTR и становится ведомым. У STM32 то же самое называется ошибкой MODF. Вывод SS/NSS ведущего настраивают выходом или переводят в программный режим; у STM32 есть и третий вариант — аппаратный NSS как выход (бит SSOE).

Команда чтения

Многие датчики кодируют чтение старшим битом адреса. У BME280 управляющий регистр 0xF4 (ctrl_meas) читают, передавая 0xF4, а записывают, передавая 0x74. Если бит чтения не выставить, датчик воспримет запрос как запись и ничего не вернёт.

Режим тактирования по даташиту определяют по инструкции в ответе «Как узнать режим SPI по даташиту?», четыре режима разобраны в термине «режимы SPI», а посмотреть кадр по битам поможет диаграмма кадра SPI. Основы шины — на странице SPI.

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

Почему SPI читает 0x00, а не 0xFF?

Если MISO прижата к нулю — подтяжкой вниз, замыканием или вторым устройством на шине, которое тоже выбрано, — читаются нули. Проверьте, что одновременно опущен только один CS и что у неиспользуемых ведомых CS в единице.

Зачем передавать байт, если нужно только прочитать?

В SPI ведущий сам выдаёт такты, а такты идут, только пока он передаёт. По RM0008 обмен начинается записью байта в буфер передачи, и принятый байт появляется одновременно с отправленным. Поэтому для чтения передают фиктивный байт, обычно 0x00 или 0xFF.

Почему Arduino перестаёт быть ведущим SPI?

Если вывод SS (D10 на Uno) настроен как вход и на нём оказался ноль, по даташиту ATmega328P модуль SPI сбрасывает бит MSTR и становится ведомым. Поэтому D10 держат выходом, даже если CS устройства подключён к другому выводу.

Источники

  1. STMicroelectronics. RM0008 Rev 21. Reference manual: STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx — разд. 25.3.3 — в режиме ведущего передача начинается при записи байта в буфер передачи, принятый байт попадает в буфер приёма с флагом RXNE; NSS в аппаратном режиме входа держат в единице, в программном режиме ставят SSM и SSI; MSTR и SPE остаются установленными, только если NSS в единице; разд. 25.3.10 — ошибка MODF при низком NSS у ведущего: сбрасываются SPE и MSTR, модуль становится ведомым; разд. 25.3.1 — при SSOE = 1 вывод NSS ведущего работает выходом
  2. Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet (DS40002061B) — разд. 19.3.1 — ведомый при высоком SS не принимает данные, все его выводы — входы; разд. 19.3.2 — если у ведущего SS настроен как вход и опущен в ноль, бит MSTR сбрасывается и SPI становится ведомым, MOSI и SCK превращаются во входы
  3. Bosch Sensortec. BME280 Combined humidity and pressure sensor: Data sheet (BST-BME280-DS001-24, revision 1.24, February 2024) — разд. 6.3 — в SPI старший бит адреса регистра заменён битом чтения/записи: для чтения регистра передают его полный адрес (0xF7), для записи — адрес без старшего бита (0x77); разд. 5.4.5 — управляющий регистр ctrl_meas по адресу 0xF4

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