Запуск передачи SPI с помощью прерывания в Arduino Due

У меня есть DDS, который управляется Arduino DUE, цикл() ожидает последовательных команд и на их основе вызывает ту или иную функцию, которая устанавливает частоту, фазу, амплитуду и т. д. DDS через SPI. В дополнение к этому я хочу иметь возможность использовать внешнее прерывание, запускаемое сигналом TTL, для сброса аккумулятора фазы DDS. Сброс фазы осуществляется записью в регистр SPI — resetPhase().

Каким-то образом функция resetPhase() запускается правильно, но как только я добавляю к ней SPI.transfer, связь SPI перестает работать вообще, не только через прерывания, но и функции, запускаемые через последовательные команды, перестают работать.

>

Есть ли способ заставить это работать?

SPISettings spiSettings = SPISettings(10000000, MSBFIRST, SPI_MODE0);

void setup()
{
    pinmode(chipSelect, OUTPUT);
    int syncPIN = digitalPinToInterrupt( interruptPin);
    SPI.usingInterrupt(syncPIN);
    attachInterrupt(syncPIN, resetPhase, RISING);
}


void resetPhase():
{
    SPI.beginTransaction(spiSettings);
    digitalWrite(chipSelect, LOW);
    SPI.transfer(controlRegister);
    digitalWrite(chipSelect, HIGH);
    SPI.endTransaction();
}

, 👍0

Обсуждение

Вероятно, при передаче SPI используется прерывание, которое не может сработать, поскольку вы уже находитесь в прерывании. Вы должны иметь операции SPI вне прерывания и просто обновлять некоторые переменные и устанавливать флаг в своем прерывании., @Majenko

Однако я не знаком с внутренней работой библиотеки Due SPI. Лучше всего перестраховаться и не использовать SPI в прерывании., @Majenko

@Маженко Я думал, что SPI.usingInterrupt специально предназначен для этой цели// Если SPI используется внутри прерывания, эта функция регистрирует // это прерывание с библиотекой SPI, поэтому метод BeginTransaction() может // предотвращаем конфликты. Входной номер прерывания — это используемый номер. // с помощью AttachInterrupt. Если SPI используется из другого прерывания // (например, таймер), номер прерывания должен быть 255. static void usingInterrupt(uint8_t ignoreNumber);, @shz


1 ответ


1

В общем, лучше делать как можно меньше действий в подпрограмме обслуживания прерываний (ISR).

resetPhase — это ваш ISR, и обычно он устанавливает флаг или семафор, чтобы сигнализировать коду с более низким приоритетом о том, что необходимо выполнить определенную работу и, в данном случае, вероятно, не более того. Тогда ваш код loop, заметив, что флаг установлен, очистит флаг и выполнит свою работу.

Я полагаю, что авторы библиотеки думали, что SPI.usingInterrupt облегчит использование SPI, но выполнение ввода-вывода в ISR кажется немного противоречащим лучшим практикам. Эти проблемы отражены здесь, а также некоторые другие предостережения относительно прерываний и ISR. . Возможно, это не тот ответ, который вы ищете, но я надеюсь, что он поможет.

,