Как отправить данные ads1115 через spi на master arduino

Я пытаюсь отправить данные ADS 1115, которые подключены к Arduino mega_1 через I2C, а arduino Mega_1 подключена к arduino Mega_0 через SPI. Arduino Mega_1 действует как ведомое устройство и отправляет данные ADS 1115 на ведущее устройство. Я думаю, что вся моя установка работает, но я хочу получить фактические данные ADS 1115 на мастере Arduino. Вот скриншоты результатов моего кода

мастер

#include <SPI.h>

void setup (void)
{
  Serial.begin (9600);
  Serial.println ();

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

  // Переводим выводы SCK, MOSI, SS в режим вывода
  // также переводим SCK, MOSI в состояние LOW, а SS в состояние HIGH.
  // Затем переведите оборудование SPI в режим Master и включите SPI.
  SPI.begin ();

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

}  // конец настройки

byte transferAndWait (const byte what)
{
  byte a = SPI.transfer (what);
  delayMicroseconds (20);
  return a;
} // конец передачи и ожидания

void loop (void)
{
byte a;

  // включить выбор ведомого
  digitalWrite(SS, LOW);    

  transferAndWait ('a');  // добавить команду
a=transferAndWait (0);


  // отключаем выбор ведомого
  digitalWrite(SS, HIGH);

  Serial.println ("results:");
  Serial.println (a);

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

подчиненный

#include <Wire.h>
#include <Adafruit_ADS1015.h>
int out_buf;
int adc0;

// объявления Adafruit_ADS1115; /* Используйте это для 16-битной версии */
Adafruit_ADS1015 ads;
// что делать с входящими данными
volatile byte command = 0;
void ss_falling ()
{
  command = 0;
} 
void setup (void)
{
 ads.begin();
 Serial.begin(9600);  
 //ads.startComparator_SingleEnded(0, 1000);
// нужно отправить на вход master, *slave на выход*
 pinMode(MISO, OUTPUT);

// включаем SPI в ведомом режиме
 SPCR |= _BV(SPE);

 // включаем прерывания
 SPCR |= _BV(SPIE);
 attachInterrupt (0, ss_falling, FALLING);

}

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

  switch (command)
  {
  // нет команды? тогда это команда
  case 0:
    command = c;
    SPDR = 0;
    break;

  // добавляем к входящему байту, возвращаем результат
  case 'a':
    SPDR = out_buf; // добавляем 15
    break;

  } // конец переключателя

}  // конец процедуры обслуживания прерывания (ISR) SPI_STC_vect


void loop (void)
{
adc0 = ads.readADC_SingleEnded(0);
Serial.print("AIN0: "); Serial.println(adc0);

out_buf=adc0;
// int buff = atoi(out_buf);
Serial.print("AIN1: "); Serial.println(out_buf);
delay(1000);
 }

я отправляю 1570, но на стороне мастера я получил 35. Я думаю, что данные ADS имеют 16 бит, т.е. 2 байта, а SPI получает только 1 байт за раз. Я застрял здесь, пожалуйста, помогите мне. Заранее спасибо

пример

, 👍0


2 ответа


Лучший ответ:

0

Моя проблема теперь решена, благодаря всемогущему. Я сделал несколько изменений в коде: 1. Преобразование полученных данных типа int из ADS в Char. 2. Сохранил его в массиве, чтобы сформировать строку.

Вот мой модифицированный подчиненный код:

#include <Wire.h>
#include <Adafruit_ADS1015.h>
Adafruit_ADS1015 ads;
void setup (void)
{
ads.begin();
 Serial.begin(9600);
  // нужно отправить на вход master, *slave на выход*
  pinMode(MISO, OUTPUT);

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

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

char buf[20];
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)
{
int adc0=0;
adc0 = ads.readADC_SingleEnded(0);
itoa(adc0,buf,10);
Serial.print("AIN1: "); Serial.println(buf);
delay(500);
}  // конец цикла

