0

I have a DDS that is controlled by an Arduino DUE, loop() waits for Serial commands and based on them calls one or another function that sets the DDS's frequency, phase, amplitude etc via SPI. In addition to that I want to be able to use an external interrupt triggered by a TTL signal to reset the DDS's phase accumulator. The phase reset is done by writing an SPI register - resetPhase().

Somehow the resetPhase() is triggered correctly, but as soon as I add a SPI.transfer to it the SPI communication stops working altogether, not just through interrupts, but also the functions triggered via serial commands stop working.

Is there a way to get it to work?

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();
}
  • 1
    Probably SPI transfers use an interrupt, which can't trigger because you're already in an interrupt. You should have the SPI operations outside the interrupt and just update some variables and set a flag in your interrupt. – Majenko Nov 19 '18 at 19:40
  • I am not familiar with the internal workings of the Due SPI library to be sure though. Best to be safe and not do SPI in an interrupt regardless. – Majenko Nov 19 '18 at 19:41
  • @Majenko I thought that the SPI.usingInterrupt is specifically for that purpose// If SPI is used from within an interrupt, this function registers // that interrupt with the SPI library, so beginTransaction() can // prevent conflicts. The input interruptNumber is the number used // with attachInterrupt. If SPI is used from a different interrupt // (eg, a timer), interruptNumber should be 255. static void usingInterrupt(uint8_t interruptNumber); – shz Nov 20 '18 at 13:23
1

In general, it's best to do as little as possible in your interrupt service routine (ISR).

resetPhase is your ISR here, and typically it would set a flag or semaphore to signal lower priority code that certain work needs to be done and, in this case, probably nothing more. Then your loop code on noticing the flag is set would clear the flag and do its work.

I imagine the library authors thought SPI.usingInterrupt would ease use of SPI, but performing I/O in an ISR seems a bit contrary to best practices. These concerns are echoed here, along with some other caveats regarding interrupts and ISRs. Possibly not the answer you're looking for, but I hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.