Подключение нескольких устройств по SPI

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,369
965
58
Марий-Эл
Ещё одно объяснение через Сферического коня в вакууме.
У тебя есть куча кирпича и конвеер, который может поворачиваться.
Ты на одном конце кладёшь кирпич и он едет ко второму чуваку, который снимает кирпич и укладывает его.
В это время тебе приходит СМС. Прими посылку.
А конвеер у тебя один.
Ты смотришь, остались ли на нём кирпичи, если да, ты ждёшь когда уедет последний, поворачиваешь конвеер к третьему чуваку и врубаешь реверс, а он кладёт посылку на конвеер. Ты ждёшь, когда посылка доедет до тебя, снимаешь её поворачиваешь конвеер ко второму и опять его переключаешь в первоначальное состояние.
И начинаешь грузить кирпичи заново. А второй чувак покурив, пока ты принимаешь посылку, продолжает укладывать плывущие к нему кирпичи.
 

poty

★★★★★★✩
19 Фев 2020
3,205
931
Модифицировать библиотеку
я, вообще-то с этого начал и давал комментарий к реальному случаю, а не к разработке новых библиотек. Если мы говорим о том, что мы будем писать библиотеки сами, то смысла в разговоре нет.
В микроконтроллерах состояние шины можно узнать всегда!!!!
Согласен, только не штатными методами тех библиотек, которые использовал спрашивающий товарищ. Не очень понял про "уровень железа", он здесь нам совсем не помощник.
ничего не знает о приоритете прерываний
Приоритет прерываний действует, если имеются несколько флагов и нужно выбрать в какой последовательности они начнут выполняться. Если прерывание уже выполняется, то все остальные запрещены. Этот запрет можно обойти, но тогда возможно переполнение стека из-за множества вложенных прерываний.
Нет такого в микроконтроллерах
Не соглашусь. Я всегда программирую асинхронные процессы на очередях, независимо от того, на чём они выполняются. Про ОС вообще не понял, к чему это?
TFT Дисплей работающий по SPI не может так вот просто работать по прерываниям.
Не соглашусь. SPI не знает, что у тебя на другом конце и управление по прерываниям - штатный вариант для неё. То, что в известных тебе библиотеках этого нет - лишь лень тех, кто их писал (или экономия на прерываниях, дань совместимости...).
Теперь по поводу описания работы. Я не зря описывал возможности библиотек. Берём конкретику, допустим, так нелюбимый Atmega 328p. Для настройки/контроля SPI в нём имеется три основных регистра: SPCR, SPSR, SPDR (очень простая реализация). Можно изменять порядок передачи бит, полярность синхроимпульсов и их фазу для передачи данных, 4 скорости передачи (плюс удвоение), использование прерывания. Можно контролировать окончание передачи байта, коллизию буфера передачи. Каждая библиотека инициализирует (или нет) эти параметры и отслеживает статус напрямую или через библиотеки-прокладки. Т.е., в вышеприведённом коде, инициализация монитора может заменить параметры, которые раньше были установлены для радио. Выделил слово "может", так как мне лень лезть в реальные библиотеки и продираться через код их программистов. Чтобы этого (изменения инициализации) не произошло, можно запомнить параметры для каждого устройства и восстанавливать их перед изменением SS. Но! Это невозможно сделать с помощью готовых библиотек. Нужно смотреть в их код и определять эти самые параметры, делать дополнительные функции восстановления этих параметров. Далее:
Как только SPI освободился, мы отключаем CS дисплея, Включаем CS nRF и начинаем сеанс.
Здесь мы тоже должны восстановить параметры SPI для nRF, а после
отключаем CS nRF и восстанавливаем состояние CS дисплея
восстановить параметры SPI для дисплея. Кроме того, я сильно не уверен, что либо сама библиотеки, либо библиотека-прокладка управления шиной не используют функции времени (Wire, допустим, при блокировке millis перестаёт работать от слова совсем). Так что
выходим из прерывания
может вообще не сработать, так как на время переключения на nRF все функции времени (кроме ограниченно годного micros) будут заблокированы.
И тут мы приходим к тому, что всё нами написанное - это повтор уже имеющегося в библиотеках + некий упрощённый аналог мультиплексирования запросов. И как только что-то из применённого железа поменяется мы приходим к новому анализу библиотек, параметров, функций и настроек.
Версии дальнейшего - а) переписывание библиотек (как вариант, но не в случае с ТС), б) создание библиотеки-прокладки, реализующей очередь, которая будет работать с любыми библиотеками.
 

Kulibin_

✩✩✩✩✩✩✩
13 Мар 2023
12
0
Если потеря данных критична, то прервать вывод данных на прочие SPI устройства и начать чтение буфера NRF24. Если производился вывод на дисплей, то запомнить место до которого произведена запись и продолжить с того же места.
Приблизительно так?
C++:
void loop(void) {
  byte pipeNo;
  if ( radio.available(&pipeNo)) { // если есть входящие данные

  radio.read(&recieved_data, sizeof(recieved_data)); // считываем их и сохраняем в recieved_data

  digitalWrite(Radio_CS, HIGH); // отключаем радио
  digitalWrite(TFT_CS, LOW); // включаем дисплей
      
  tft.fillRect(95, 0 , 50, 128, ST7735_BLACK); // работаем с дисплеем
  tft.setCursor(97, 10);
  tft.println(recieved_data[0]);

  }
  digitalWrite(Radio_CS, LOW); // снова включаем радио

}
И если передавать массив не байт, а инт, то принципиально ведь ничего не изменится и на целостность данных не повлияет?