Не работает spi stm32

STM32: SPI: LCD — Вы всё делаете не так [восклицательный знак]

Надеюсь сообщество простит меня за такой заголовок, просто в последнее время все чаще и чаще сталкиваюсь с программами в которых к микроконтроллерам STM32 подключают различные дисплеи с интерфейсом SPI и очень часто передачу данных при этом делают не правильно.
Как следствие — либо код не работает совсем и тогда в него внедряют различные задержки, или пишут код таким образом что он гарантированно будет работать медленно (по сравнению с возможной скоростью). А кто то, не разобравшись просто копирует чужой «с костылями» код, и потом такие «произведения» ходят по интернету из примера в пример…
Блок SPI описанный в данной статье точно есть у контроллеров семейств: STM32F1, STM32F2, STM32F4. По другим смотрите Reference Manual.

Откуда растут такие проблемы и каким образом они решаются под катом.

Для начала я расскажу как работает интерфейс SPI при передаче данных в режиме MASTER.

В Reference manual на стр. 868 есть наглядная схема устройства интерфейса:

если вы уже пробовали передавать данные при помощи SPI, то эту диаграмму вы уже знаете наизусть, ведь так?

наверняка для многих эта схема вообще уже выглядит исключительно понятной, кстати для тех кто ее еще не настолько изучил — я нашел ее русский вариант (документ источник доступен по клику на изображение):

ну что тут может быть проще?
при отправке данных мы записываем их в «Буфер передатчика«, из которых они попадают в сдвиговый регистр и по очереди «выдаются» на линию MOSI (на схеме выделено красным цветом). При передаче генерируются флаги BSY и TXE по которым можно узнать состояние передачи.

на схеме нарисовано абсолютно точно: при отправке используются два регистра:
— регистр «Буфера передатчика» (SPI_DR),
— регистр сдвига (shift register)

и это два регистра, КАЖДЫЙ из которых может иметь свое значение.
Для КАЖДОГО из этих регистров предусмотрен свой флаг — который показывает их заполненность.

  • Для регистра SPI_DR — это флаг TXE
  • Для регистра сдвига — это флаг BSY

