SPI в режиме SLAVE

x-nikolas
Offline
Зарегистрирован: 30.04.2017

Всем добрый день!

Возникла задача передать данные от Arduino Nano на Jetson TX2 по SPI. SPI на Jetson удалось запустить только в режиме мастер. Поэтому Arduino стал слэйвом. С помощью кода ниже удалось получить данные в обратную сторону (Jetson --> Arduino).

Вопрос: как передать данные от Arduino (SPI Slave)  в Jetson (SPI Master)? Насколько я понимаю, во время транзакции одновременно передаются данные и по MISO и по MOSI и мастер может принять данные от слэйва. Но всё, что ни пробовал, результата не дало. Вот код Ардуино:

#include <SPI.h>   
#define SPI_SS 10

void slaveSPI_Setup() 
{
   SPI.setDataMode(SPI_MODE0); //не влияет на работу
   SPI.setBitOrder(MSBFIRST); //не влияет на работу
   SPI.setClockDivider(SPI_CLOCK_DIV4); //не влияет на работу
   //pinMode(MISO, OUTPUT); //при добавлении приводит к искажению принятых данных
   //pinMode(SPI_SS, INPUT); //не влияет на работу
   
   SPCR |= _BV(SPE);       // включение SPI в режиме SLAVE
}   
/// Функция для чтения данных
unsigned char slaveSPI_read() 
{
   while(!(SPSR & (1<<SPIF)));
   return SPDR; 
}

void setup() 
{
   Serial.begin(112500);
   slaveSPI_Setup(); 
}   

void loop() 
{
   unsigned char ch = slaveSPI_read();
   Serial.println(ch);
} 

Интересно, что настройки "SPI.set..." никак не влияют на работу, если их закомментить. А вот если раскомментить "pinMode(MISO, OUTPUT)" - начинаю принимать не те числа, что отправляю, хотя в описании SPI везде написано, что в режиме SLAVE MISO нужно обязательно определить как OUTPUT.

В общем, прошу подсказать, что нужно добавить в этот код, чтобы Arduino ещё и отправлял данные мастеру.

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

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

Но если Вам это трудно понимать, поищите библиотеку SPI которая понимает режим slave, их много и они легко ищутся.

x-nikolas
Offline
Зарегистрирован: 30.04.2017

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

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

Спасибо! Немного подредактировал под свою задачу Ваш код (по сути убрал лишнее, чтобы проще было воспринимать). Я убрал всю обработку строк, т.к. принимаю от мастера число (и число же хочу отправить мастеру обратно) . Вот, что получилось:

#include <SPI.h>
 
void setup(void) {
    Serial.begin(57600);
    Serial.println("I am slave!");
    //  Инициализируем SPI при SS в режиме INPUT (получаем slave режим)
    //  и вручную выставляем правильные направления пинов
    //
    SPI.begin();
    SPI.beginTransaction(SPISettings());
    pinMode(MISO, OUTPUT);
    pinMode(MOSI, INPUT);
    pinMode(SCK, INPUT);
    pinMode(SS, INPUT);
    SPI.attachInterrupt();  // Включаем прерывания
}

static byte c=0;

ISR(SPI_STC_vect) {

    с=SPDR; 
    Serial.println(c);
    SPDR=0x0A;
    }

void loop(void) {
}

С помощью такой программы я отлично принимаю от Master устройства биты, но в ответ Slave устройство ничего не передаёт. Проверил это в том числе осциллографом - на выводе MISO пусто (а точнее какой-то один импульс, вне зависимости от того, что я присваиваю SPDR).

Так вот мой изначальный вопрос вот в чём: как сделать так, чтобы Slave начал отвечать мастеру?

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

x-nikolas пишет:
как сделать так, чтобы Slave начал отвечать мастеру?

1.
запустите мою программу прямо как она есть - безо всяких переделок и убедитесь в том, что там слейв нормально отвечает и мастер принимает ответы

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

3.
Таким образом Вы поймёте где Вы её ломаете, локализуете до мельчайшего шага: вот так ещё работало, а вот тут дунул и ... 

4.
думаю, Вы тогда сумеете победить, а не сумеете - выкладывайте два скетча "ещё работающий" и "уже не работающий" разница между которыми минимальна - посмотрим что там.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

ТС разберись, что такое SPI и тогда поймёшь как это реализовать.
Подскажу , ключевое слово "сдвиговый регистр"

https://youtu.be/85Lhi_824ks

x-nikolas
Offline
Зарегистрирован: 30.04.2017

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

1.

запустите мою программу прямо как она есть - безо всяких переделок и убедитесь в том, что там слейв нормально отвечает и мастер принимает ответы

Согласен. Прошу для чистоты эксперимента поделиться библиотекой "Printing.h", не получилось её найти.

x-nikolas
Offline
Зарегистрирован: 30.04.2017

Kakmyc пишет:
ТС разберись, что такое SPI и тогда поймёшь как это реализовать. Подскажу , ключевое слово "сдвиговый регистр" https://youtu.be/85Lhi_824ks

Kakmyc, спасибо, видео очень хорошее. Хотя, это я уже знал.

