Двухстороннее общение двух UNO через SPI

Тема в разделе "Проводная и беспроводная связь", создана пользователем Daemon2017, 15 янв 2017.

  1. Daemon2017

    Daemon2017 Нерд

    Здравствуйте!

    Задумка такая: есть две Уны, первая Уна (Мастер) отправляет второй (Слейву) 0. Слейв это число инкрементирует и отправляет обратно Мастеру. Мастер снова инкрементирует число и отправляет Слейву.

    Изучил вот эти материалы, но так и не понял, как это сделать:
    http://www.gammon.com.au/spi
    https://arduino.stackexchange.com/questions/16348/how-do-you-use-spi-on-an-arduino

    Код (C++):
    #include <SPI.h>

    int data = 0;
    volatile bool process_it;

    void setup (void)
    {
      Serial.begin (115200);

      //Чтобы слать Мастеру
      pinMode (MISO, OUTPUT);

      //Подготовка для работы с прерываниями
      process_it = false;

      //Подключаем прерывания
      SPI.attachInterrupt();

      //Занижаем скорость отправки за счет предделителя
      SPI.setClockDivider(SPI_CLOCK_DIV8);
    }

    void loop (void)
    {
      dataSend();

      dataReceive();
    }

    void dataSend()
    {
      //Делаем Слейв-Селект высокоуровневым
      digitalWrite(SS, HIGH);

      //Включаем СПИ (режим отправки)
      SPI.begin ();

      char c = data;

      //Делаем Слейв-Селеект низкоуровневым - даем Слейву понять, что сейчас ему будут слать что-то
      digitalWrite(SS, LOW);

      //Отсылаем пробную строку
      SPI.transfer (c);

      //Делаем Слейв-Селект высокоуровневым
      digitalWrite(SS, HIGH);

      Serial.println ("Что-то отправилось");

      //Спим
      delay (1000);
    }

    ISR (SPI_STC_vect)
    {
      //Ловим байт из СПИ
      byte c = SPDR;

      //Увеличиваем на единицу
      data = c++;

      process_it = true;
    }

    void dataReceive()
    {
      //Включаем СПИ (режим приема)
      SPCR |= bit (SPE);

      //Если сработало прерывание - к нам шлют что-то
      if (process_it)
      {
        Serial.println ("Что-то пришло");

        process_it = false;
      }
    }
    Буду очень благодарен, если поможете исправить мой код! Пример рабочего кода тоже будет очень кстати :)
     
  2. rkit

    rkit Гуру

    Вы в одном скетче и слейв и мастер реализуете. Мастер получает ответ в возращаемом значении функции SPI.transfer, если мне память не изменяет.
     
    Daemon2017 нравится это.
  3. mcureenab

    mcureenab Гуру

    Посмотрите по первой ссылке пост "How to get a response from a slave". Ссылка:
    http://www.gammon.com.au/spi

    Скетч Master (example) заливаем на Master плату. Скетч Slave (example) заливаем на Slave плату.
    Master плату подключаем к ПК по USB. Открываем com порт и смотрим сообщения от платы.
     
  4. Daemon2017

    Daemon2017 Нерд

    Т.е. прием у мастера и слейва исполняется по-разному? А отправка одинаковая, или тоже разная?
    Текущий код подойдет для слейв-платы, а для мастер-платы его нужно переписать так, как Вы сказали - верно?
     
  5. Daemon2017

    Daemon2017 Нерд

    Как я вижу из кода - тут мастер только отправляет, а слейв - только принимает. А я пытаюсь сделать так, чтобы и мастер, и слейв умели и отправлять, и принимать.
     
  6. rkit

    rkit Гуру

    Текущий код никуда не подойдет. Вот рабочий пример пары приемник-передатчик https://forum.arduino.cc/index.php?topic=184527.0
     
  7. mcureenab

    mcureenab Гуру

    Вы или не тот пост в теме смотрите, или не поняли листинги.
    Ищите пост "How to get a response from a slave" на сиранице:
    http://www.gammon.com.au/spi

    Там Master отправляет на Slave несколько чисел. Slave прибавляет или вычитает из них свои числа и отправляет назад.

    Master довольно просто устроен. Передача и прием проходят одним вызовом функции
    Код (C++):
    response = SPI.transfer (request);
    В Slave уходит байт request. И от Slave возвращается байт response.
    На стороне Slave код сложнее. Требуется обработка прерывания.