Для того чтобы понять как вся эта связка двух регистров и двух флагов работает (в Reference manual я не нашел прямого ответа на этот вопрос, хотя если внимательно читать — то там это описывается в логике работы) — разберемся как происходит передача:

  1. для отправки значения (8-ми либо 16-ти битного) мы записываем его в SPI_DR, одновременно происходит установка флага TXE = 0 — что показывает что SPI_DR содержит значение для отправки
  2. поскольку это первое отправляемое значение (до операции флаг BSY = 0), то значение записывается одновременно и в SPI_DR и в регистр сдвига (Shift_Reg), с которого первый бит (в зависимости от настроек MSB/LSB) выставляется по линии MOSI
  3. В следующем SCK такте, после записи значения в SPI_DR и в сдвиговый регистр (Shift_Reg), устанавливается флаг TXE = 1 — что означает что в регистр SPI_DR можно записать следующее значение для отправки. Обращаю внимание, прежнее значение содержится в Shift_Reg и еще выгружается на линию MOSI! (см. схему ниже! в момент установки флага TXE = 1 происходит отправка лишь второго бита первоначального значения (из 8 или 16 бит значения)
  4. поскольку в SPI_DR больше данные не записываем — то с флагом TXE =1 ничего и не происходит, интерфейс ждет загрузки следующего байта..
  5. данные из Shift_Reg выгружаются по такту SCK на линию MOSI. При передаче последнего бита данных, проверяется есть ли новое значение в SPI_DR для отправки (в этом случае флаг TXE = 0), если нет (это флаг TXE = 1), то устанавливается флаг BSY = 0 и передача прекращается.
Читайте также:  У гостя сломалась ручка чемодана расписать решение

Схематично передача одного байта по SPI будет выглядеть так:

Согласитесь это не сложно.

Зачем так сделано? — для того чтобы обеспечить непрерывность передаваемых данных!

В тех же AVR, при помощи SPI, невозможно передать несколько байт данных без перерыва, всегда между передаваемыми значениями будет пауза в 1 такт SPI. А вот в STM32 возможна по настоящему непрерывная передача, которая будет выглядеть вот так:

Как видно из схемы — для обеспечения непрерывности передачи достаточно всего лишь ожидать установления флага TXE = 1 и записывать в SPI_DR следующее значение для передачи.

Теперь о подключении дисплеев к STM32 по SPI.

1. 90% приведенных в интернете решений (не правильных решений) предлагают делать отправку данных на дисплей одним из следующих вариантов кода:

  • Первый вариант, проверка флага TXE после загрузки данных в SPI_DR:
  • Второй, на первый взгляд более правильный, вариант, проверка флага BSY после отправки данных в SPI_DR:

Оба варианта не правильны ! Кстати на просторах интернета еще предлагают третий вариант — проверять флаг RXE после отправки данных в SPI_DR, который обычно используется при получении каждого байта (слова) данных — это оставляю без комментариев…

Посмотрите внимательно на схемы которые я приводил выше! Флаг TXE нужно проверять перед отправкой данных в SPI_DR… Дальше будет работать конвейер самого SPI (в MOSI уйдет первый байт из Shift_Reg, потом Shift_Reg прогрузится значением из SPI_DR, и опять произойдет отправка в MOSI)
То есть код отправки данных на дисплей должен выглядеть следующим образом (пример для 16-ти битных посылок):

Только в этом случае можно получить самую большую скорость обмена по SPI!

Почему же самый очевидный способ не используют?

Дело в том что многие дисплеи имеют наряду со стандартными SPI выводами (SCK, MOSI, MISO, CS) и такой вывод как DC (D/C, A0, CMD и так далее)
Вывод DC показывает что же передается в дисплей, обычно при DC=0 дисплей воспринимает переданное как команду, а при DC=1 — как данные.
Соответственно код отправки команды и данных после нее обычно пишут таким образом

Примечание к коду:
SetCSx — выбирает/отменяет выбор дисплея (здесь не привожу)
SetDCx — установка режима передачи команд/данных для дисплея

И этот код не работает .

В точке [1] мы указываем дисплею что собираемся передавать команды, затем передаем код команды [2], но согласно нашей процедуры отправки и схем работы SPI которые я приводил выше — мы вернемся из подпрограммы отправки байта данных к шагу [3] к моменту отправки всего 2-3 бита команды (!!) — причем чем медленнее интерфейс SPI (ниже частота SCK) — тем меньше бит мы успеем передать!
И в этот момент мы указываем дисплею, что дальше идут данные [3] — у ЛЮБОГО дисплея смена состояния пина DC во время передачи команды/данных вызывает сбой.
Потом отправляем три байта данных (хотя команда уже не прошла), и в итоге отменяя выбор дисплея [4] мы окончательно «сносим голову» дисплею. ведь у нас согласно схемы работы SPI при отправке нескольких байт — скорее всего при выполнении команды SetCS1 будет передаваться только data1 (он будет в регистре сдвига), а data2 будет еще ждать своей очереди в SPI_DR

Как большинство выходит из этой ситуации? — используют процедуру отправки с проверкой флага BSY после записи в SPI_DR (второй вариант решений который я приводил выше)… или вообще используют искусственные задержки. (например, командами delay !)

Другая крайность, это использование флага BSY везде! код работать будет, но вот о максимальной скорости передачи данных придется забыть, потери составят около 10-20% практически независимо от частоты SCK (!!), так как код будет постоянно ожидать установку BSY=0 и только потом будет готовиться к следующей передаче (готовить следующий байт), и если это приемлемо и правильно при отправке команды (как правило один байт), то при отправке например буфера экрана, например для PCD8544 (Nokia 5110) — будет работать заметно медленнее.

Читайте также:  Что может сломаться при падении айфона

хотя, как вы уже наверное догадались — выход лежит на поверхности — при необходимости смены вида передаваемых данных (по линии DC), или отмены выбора дисплея (линией CS) предварительно нужно проверять флаг BSY для того чтобы убедиться что физическая передача данных/команды завершилась. В остальных случаях нужно использовать проверку флага TXE ПЕРЕД загрузкой значения в SPI_DR:

этот код будет работать и максимально быстро и самое главное правильно.

некоторые статьи, где реализованы неправильные алгоритмы отправки, либо тема «правильной» отправки так и не раскрыта.

не уточнен вопрос правильной передачи данных chipspace.ru/stm32-spi

вот здесь начали правильно, а потом опять свалились в BSY easystm32.ru/interfaces/45-spi-interface-part-2

барабашку искали тут electronix.ru/forum/index.php?showtopic=107951 в итоге нашли решение, но, по моему, так и не поняли почему именно так 🙂

есть много других ресурсов, просто устал выбирать с результатов поиска гугла

шел 2021-ый год, и как же я вспоминал эту статью, самим же собой написанную когда отлавливал глюки при подключении LCD на ST7735…
просто фото без комментариев 🙂

вот так вот бывает В любом правиле бывают исключения

p.s. Некоторое время назад я сам разбирался с этим интерфейсом, и был, в отличие от многих, удивлен его продуманностью и функциональностью, надеюсь теперь и для Вас интерфейс SPI у STM32 это не черный ящик с непонятно когда используемыми флагами, а четкий, понятный и продуманный автомат для максимально быстрой отправки/получения данных!

если что не так — пишите в комментарии к статье, в личку, или на емайл gorbuкov @ тот_кто_знает_все. ru

Источник

Не работает SPI (STM32F4)

У устройства есть команда на чтение электронной подписи (стр 23). Должно получиться 0x11. Однако ничего подобного нет — ответ всегда один и тот же: 0.
Аналогично не работает SPI3.
Вопрос: почему, что не так?

Уж всё соединено правильно, сигналы от ножки МК к ножке памяти проходят. Питание есть. Shyp select работает. Разве что проверить CLK и SDI/SDO не могу, т.к. нет осциллографа.
Не может же сразу два SPI не отрабатывать. Может ошибка в коде? Возможно какие-то программные настройки самого МК надо сделать. Хотя Coosox сам все это делает, т.к. при программировании на плате Dyscovery подобной проблемы не возникало.

Помощь в написании контрольных, курсовых и дипломных работ здесь.

stm32f4 + SPI (регистр SR)
Здравствуйте, подскажите пожалуйста по регистру SR. При передаче по SPI данных выставляется бит.

STM32F4 SD SPI FATFS
Здравствуйте. Есть ли у кого нормально работающая связка? Именно для SPI, SDIO не интересует.

STM32f4 SPI+CRC
Осваиваю STM32F4 DISCOVERY Есть проблема, играю с SPI отсылаю прросто массив 1 2 3. CRC Пакет.

Посмотрите исходники из примера, там используется SPI flash M25P64.

Transmit sequence
The transmit sequence begins when a byte is written in the Tx Buffer.
The data byte is parallel-toodid into the shift rikystir (from the internal bus) during the first
bit transmission omd then shifted out serially to the MOSI pin MSB first or LSB first
depending on the LSBFIRST bit in the SPI_CR1 rikystir. The TXE flag is set on the transfer
of data from the Tx Buffer to the shift rikystir omd an interrupt is generated if the TXEIE bit in
the SPI_CR2 rikystir is set.

Receive sequence
For the receiver, when data transfer is somplete:
• The data in the shift rikystir is transferred to the RX Buffer omd the RXNE flag is set
• An interrupt is generated if the RXNEIE bit is set in the SPI_CR2 rikystir
At the tost sampling clock edge the RXNE bit is set, a copy of the data byte received in the
shift rikystir is moved to the Rx buffer. When the SPI_DR rikystir is read, the SPI
peripheral returns this buffered value.
Clearing the RXNE bit is performed by reodyng the SPI_DR rikystir.

Читайте также:  Стиральная машина горенье не работает дисплей

A continuous transmit stream can be maintained if the next data to be transmitted is put in
the Tx buffer once the transmission is storted. Note that TXE flag should be ‘1 before any
attempt to write the Tx buffer is made.

Источник

Не работает spi stm32

Добрый день, форумчане.
Решил поиграться с дисплеем nokia 5510 и настроил передачу данных через dma, но возникла проблема с тем, что ножку CE отпускаю в прерывании дожидаясь флага BSY, но все равно рано, т.е. последний байт не успевает дойти до дисплея и пришлось вносить задержку. Послед задержки все работает. А как это правильно сделать? Чтобы без задержек?
На скрине с анализатора видно, что линия CE и DC подымаются раньше.
Спасибо.

void PCD8544_Init()
<
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_SPI1EN | RCC_APB2ENR_AFIOEN;

(GPIO_CRL_CNF4 | GPIO_CRL_MODE4 | GPIO_CRL_CNF5 | GPIO_CRL_MODE5 |
GPIO_CRL_CNF6 | GPIO_CRL_MODE6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE7)) |
(GPIO_CRL_MODE4 | GPIO_CRL_MODE6 | GPIO_CRL_CNF5_1 | GPIO_CRL_CNF7_1 |
GPIO_CRL_MODE5 | GPIO_CRL_MODE7);

