Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Один SPI на два дивайса
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Oleg_IT
STM32F417. Есть два дивайса, датчик температуры и управляемый резистор, из первого нужно только читать данные, во второй только писать, выводы MOSI, MISO развожу по соответствующим девайсам, CS понятно разные. SPI2 назначать как Full-Duplex Master?
arhiv6
Да, это будет случай Full-Duplex Master.
Oleg_IT
Спасибо.
Oleg_IT
Так не получается. Проект генерю из STM32CubeMx. Пока работаю только с датчиком температуры, подключены SO, SCK и CS. Если конфигурить SPI как Full-Duplex Master то программа виснет на чтении данных, если как Receive Only Msster то данные идут, но не полностью.
SPI сконфигурю с DMA, когда наступает момент чтения температуры вызываю функции
Код
    uint16_t Temp; // Значение измеренной температуры
…………………………………………………
    HAL_GPIO_WritePin(GPIOA,CS_Termo_Pin,GPIO_PIN_RESET);
    HAL_SPI_Receive_DMA(&hspi1,(uint8_t*)&Temp,2);

По окончанию работы DMA вызывается прерывание со статусом HAL_DMA_STATE_READY_MEM0, поднимаю пин CS
Код
    HAL_GPIO_WritePin(GPIOA,CS_Termo_Pin,GPIO_PIN_SET);


Но по осциллографу вижу, что CS отключает датчик температуры ровно посередине второго байта. Соответственно первый байт приходит, видно он меняется, второго байта нет. Почему так может быть? В какой момент отключать CS?

Как правильно работать с несколькими девайсами ни одном SPI? Нужно и одно чтение и одна запись и Full-Duplex Master для третьего девайса.
Obam
"…Как правильно работать с несколькими девайсами ни одном SPI?…"

Каждому ведомому свой отдельный CS. MOSI, MISO общие для всех ведомых. В каждый конкретный момент времени общение идёт с одним конкретным ведомым (активен только один CS).
Oleg_IT
Цитата(Obam @ Dec 11 2015, 13:29) *
Каждому ведомому свой отдельный CS. MOSI, MISO общие для всех ведомых. В каждый конкретный момент времени общение идёт с одним конкретным ведомым (активен только один CS).

Я так и делаю, у меня пока один девайс с одной линией SO и с Full-Duplex Master не работает. Наверное придётся переключать Full-Duplex Master <-> Receive Only Msster <-> Transmit Only Msster
Obam
Цитата(Oleg_IT @ Dec 11 2015, 12:55) *
SPI сконфигурю с DMA, когда наступает момент чтения температуры вызываю функции
Код
    uint16_t Temp; // Значение измеренной температуры
…………………………………………………
    HAL_GPIO_WritePin(GPIOA,CS_Termo_Pin,GPIO_PIN_RESET);
    HAL_SPI_Receive_DMA(&hspi1,(uint8_t*)&Temp,2);

По окончанию работы DMA вызывается прерывание со статусом HAL_DMA_STATE_READY_MEM0, поднимаю пин CS
Код
    HAL_GPIO_WritePin(GPIOA,CS_Termo_Pin,GPIO_PIN_SET);


Но по осциллографу вижу, что CS отключает датчик температуры ровно посередине второго байта. Соответственно первый байт приходит, видно он меняется, второго байта нет. Почему так может быть? В какой момент отключать CS?

Как правильно работать с несколькими девайсами ни одном SPI? Нужно и одно чтение и одна запись и Full-Duplex Master для третьего девайса.


CS снимается, когда DMA записал последний байт в DR, а должен сниматься когда вычитан последний байт из DR. Вообще странно: цикл SPI это одновременное запись-чтение и надёжным признаком является заполнение DR принятым.
Может есть другой более подходящий статус HAL_DMA_STATE_****
scifi
Цитата(Oleg_IT @ Dec 11 2015, 11:55) *
Так не получается. Проект генерю из STM32CubeMx.

По-моему, вывод очевиден. Куб - в топку. Накодить всё самостоятельно, как принято у настоящих мущщин laughing.gif
Oleg_IT
Цитата(scifi @ Dec 11 2015, 14:58) *
По-моему, вывод очевиден. Куб - в топку.

