Как отправить строку с подчиненного устройства Arduino с помощью SPI?

У меня есть Arduino Uno, выступающий в качестве ведущего, а 3 Arduino Nano выступают в качестве подчиненных.

Глядя на этот пример: http://www.gammon.com.au/forum/?id=10892, он говорит мне, как отправить строку от ведущего устройства к ведомому, но я не видел ни одного примера отправки строки от ведомого устройства к ведущему устройству. Мне удалось успешно отправлять и получать цифры на / от ведущего и ведомого устройств, но я не мог понять, как отправлять строки от ведомого устройства к ведущему, основываясь на примере.

Насколько я понимаю, связь SPI может отправлять информацию только байт за байтом, поэтому должен ли я преобразовать свою строку в байтовый формат, прежде чем помещать ее в переменную SPDR, чтобы ее можно было отправить обратно ведущему?

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

Заранее благодарю.

, 👍2


4 ответа


0

Строка - это только массив символов, заканчивающийся символом \0. Но вы также можете получить к нему доступ в виде массива байтов, заканчивающихся на 0. И отправляйте их по одному байту, пока он не достигнет 0 (отправьте его тоже). На master вы сохраняете его в достаточно длинный массив символов (работайте с ним как с байтами), включая конечный ноль и бинго, у вас есть переданная строка символов :)

,

0

Как мне отправить строку из подчиненного устройства Arduino с помощью SPI?

В зависимости от вашего определения строки это будет выглядеть примерно так (для master):

String message = "....";
SPI.transfer(message.c_str(), message.length() + 1);

или

char message[MESSAGE_MAX];
strcpy(message, ....);
SPI.transfer(message, strlen(message) + 1);

Для ведомого устройства SPI это значение необходимо будет преобразовать либо в ISR SPI, либо в busy - дождитесь выбора чипа, а затем передачи.

Ваше здоровье!

,

3

Помните, что мастер управляет передачей (обеспечивает синхронизацию), как бы это ни было сделано. Например:


Мастер

// мастер

#include <SPI.h>

void setup (void)
{
  Serial.begin (115200);
  Serial.println ("Starting");

  digitalWrite(SS, HIGH);  // убедитесь, что SS остается высоким на данный момент

  // Перевести контакты SCK, MOSI, SS в режим вывода
  // также переведите SCK, MOSI в НИЗКОЕ состояние и SS в ВЫСОКОЕ состояние.
  // Затем переведите оборудование SPI в режим Master и включите SPI
  SPI.begin ();

  // Немного замедлите работу мастера
  SPI.setClockDivider(SPI_CLOCK_DIV8);

}  // завершение настройки

void loop (void)
{
  char buf [20];

  // включить подчиненный выбор
  digitalWrite(SS, LOW);    
  SPI.transfer (1);   // инициировать передачу
  for (int pos = 0; pos < sizeof (buf) - 1; pos++)
    {
    delayMicroseconds (15);
    buf [pos] = SPI.transfer (0);
    if (buf [pos] == 0)
      {
      break;
      }
    }

  buf [sizeof (buf) - 1] = 0;  // обеспечить завершение null

  // отключить подчиненный Выбор
  digitalWrite(SS, HIGH);

  Serial.print ("We received: ");
  Serial.println (buf);

  delay (1000);  // задержка в 1 секунду 
}  // конец цикла

В этом примере ведущий инициирует передачу, отправляя 0x01 ведомому устройству. Затем он возвращает байты обратно до 0x00 байта (означающего конец строки). Задержка в микросекундах существует для того, чтобы дать ведомому устройству время для ответа.


Подчинение

// Ведомый

void setup (void)
{

  // должны быть отправлены на master in, * slave out*
  pinMode(MISO, OUTPUT);

  // включить SPI в подчиненном режиме
  SPCR |= bit(SPE);

  // включить прерывания
  SPCR |= bit(SPIE);
}  // завершение настройки

volatile char buf [20] = "Hello, world!";
volatile int pos;
volatile bool active;

// Процедура прерывания SPI
ISR (SPI_STC_vect)
{
  byte c = SPDR;

  if (c == 1)  // запуск новой последовательности?
    {
    active = true;
    pos = 0;
    SPDR = buf [pos++];   // отправить
    return;
    }

  if (!active)
    {
    SPDR = 0;
    return;
    }

  SPDR = buf [pos];
  if (buf [pos] == 0 || ++pos >= sizeof (buf))
    active = false;
}  // завершение процедуры обслуживания прерываний (ISR) SPI_STC_vect

void loop (void)
{

}  // конец цикла

Подчиненный делает все внутри ISR. Поступление байта 0x01 приводит к сбросу его "указателя" на начало буфера. После этого он отвечает другим байтом из буфера, пока не достигнет конечного байта 0x00.

,

1

В части sender я использую метод преобразования строки в массив символов перед отправкой получателю.

Мастер

#include <SPI.h>
const int size_arr = 50;  // определяет размер массива (должен быть меньше размера подчиненного устройства)
char buf[size_arr]; // определяет массив символов, используемый для преобразования из строки для отправки подчиненному устройству
String main_dat = "jack,12,47,123,8888"; // реальные строковые данные

void setup() {

pinMode(SS, OUTPUT);
digitalWrite(SS, HIGH);
SPI.begin();
SPI.setClockDivider(SPI_CLOCK_DIV4);

}
void loop() {
main_dat.toCharArray(buf, size_arr); // преобразовать строковые данные в массив символов
Spi_tranmis(buf); // задержка отправки массива символов
delay(500);

}

void send_spi(byte pram) {

  digitalWrite(SS, LOW);
  SPI.transfer(pram);
  digitalWrite(SS, HIGH);
  delayMicroseconds(50);

}

void Spi_tranmis(char buf[]) {
for (int i = 0 ; i < size_arr ; i ++) {
  send_spi(buf[i]);
}

send_spi('\n');
}

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

Подчинение

#include <SPI.h>


const int size_arr = 51; // определяет размер массива (должен быть больше размера основного массива)
char buf[size_arr]; // массив символов, используемый для получения от master

volatile byte pos = 0;
volatile boolean process = false;

String msg; // реальные данные

void setup() {
   Serial.begin(9600);
   Serial.println("test");
   pinMode(MISO, OUTPUT);
   digitalWrite(MISO, LOW);
   SPCR |= _BV(SPE);
   SPCR |= _BV(SPIE);

 }

 ISR(SPI_STC_vect) {
  char c = SPDR;

  if (pos < sizeof buf) {
    if (c == '\n') {
      process = true;
    }
     else {
      buf[pos++] = c;
     }
   }
 }


void loop() {
  recvHandle();

}


void recvHandle() {
  if (process) {  // когда SPI доступен
    msg = String(buf);   // преобразовать массив символов в строку
    Serial.println(msg);
    process = false;
    pos = 0;
  }

}

  • Вы должны определить размер массива символов в получателе больше, чем в отправителе *
,