Если использовать вот такой простой код (см. ниже), то SLAVE отвечает мастеру. Казалось бы - работает, НО! Примерно 5-10% посылок приходят не верными (например, вместо "10" приходит "5" - похоже на сдвиг посылки на 1 бит). Пробовал пару Arduino-Arduino, Arduino (slave)-Jetson(master) - результат тот же. Причём периодичность "кривых" посылок не закономерная.

void setup() {
    Serial.begin(112500);
    pinMode(MISO, OUTPUT);   //MISO как выход - это понятно
    SPCR |= (1<<SPE);   // включаем SPI как SLAVE
}
 
void loop() {
SPDR=0x0A;  // пишем в регистр, что хотим передать
                       // если делать это в прерывании - эффект тот же
}

Ни в одном описании на SPI не удалось найти информации, что я делаю не так, и во всех примерах код примерно такой же.

Судя по Вашему комментарию, Вы уже очень хорошо разобрались в вопросе касательно SPI. Можете подсказать, что не так с моим кодом? В виде подсказки с ключевым словом, или, может, просто скажете, что я делаю не так.

test1
Offline
Зарегистрирован: 06.01.2020

Разве прежде чем писать в регистр не надо проверять готовность SPI? Там, в регистре статуса вроде какой-то битик везде ещё проверяют.

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

x-nikolas пишет:

Согласен. Прошу для чистоты эксперимента поделиться библиотекой "Printing.h", не получилось её найти.

https://github.com/elilitko/ArduinoStuff/tree/master/Printing

x-nikolas
Offline
Зарегистрирован: 30.04.2017

test1 пишет:

Разве прежде чем писать в регистр не надо проверять готовность SPI? Там, в регистре статуса вроде какой-то битик везде ещё проверяют.

Перед чтением - да, обязательно. Но при ответе слэйва это не помогает. Странно именно то, что в целом-то работает, если не считать процент кривых посылок. А как эти кривые посылки лечить - пока не понятно.

x-nikolas
Offline
Зарегистрирован: 30.04.2017

Вопрос решён! Большое спасибо за помощь. Ваша программа так же не стабильно работала, пока я не объединил GND контроллеров. Раньше я не встречал на то прямых указаний. В общем, ещё раз спасибо!

P.S.: ранее я пробовал объединить пины GND у Ардуино и у Jetson, но у меня в тот момент почему-то сразу погас экран монитора, подсоединённого к Jetson, и я отказался от этой идеи. В этот раз объединил - и всё норм. Ура.

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

x-nikolas пишет:
пока я не объединил GND контроллеров

Да, уж, блин! "Уж", если чё, - это зверь такой.

Леонид Филатов как-то писал:

Я битый час вертел в руках солонку,
И вдруг меня пронзило: «В этом — соль!»

:-)

sadman41
Offline
Зарегистрирован: 19.10.2016

Какая устойчивая система. Нет одного провода из четырех, а процент ошибок всего лишь 10%.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

x-nikolas пишет:

...пока я не объединил GND контроллеров. Раньше я не встречал на то прямых указаний.

А в каком классе ты учишься?

В любом случае, если ты хочешь заниматься Ардуино, тебе нужно прочитать учебник физики за 8 класс. Без этого - никак.

 

PS. Для ученика средних/младших классов у тебя очень хороший русский.

x-nikolas
Offline
Зарегистрирован: 30.04.2017

sadman41 пишет:
Какая устойчивая система. Нет одного провода из четырех, а процент ошибок всего лишь 10%.

Все 4 провода на месте, GND - пятый.

x-nikolas
Offline
Зарегистрирован: 30.04.2017

andriano пишет:

x-nikolas пишет:

...пока я не объединил GND контроллеров. Раньше я не встречал на то прямых указаний.

А в каком классе ты учишься?

В любом случае, если ты хочешь заниматься Ардуино, тебе нужно прочитать учебник физики за 8 класс. Без этого - никак.

PS. Для ученика средних/младших классов у тебя очень хороший русский.

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

Но, вижу, что многие тут предпочитают выражать надменность и собственную важность.

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

KPG
Offline
Зарегистрирован: 09.06.2019

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

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

Жалко, что для каких то таких ответов на вопрос не создан FAQ на форуме.

P.S. Посмотрел сколько созданных топиков в разделе Программирования - около 500! Карл.

Кто их будет просматривать и при таком дизайне поисковика на форуме.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

x-nikolas пишет:

Да, я мало работал с контроллерами, и могу не знать каких-то вещей, кому-то кажущихся элементарными.

Тот факт, что электрический ток может протекать только по замкнутой цепи, никакого отношения к специфики контроллеров отношения не имеет.

Цитата:

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

Спасибо за Ваше мнение, что мне лучше писать на форуме.

Но скажу честно, откровенная ложь меня всегда шокирует. Особенно в тех случаях, когда лжец в принципе не получает каких-либо "бонусов" от своей лжи. Возникает вопрос: "Зачем!?!"

 

PS. "-1" на Вашем сообщении - не мой. Делайте выводы.