Uno + nrf24l01 + MicroSD module: конфликт по SPI

Goshman
Offline
Зарегистрирован: 28.05.2016

Добрый день!

Аналогичная тема поднималась про мегу, но там все зашло в тупик.

Имеется связка Uno + nrf24l01 + MicroSD module.

Вот ссылка на схемотехнику модуля: http://www.dfrobot.com/image/data/DFR0229/MicroSD%20ModuleV1.0_Sch.pdf

По отдельности все работает. Но, стоит установить в слот SD карту, как nrf24l01 затыкается. Карта при этом нормально инициализируется.

Ниже проверочный код:

#include <SPI.h>
#include <SdFat.h>

#include <RF24.h>

// пины радиомодуля
#define CE_PIN 3
#define CSN_PIN 2

// пин карты
#define SD_CARD_PIN A1

typedef unsigned char uchar;

const uint64_t pipe = 0xE8E8F0F0E1LL;

// структура приемника (внешний датчик шлет посылки в таком формате)
struct  {
  uchar addr;           // +1 = 1
  uchar info;           // +1 = 2
  float param1;         // +4 = 6
  float param2;         // +4 = 10
  float param3;         // +4 = 14
  float param4;         // +4 = 18
  float param5;         // +4 = 22
  float param6;         // +4 = 26
  uchar err;            // +1 = 27
  uchar rsrv1;          // +1 = 28
  unsigned int  rsrv2;  // +2 = 30
  unsigned int  rsrv3;  // +2 = 32
} data_packet;

RF24 radio(CE_PIN, CSN_PIN);

// File system object.
SdFat sd;

void setup() {
  delay(1000);

// на всякий случай настраиваем пины, хотя библиотеки сами все делать умеют
  pinMode(CE_PIN, OUTPUT);
  pinMode(CSN_PIN, OUTPUT);
  pinMode(SCK, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SD_CARD_PIN, OUTPUT);

  delay(50);

  Serial.begin(115200);
  Serial.println("Start");

  radio.begin();                      // Включение модуля;
  radio.setAutoAck(true);             // Не ждем подтверждения приема
  radio.setChannel(76);               // Установка канала вещания;
  radio.setRetries(15, 15);           // Установка интервала и количества попыток "дозвона" до приемника;
  radio.setDataRate(RF24_250KBPS);    // Установка минимальной скорости;
  radio.setPALevel(RF24_PA_MAX);      // Установка максимальной мощности;
  radio.openReadingPipe(1, pipe);     // Активация данных для приема
  radio.startListening();             // Слушаем эфир

// лишнее, но мало ли
  digitalWrite(CSN_PIN, HIGH);
  delay(50);

  uint32_t t = millis();
  if (!sd.cardBegin(SD_CARD_PIN, SPI_HALF_SPEED)) {
    Serial.println("Card failed");
  } else  {
    t = millis() - t;
    Serial.print("Card init time: ");
    Serial.print(t);
    Serial.println("ms");
  }

// лишнее, но мало ли
  digitalWrite(SD_CARD_PIN, HIGH);
  delay(50);
}

void loop() {
  if (radio.available()) {  // Что-то пришло
    radio.read(&data_packet, sizeof(data_packet));  // Читаем данные
    Serial.print(" T1 = ");
    Serial.print(data_packet.param1, 1);
    Serial.print("C T2 = ");
    Serial.print(data_packet.param2, 1);
    Serial.print("C Us = ");
    Serial.print(data_packet.param3, 2);
    Serial.print("V U1 = ");
    Serial.print(data_packet.param4, 2);
    Serial.print("V Tint = ");
    Serial.print(data_packet.param5, 1);
    Serial.println("C");
  }

  if (millis() % 1000 == 0) {
    delay(1); // от повтороного срабатывания
    Serial.println("next second");
  }
}

Пробовал подтягивать выводы MISO и пины выбора устройств резисторами к 5В (правда номинал великоват 50 кОм) - ничего не поменялось.

Подскажите куда копать, плис.

a5021
Offline
Зарегистрирован: 07.07.2013

SPI может использоваться либо одним устройством, либо другим, но не обеими одновременно.

Goshman
Offline
Зарегистрирован: 28.05.2016

a5021 пишет:

SPI может использоваться либо одним устройством, либо другим, но не обеими одновременно.

Я это прекрасно понимаю. Но у меня в коде как раз все раздельно и используется. К карте я вообще обращаюсь только при ее инциализации. В дальнейшем идет опрос только радиомодуля. Чипселекты у карты и радиомодуля разные.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А по вроемени их развести никак нельзя?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну как же, в 61 строке Вы включили слушание, а в 68 лезете к карте. Во время слушания.

Можно ли по логике задачи развести так, чтобы в каждый момент времени работал кто-то один. Если можно. то и сделайте. А нельзя - переводите кого-нибудь в софт-SPI

Goshman
Offline
Зарегистрирован: 28.05.2016

ЕвгенийП пишет:

А по вроемени их развести никак нельзя?

Так я там даже задержки на 50 мсек воткнул между инициализацией радиомодуля и SD-карты.

После инициализации карты я к ней вообще больше не обращаюсь. Только радиомодуль в loop() опрашиваю.

a5021
Offline
Зарегистрирован: 07.07.2013

Вот и выясните, зачем карта лезет не в свое время.

Goshman
Offline
Зарегистрирован: 28.05.2016

ЕвгенийП пишет:

Ну как же, в 61 строке Вы включили слушание, а в 68 лезете к карте. Во время слушания.

Можно ли по логике задачи развести так, чтобы в каждый момент времени работал кто-то один. Если можно. то и сделайте. А нельзя - переводите кого-нибудь в софт-SPI

Так я радиомодуль в режим прослушки включил и все. Чипселект возводится у него в "1". Он слушает же независисмо от состояния шины SPI. Только когда я вызываю radio.available(), контроллер вновь к нему обращается по SPI. Или я себе это не правильно представляю?

К тому же карта инициализируется уже после радиомодуля. И инициализация проходит успешно.

 

Goshman
Offline
Зарегистрирован: 28.05.2016

a5021 пишет:

Вот и выясните, зачем карта лезет не в свое время.

Осциллограф утверждает, что чипселект карты только на этапе ее инициализации падает в "0". В дальнейшем всегда в "1" возведен.

Дергается только чипселект карты при попытке ее опроса.

 

Goshman
Offline
Зарегистрирован: 28.05.2016

В общем все заработало.

А косяк был в том, что при инициализации портов на вывод они устанавливались "0". И конфликт был на этапе инициализации радиомодуля. А не при опросе модуля в дальнейшем.

Всем спасибо!