Конфликт 2 устройств SPI

Я хочу подключить Ethernet-модуль W5500 и модуль SD-карты к Arduino Uno с помощью SPI (конечно, с разными контактами CS). При отдельном подключении они работают нормально, но при подключении в одну цепь модуль Ethernet не получает правильный IP-адрес и всегда получает адрес 255.255.255.255. Для меня модуль Ethernet является вероятным виновником, поскольку модуль SD-карты работает без проблем, даже когда модуль Ethernet также подключен.

Пытался использовать Ethernet & Библиотеки Ethernet2, но без разницы. Пробовал вручную назначать IP-адрес, но это не сработает. Я даже установил контакты CS в HIGH в настройке перед вызовом SD.begin & Ethernet.begin(), чтобы оба компонента не «прослушивали» одновременно, но это все равно не работает. Как это исправить?

Вот скетч, над которым я работаю. Хотя он не использует модуль SD, но, как упоминалось выше, если модуль SD подключен к цепи, модуль Ethernet не получает неверный IP-адрес

#include <SPI.h>
#include <Ethernet2.h>

//IP-адрес ip(192, 168, 1, 22);


// MAC-адрес просто должен быть уникальным. Это должно работать
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

EthernetServer server(80);

void setup()
{

  pinMode(8, OUTPUT); // SD-модуль CS
  digitalWrite(8, HIGH);
  pinMode(10, OUTPUT); // Ethernet-модуль CS
  digitalWrite(10, HIGH);
  delay(1);

  Serial.begin(9600);
  Ethernet.begin(mac);
  server.begin();
  Serial.print("Server started on: ");
  Serial.println(Ethernet.localIP());
}

void loop()
{
  // прослушивание входящих клиентов
  EthernetClient client = server.available();
  if (client)
  {
    while (client.connected())
    {
      // отправляем стандартный HTTP-заголовок ответа
      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println();

      // отправить тело
      client.println("<html><body>");
      client.println("<h1>Arduino Server</h1>");
      client.print("<p>A0=");
      client.print(analogRead(0));
      client.println("</p>");
      client.print("<p>millis=");
      client.print(millis());
      client.println("</p>");
      client.println("</body></html>");
      client.stop();
    }
    delay(1);
  }
}

Еще один скетч со ссылкой на библиотеки SD и Ethernet

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

byte mac[] = { 0x00, 0xC3, 0xA2, 0xE6, 0x3D, 0x57 };
byte LED = 2;
char wServer[] = "media.wizards.com";
char wFile[] = "/images/magic/tcg/resources/rules/MagicCompRules_20140601.pdf";

EthernetClient myClient;

void setup() {
  //D53 на Arduino Mega должен быть выходом.
  pinMode(53, OUTPUT);

  pinMode(LED, OUTPUT);

  Serial.begin(9600);
  while (!Serial);

  Serial.print("Establishing network connection... ");

  if (Ethernet.begin(mac) == 0) {
    Serial.println("FAILED!");
    while (true) {
      digitalWrite(LED, HIGH);
      delay(500);
      digitalWrite(LED, LOW);
      delay(500);
    }
  } 
  else {
    Serial.println("OK!");
  }
}