А что таково в нём плохого? Открытый код делает, что не нравится можно менять, дорабатывать, знать бы что, где.
Obam
Вот тут-то и парадокс: когда знаешь что и где "кубы" без надобности.

Так почему DMA, не приняв последний байт, отваливался?
Oleg_IT
Цитата(Obam @ Dec 11 2015, 18:19) *
Вот тут-то и парадокс: когда знаешь что и где "кубы" без надобности.

Так почему DMA, не приняв последний байт, отваливался?

Да ни какого парадокса, просто экономия времени и можно посмотреть как люди программы пишут, если опыта мало.

А с DMA пока не пойму. в прерывания он входит только с HAL_DMA_STATE_READY_MEM0, сконфигурил я его так. Я вот думаю, может в SPI флаг окончания приёма контролировать, в основном цикле и когда прерывание от DMA пришло. Кривовато это как-то.
Tarbal
Цитата(Oleg_IT @ Dec 11 2015, 17:40) *
Да ни какого парадокса, просто экономия времени и можно посмотреть как люди программы пишут, если опыта мало.

А с DMA пока не пойму. в прерывания он входит только с HAL_DMA_STATE_READY_MEM0, сконфигурил я его так. Я вот думаю, может в SPI флаг окончания приёма контролировать, в основном цикле и когда прерывание от DMA пришло. Кривовато это как-то.


Контролировать в цикле неправильно.
Во первых есть аппаратный CS, который праввильно поведет себя.
Если совсем нет выбора, а надо подключить несколько SPI устройств, то можно включить их последовательно. Поищите по ключевым словам daisy chain.
SPI устройство это регистр сдвига, который защелкивает информацию по положительному фронту CS. Для записи в устройство в конце цепочки вам придется формировать посылку из нескольких слов, чтобы нужное дошло.
Ну вот например так как здесь описано:
https://en.wikipedia.org/wiki/Serial_Periph...l_Interface_Bus

Есть и другие способы, но это уже если устройство их поддерживает.

А куб мне пока нравится.
Oleg_IT
Заметил особенность, при увеличении BaudRatePrescaler общее время приёма растёт быстрее чем время нахождения CS в открытом состоянии, т.е. при BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2(4, 8, 16) приём укладывается в CS == 0, а когда BaudRatePrescaler больше, приём обрезается. Похоже DMA живёт отдельно от SPI.

CS аппаратный не подходит, для каждого девайса у меня он свой. Теорию SPI я знаю, но сейчас не в ней проблема.
Oleg_IT
Цитата(Tarbal @ Dec 12 2015, 05:07) *
Контролировать в цикле неправильно.

Не правильно, но работает. Почему прерывание раньше происходит так и не понял, может так задумано.
Tarbal
Цитата(Oleg_IT @ Dec 14 2015, 10:41) *
Не правильно, но работает. Почему прерывание раньше происходит так и не понял, может так задумано.


Пренебрежение опытом -- источник "необъяснимых" чудес в поведении разрабатываемого устройства.

Бывает, что несколько событий могут вызвать прерывание по одному и тому же вектору.
Если это так, то прочитайте в прерывании флаги и определите то ли прерывание произошло, которого вы ожидали. Если не то, то покинте (если вам его не надо обрабатывать) обработчик.
Oleg_IT
Цитата(Tarbal @ Dec 14 2015, 18:26) *
Пренебрежение опытом -- источник "необъяснимых" чудес в поведении разрабатываемого устройства.

Бывает, что несколько событий могут вызвать прерывание по одному и тому же вектору.
Если это так, то прочитайте в прерывании флаги и определите то ли прерывание произошло, которого вы ожидали. Если не то, то покинте (если вам его не надо обрабатывать) обработчик.

Не мой случай, это прерывание возникает только один раз за период обмена, проверено.
Tarbal
Цитата(Oleg_IT @ Dec 15 2015, 08:42) *
Не мой случай, это прерывание возникает только один раз за период обмена, проверено.


Вопрос стоит не сколько раз происходит прерывание, а какие флаги разрешения прерывания и какие флаги событий установлены. Вы ведь хотите понять что происходит. Так начинайте расследование планомерно и тщательно. Если хотите отгадать или чтобы вам кто-нибудь другой отгадал в чем дело, то игнорируйте мои рекомендации.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.