На стороне мастера

Мы получаем строку, отправляя одно фиктивное значение за раз. Вот модифицированный мастер-код:

#include <SPI.h>

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

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

  // Переводим выводы SCK, MOSI, SS в режим вывода
  // также переводим SCK, MOSI в состояние LOW, а SS в состояние HIGH.
  // Затем переведите оборудование 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;  // обеспечим завершающий нуль

  // отключаем выбор ведомого
  digitalWrite(SS, HIGH);

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

  delay (500); 
}  // конец цикла
,

0

Реализация подчиненного режима SPI немного сложнее, чем вы думаете. Самое важное, что нужно помнить, это то, что это не протокол типа «Дайте мне X» -> «Хорошо, вот X». На самом деле это протокол "Вот X" <=> "Вот Y".

То есть в тот момент, когда ведущий отправляет X подчиненному, подчиненный отправляет "Y" главному.

У вас это так: мастер отправляет «а» в качестве команды и отбрасывает то, что получает. Раб запоминает это «а» как «команду». Затем мастер отправляет 0 и запоминает, что получает. Ведомый получает этот 0 и думает: «А, я получил команду в прошлый раз, поэтому он должен захотеть значение» и ставит значение в очередь для отправки при следующей транзакции. Затем это отбрасывается, поскольку это происходит при отправке следующей «команды».

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

  • Когда SS падает, установите "счетчик байтов" на 0.
  • При получении байта проверьте "счетчик байтов":
    • Байт 0: если это "a", поместите первый байт значения в SPDR.
    • Байт 1: поместите второй байт значения в SPDR.
    • Байт 3: ничего не делать (или поместить 0 в SPDR)
  • Увеличить счетчик байтов

Таким образом, транзакция выглядит примерно так (1570 – это 0x622 в шестнадцатеричном формате, и я выбираю "little endian", поскольку AVR, естественно, использует обратный порядок байтов):

Master Sends        Slave Queues          Master Receives
'a'                 0x22                  Rubbish
0                   0x06                  0x22
0                   0x00                  0x06

'a'                 0x22                  0x00
0                   0x06                  0x22
0                   0x00                  0x06

Важно помнить, что ведущий получает то, что подчиненный поставил в очередь при следующей передаче.

,

Моя связь SPI работает нормально, потому что я также пробовал сложение и вычитание между ведущим и подчиненным, и результат был «ок»., @Alok Mishra

Если бы ваша spi-связь работала нормально, вы бы не просили нас о помощи..., @Majenko

чувак прочитал эти строки: «Я отправляю 1570, которые являются данными ads1115, но на стороне Master я получил 35, я думаю, что данные ADS имеют 16 бит, то есть 2 байта, а SPI получает только 1 байт за раз». SPI мне подходит .... я думаю, что чего-то не хватает, например, преобразования байтов в символы или разделения 16-битных данных adc на 8 бит, а затем отправки мастеру, это моя настоящая проблема., @Alok Mishra

35 не имеет никакого отношения к 1570. Самое близкое, что вы можете получить, это 34 (0x22). Исправление вашего кода так, как я указываю, не только устраняет беспорядок, который вы создали в системе-отправителе, но также устраняет проблему с 16-битной версией. О, и сделайте свой out_buf изменчивым. Также out_buf должен быть "захвачен" в момент, когда вы либо ставите в очередь первый байт, либо когда SS падает., @Majenko

я добавил еще два скриншота, на которых я отправляю 10, а в ответ получаю 20 "20 = 10 + 10", @Alok Mishra

Это чистая случайность, что *иногда* вы получаете результат, который *считаете* правильным. Это не так. Вы получаете *старые* результаты по *предыдущим* транзакциям, которые *никогда не отправлялись*., @Majenko

хорошо, если я делаю неправильно, то как правильно отправить рекламные данные мастеру arduino с помощью spi, @Alok Mishra

Как я подробно описал в своем ответе., @Majenko