void loop() {

  Serial.print("Connecting to ");
  Serial.print(wServer);
  Serial.print("... ");

  if (myClient.connect(wServer, 80) == 1) {
    Serial.println("OK!");

    myClient.print("GET ");
    myClient.print(wFile);
    myClient.println(" HTTP/1.0");
    myClient.print("Host: ");
    myClient.println(wServer);
    myClient.println();

    if (SD.begin(8)) {
      if (SD.exists("MAGIC.PDF"))
        SD.remove("MAGIC.PDF");

      Serial.print("Saving response... ");
      digitalWrite(LED, HIGH);

      File dd = SD.open("MAGIC.PDF", FILE_WRITE);

      char lc;
      while (myClient.connected()) {
        if (myClient.available()) {
          char nc = myClient.read();
          if ((lc == 10) && (nc == 13)) {
            while (myClient.available() == 0);
            myClient.read();
            break;
          }
          else
            lc = nc;
        }
      }

      while (myClient.connected()) {
        if (myClient.available() > 0) {
          dd.write(myClient.read());
        }
      }

      dd.close();
      delay(500);
      Serial.println("OK");
      digitalWrite(LED, LOW);
    }
    else
      Serial.println("No SD card detected!");

    myClient.stop();
  } 
  else
    Serial.println("FAILED!");

  delay(3600000);
  asm volatile(" jmp 0");

, 👍0

Обсуждение

Где вы сказали библиотеке SD и библиотеке Ethernet, какую CS они должны использовать?, @theSealion

В дополнение к @theSealion очень актуальный вопрос. Эта [статья](https://www.pjrc.com/better-spi-bus-design-in-3-steps/) должна помочь вам устранить неполадки и сузить круг причин., @hcheung

[ethernet2.h](https://github.com/adafruit/Ethernet2) устарел., @hcheung

ethernet2 по умолчанию использует контакт 10 в качестве cs (https://github.com/adafruit/Ethernet2/blob/master/src/utility/w5500.h#L133), однако ваш код не имеет ссылки на библиотеку SD-карт или инициализацию SD Card., @hcheung

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

@theSealion, библиотека Ethernet, по умолчанию использует контакт 10 в качестве cspin, поэтому нет необходимости упоминать об этом. Как я упоминал в своем исходном посте, сохранение в цепи как модуля SD-карты, так и модуля Ethernet вызывает проблему. Неважно, есть в скетче ссылка на библиотеку SD или нет. Поскольку в моей схеме модуль sd имеет контакт 8 как CSpin, и я поднял его, чтобы избежать конфликта, но это не помогает., @Zaffresky

@Zaffresky, чем я бы рекомендовал начать смотреть на оборудование. Возьмите вольтметр и посмотрите на линии CS и SPI, когда микроконтроллер находится в состоянии сброса и когда ваш скетч работает. Еще лучше было бы осциллографом смотреть сигнал., @theSealion


1 ответ


3

У меня была такая же проблема с модулем SD-карты.

Я не очень хорошо разбираюсь во всех деталях, но это связано с тем, что большинство модулей SD-карт (простых) не имеют функции трех состояний, то есть они не могут работать с несколькими устройствами SPI на одной шине.

К сожалению, у Arduino есть только одно соединение SPI, но есть решения:

  • Существуют буферы с тремя состояниями, которые вы можете использовать (где-то в диапазоне CD или 74HC). См. комментарий hcheung: используйте, например, буфер с тремя состояниями 74AHC125 MISO.
  • Однако другим решением является использование, например, защитного экрана SD-карты, например https://boutique.semageek.com/en/1445-sd-storage-shield-with-rtc-clock-for-arduino.html

,

Я думаю, вы имеете в виду [74AHC125](https://cdn-shop.adafruit.com/datasheets/74AHC125.pdf) для использования буфера с тремя состояниями MISO., @hcheung

@hcheung да, спасибо ... добавлю в ответ, @Michel Keijzers

Проблема с SD-картами заключается в том, что SD-карта не соответствует строго стандартам протокола SPI. Вывод CS не приводит к изоляции SD-карты от шины, как это должно быть, и есть определенные операции, которые вы выполняете с SD-картой через шину SPI, когда вывод CS удерживается в высоком состоянии., @Majenko

Также важен порядок инициализации. Вы должны запустить SD-карту перед любым другим устройством SPI, чтобы убедиться, что каждое устройство на шине является SPI, поскольку SD-карта по умолчанию работает в режиме SDIO, и это может мешать остальной части шины., @Majenko

@Majenko, прав ли я, что буфер с тремя состояниями, такой как 74AHC125, решит проблему с выводом CS?, @Michel Keijzers

Это, безусловно, помогает делу, да. Когда SD изолирован от шины, то, что бы он ни делал, он не может мешать остальной части шины., @Majenko

Лично я никогда не делю шину SPI с чем-либо еще при использовании SD-карты (но тогда я использую PIC32 с несколькими шинами SPI). При необходимости вы всегда можете использовать SPI для других устройств, которым не нужна высокая скорость., @Majenko

@Majenko приятно знать, спасибо ... давно не использовал SD-карту, но обнаружил проблему, когда начал работать с Arduino, честно говоря, никогда не пробовал буфер (так как я просто пробовал много вещей)., @Michel Keijzers

@Majenko Также одной из причин использования STM32 является то, что у них действительно больше функций (например, больше SPI и особенно больше SRAM)., @Michel Keijzers

@MichelKeijzers Мех ... если вам нравится ARM, конечно ... Дайте мне MIPS в любой день;), @Majenko

@Majenko, можете ли вы привести пример микроконтроллеров MIPS? (или я что-то пропустил), @Michel Keijzers

@MichelKeijzers PIC32. Это все, что я использую, если мне не нужно использовать что-то еще из-за требований клиента., @Majenko

@Majenko как-то это на самом деле не рекламируется или около того ... Я имею в виду, что я проверил Arduino и обнаружил, что он слишком ограничивает то, что я хотел (изучение микроконтроллеров), и наиболее «очевидные» ссылки, где STM32 (F1). Так что я не знаю, насколько хорош/плох PIC32 (вероятно, хорош, поскольку им пользуются профессионалы). Но я немного сомневаюсь, чтобы перейти (снова) на другую архитектуру., @Michel Keijzers

Хе. Преимущество PIC32 в том, что он получает от меня наилучшую аппаратную/программную поддержку;) chipKIT — это вариант API Arduino для PIC32, хотя он немного отстает по некоторым функциям API., @Majenko

@Majenko Я проверю это (потому что мне любопытно)., @Michel Keijzers

@MichelKeijzers Спасибо за информацию, но мне интересно, использует ли экран SD-карты также шину SPI? Если да, то чем он будет отличаться от использования модуля SD-карты?, @Zaffresky

@Majenko Я ничего не знаю об этом буфере с тремя состояниями, но прочитаю о нем больше. Также необходимо сначала заказать микросхему 74AHC125, чтобы протестировать ее., @Zaffresky

@Majenko Я пытался инициировать SD-карту до запуска Ethernet, но все равно не получается. Я предполагаю, что это скорее аппаратная проблема, и проблема с буфером с тремя состояниями, вероятно, исправит это. Что меня действительно удивляет, так это то, что даже если я подтяну CSpin SD-карты к высокому уровню на протяжении всего скетча, модуль Ethernet не сможет получить правильный IP-адрес, поэтому поддержание его CS-контакта на высоком уровне не имеет никакого эффекта?, @Zaffresky