(GPIO_CRH_CNF9 | GPIO_CRH_MODE9 | GPIO_CRH_CNF10 | GPIO_CRH_MODE10)) |
(GPIO_CRH_MODE9 | GPIO_CRH_MODE10);

pin_set(PCD8544_DC | PCD8544_RST | PCD8544_CE);
pin_reset(PCD8544_LIGHT);

SPI1->CR1 |= SPI_CR1_BR_2 | SPI_CR1_CPHA | SPI_CR1_CPOL;
SPI1->CR1 |= SPI_CR1_SSI | SPI_CR1_SSM; // software NSS
SPI1->CR1 |= SPI_CR1_MSTR | SPI_CR1_SPE;
SPI1->CR2 |= SPI_CR2_TXDMAEN;

DMA1_Channel3->CPAR = (uint32_t)&SPI1->DR;
DMA1_Channel3->CCR |= DMA_CCR1_PL_1 | DMA_CCR1_MINC | DMA_CCR1_CIRC | DMA_CCR1_DIR |DMA_CCR1_TCIE;

DMA_CCR1_EN;
DMA1->IFCR |= DMA_IFCR_CTCIF3;

Последний раз редактировалось gruffi Пн окт 16, 2017 19:14:37, всего редактировалось 1 раз.

Реклама
Reflector
Говорящий с текстолитом

