Мастер не получает правильные значения в канале SPI мастер/подчиненный

Я уже 3 недели пытаюсь найти решение своей проблемы, связанной с коммуникацией SPI.

Итак, мне нужно установить связь SPI между двумя устройствами Arduino: например, ведущее устройство отправляет букву «a» ведомому устройству; ведомое устройство получает ее и выполняет некоторую обработку. В моем случае оно должно установить один из своих 8 выводов на высокий уровень, затем считать все выводы и отправить отчет обратно ведущему устройству.

Та часть, где мастер отправляет 'a', а подчиненный его обрабатывает, работает нормально, но мастер, похоже, не получает правильные значения. Вместо этого он всегда получает 0.

Вот код:


Раб:

#include <SPI.h>;

volatile byte command = 0;
byte ett =8; //кол-во тестовых точек
byte motif= 0b000000000 ; //инициация моей переменной, которая будет содержать состояния моих пинов
byte end[8] = { 2,3,4,5,6,7,8,9}; //массив, содержащий контакты

void setup (void) {
  Serial.begin (9600);
  // нужно отправить на главный вход, *подчиненный выход*
  pinMode(MISO, OUTPUT);
  // включаем SPI в подчиненном режиме
  SPCR |= _BV(SPE);
  // включаем прерывания
  SPCR |= _BV(SPIE);
}  // конец настройки

// Процедура прерывания SPI
ISR (SPI_STC_vect) {
  byte c = SPDR;
  switch (command) {
    /////////////Предательство раба/////////////
    // нет команды? тогда это команда
  case 0:
    command = c;
    SPDR = 0;
    break;

  case 'z': ////case 'z", установите все контакты на ВХОД
    for (int i=0; i<8; i++){
      pinMode (end[i], INPUT);
    }
    break;

  case 'a': // //if 'a' : Установить один вывод на высокий уровень, затем считать состояние всех выводов, чтобы проверить, нет ли обрыва цепи или короткого замыкания
    for (int j = 0; j < ett; j++) {
      pinMode(end[j], INPUT);   // установить все контакты как INPUT
    }
    motif = 0;
    pinMode(end[0], OUTPUT);  // Установить один вывод как ВЫХОД
    digitalWrite(end[0], HIGH); // Устанавливаем выходной контакт в положение HIGH
    Serial.println();
    Serial.print(" ");  
    for (int k = 0; k < ett ; k++) { // сканирование
      if (digitalRead(end[k]) == HIGH) {
        // если вывод == HIGH, добавляем '1' к моему вектору
        Serial.print("| ");
        motif = motif + 1; // +1
      } else { // если вывод == НИЗКИЙ
        Serial.print(". ");
      }
      motif = motif << 1; // сдвиг влево
    }
    Serial.print(" -MOTIF LU= ");
    Serial.print(motif, BIN); 
    SPDR = byte (motif); //SPDR — это регистр данных SPI: он содержит данные, которые будут отправлены ведущему устройству
    Serial.print(" ");
    break;
  }
}

void loop (void) {
  // если SPI не активен, очистить текущую команду
  if (digitalRead (SS) == HIGH)
    command = 0;
}

Мастер:

#include <SPI.h>

byte CS0=10;
byte CS1=9;

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 (1000);
  return a;
} // конец transferAndWait
///traitement au niveau du maitre

void loop (void)  {
  byte esclave0_testpin0;
  /////////////Установите вывод первого ведомого устройства на Высокий, затем считайте все выводы
  digitalWrite (CS0,LOW); //активируем ведомое устройство
  transferAndWait ('a'); // устанавливаем вывод первого ведомого устройства на высокий уровень
  esclave0_testpin0 = transferAndWait ('z'); //считываем все пины ведомого устройства и сообщаем об этом в переменной esclave0_testpin0
  digitalWrite (CS0,HIGH); //отключить ведомое устройство
  Serial.println ("test_0");
  Serial.println (esclave0_testpin0, BIN);
  delay (1000);  // задержка 1 секунда
}  // конец цикла

, 👍2


1 ответ


1

В подчиненном команда всегда равна 0. Вы, вероятно, имели в виду:

void loop(void) {
    command = (digitalRead(SS) == HIGH ? 0 : 1);
}

и в ISR:

ISR (SPI_STC_vect) {

    byte input = SPDR;
    byte output = 0;

    if (command) {

        switch (input) {

            case 'a':
                //...
                break;

            case 'z':
                //...
                break;
        }
    }

     // send data back
     SPDR = output;
}

В качестве лучшей практики избегайте реализации логики в ISR и используйте глобальные volatile переменные для передачи изменений состояния в код в основном цикле. Вероятно, вам придется реализовать кольцевой буфер для приема и отправки на шину SPI...

,