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

Один SPI на два дивайса

STM32F417. Есть два дивайса, датчик температуры и управляемый резистор, из первого нужно только читать данные, во второй только писать, выводы MOSI, MISO развожу по соответствующим девайсам, CS понятно разные. SPI2 назначать как Full-Duplex Master?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так не получается. Проект генерю из 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 для третьего девайса.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"…Как правильно работать с несколькими девайсами ни одном SPI?…"

 

Каждому ведомому свой отдельный CS. MOSI, MISO общие для всех ведомых. В каждый конкретный момент времени общение идёт с одним конкретным ведомым (активен только один CS).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Каждому ведомому свой отдельный CS. MOSI, MISO общие для всех ведомых. В каждый конкретный момент времени общение идёт с одним конкретным ведомым (активен только один CS).

Я так и делаю, у меня пока один девайс с одной линией SO и с Full-Duplex Master не работает. Наверное придётся переключать Full-Duplex Master <-> Receive Only Msster <-> Transmit 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 для третьего девайса.

 

CS снимается, когда DMA записал последний байт в DR, а должен сниматься когда вычитан последний байт из DR. Вообще странно: цикл SPI это одновременное запись-чтение и надёжным признаком является заполнение DR принятым.

Может есть другой более подходящий статус HAL_DMA_STATE_****

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так не получается. Проект генерю из STM32CubeMx.

По-моему, вывод очевиден. Куб - в топку. Накодить всё самостоятельно, как принято у настоящих мущщин :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По-моему, вывод очевиден. Куб - в топку.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот тут-то и парадокс: когда знаешь что и где "кубы" без надобности.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот тут-то и парадокс: когда знаешь что и где "кубы" без надобности.

 

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

Контролировать в цикле неправильно.

Во первых есть аппаратный CS, который праввильно поведет себя.

Если совсем нет выбора, а надо подключить несколько SPI устройств, то можно включить их последовательно. Поищите по ключевым словам daisy chain.

SPI устройство это регистр сдвига, который защелкивает информацию по положительному фронту CS. Для записи в устройство в конце цепочки вам придется формировать посылку из нескольких слов, чтобы нужное дошло.

Ну вот например так как здесь описано:

https://en.wikipedia.org/wiki/Serial_Periph...l_Interface_Bus

 

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

 

А куб мне пока нравится.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

CS аппаратный не подходит, для каждого девайса у меня он свой. Теорию SPI я знаю, но сейчас не в ней проблема.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Контролировать в цикле неправильно.

Не правильно, но работает. Почему прерывание раньше происходит так и не понял, может так задумано.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не правильно, но работает. Почему прерывание раньше происходит так и не понял, может так задумано.

 

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

 

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...