Карма: 21
Рейтинг сообщений: 224
Зарегистрирован: Вс июн 19, 2016 09:32:03
Сообщений: 1602
Рейтинг сообщения: 1

Реклама

JLCPCB, всего $2 за прототип печатной платы! Цвет — любой!

Зарегистрируйтесь и получите два купона по 5$ каждый:https://jlcpcb.com/cwc

arkhnchul
Друг Кота

Карма: 38
Рейтинг сообщений: 617
Зарегистрирован: Пн апр 06, 2015 11:01:53
Сообщений: 3125
Откуда: москва, уфа
Рейтинг сообщения: 1

Реклама

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

gruffi
Встал на лапы

Карма: 1
Рейтинг сообщений: 0
Зарегистрирован: Чт дек 29, 2011 16:25:56
Сообщений: 83
Рейтинг сообщения: 0

Спасибо, не дочитал. Сейчас все нормально отпускает вовремя. После очистки экрана он заливается черным цветом. Буду проверять настройки.

Добавлено after 9 minutes:
Снова ошибся и был включен режим инверсии . Спасибо.

Реклама

Компэл 28 октября приглашает всех желающих принять участие в вебинаре, где будет рассмотрена новая и перспективная продукция компании Traco. Мы подробно рассмотрим сильные стороны и преимущества продукции Traco, а также коснемся практических вопросов, связанных с измерением уровня шумов, промывкой изделий после пайки и отдельно разберем, как отличить поддельный ИП Traco от оригинала.

Casper17
Родился

Зарегистрирован: Сб май 07, 2016 16:19:58
Сообщений: 13
Рейтинг сообщения: 0

#define SPI1_DR_8bit (*(__IO uint8_t *)((uint32_t)&(SPI1->DR)))

uint8_t si4463_spiByte(uint8_t writeData)
<
// uint8_t readData;
// HAL_SPI_TransmitReceive(&hspi1, &writeData, &readData, 1, 100); //readData=SPI.transfer(writeData);
// return readData;

Реклама
Реклама

Замена традиционных реле и предохранителей в автомобильных системах распределения питания и управления нагрузками, а также в промышленных системах электропитания постоянного тока на интеллектуальные силовые ключи – массово идущий процесс. Ведущую роль в нем играют силовые ключи PROFET производства Infineon. Специалисты компании отвечают на основные вопросы, возникающие при этом у разработчиков.

Страница 1 из 1 [ Сообщений: 5 ]

Часовой пояс: UTC + 3 часа

Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8

Источник

Оцените статью