Command within interrupt not working as expected

Hello all,

I am using the arduino to program a Variable Frequency Oscillator (VFO) ADF4153A. To do so, the arduino is using SPI to write to a few registers in an order specified by the datasheet.

void startup() {

  SPI.begin();
  vfo.R[3].set(0UL) ;         // Clearing Noise and Spur Reg
  vfo.writeDev(3, vfo.R[3]);  // Writting Noise and Spur Reg
  RegNoise();                 // Setting Noise and Spur Reg
  vfo.writeDev(3, vfo.R[3]);  // Writting Noise and Spur Reg

  RegCont();                  // Setting Contol Reg
  vfo.R[2].setbf(2, 1, 1);    // Enabling Counter Rest
  vfo.writeDev(2, vfo.R[2]);  // Writting Contol Reg

  RegR();
  RegN();
  vfo.writeDev(1, vfo.R[1]);
  vfo.writeDev(0, vfo.R[0]);  // Setting and writting R and N(0) Reg

  vfo.R[2].setbf(2, 1, 0);    // Disabling Counter Rest
  vfo.writeDev(2, vfo.R[2]);  // Writting Contol Reg
  SPI.end();
}

There is a helpful library to accomplish this task. Above is the startup function. The library defines an object (hope i’m using the right term) as the VCO. The VCO object contains a few registers each with specific values, The registers are defined using the setbf command and communicated to the chip using the writeDev command. note: spi begin and end are present because pin 12 is being used as a digital I/O elsewhere.

void ADF4351::writeDev(int n, Reg r)
{
  byte  txbyte ;
  int i ;
  digitalWrite(pinSS, LOW) ;
  delayMicroseconds(10) ;
  i=n ; // not used 
  for ( i = 3 ; i > -1 ; i--) {
    txbyte = (byte) (r.whole >> (i * 8)) ;
    SPI.transfer(txbyte) ;
  }

  digitalWrite(pinSS, HIGH) ;
  delayMicroseconds(5) ;
  digitalWrite(pinSS, LOW) ;
}

All of that works well when the startup function is called during the setup() or is contained in the loop(). However, I don’t want to continually write to the VCO, and I dont want to use the delay command. My first thought was to use the timer and a simple interrupt to call the startup function every ~4 sec. When I did so, nothing worked. The serial monitor stopped outputting and VCO wasn’t programmed property. Below is setup code which initializes the timer and interrupt function. If I test the ISR itself by commenting out the startup and running the “Serial.println(millis());” (the opposite of what is currently shown in the ISR below) the interrupt works as expected. I get an output to the serial monitor ever ~4.1 sec. However, when i add in the startup function to the interrupt, it doesn’t work, and the serial monitor will output “ye” before never output anything ever again.
I’ve been banging my head against the wall, and i’m close to just using the mills function and dropping the timer. Before i do so, does anyone have any thoughts as to why this is happening and why the startup won’t work in an ISR?

void setup() {

  Serial.begin(115200) ;
  Wire.begin();
  vfo.pinSS = ListenEn;
  vfo.init();
  
  //Freq Definitions
  vfo.Frac = 7;  // 2.9 GHz
  vfo.N_Int = 296;
  vfo.Mod = 15;   // 2.9 GHz
  vfo.RCounter = 1;
  vfo.Prescaler = 1;    // if freq is greater than 2 GHz set to 1
  vfo.RD2refdouble = 0;

  //startup();

  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1B |= (1<<CS10) | (1<<CS12);
  TIMSK1 |= (1<<TOIE1);               //Interrupt counter to 4.1 seconds

}

ISR(TIMER1_OVF_vect){
    //Serial.println(millis());
    startup();
    //pinMode(VCOenable,INPUT);  // Restting pin as input after SPI operation
    
}

Happy to provide more context, thanks in advance for any and all help,
Sami

samihawasli:
My first thought was to use the timer and a simple interrupt to call the startup function every ~4 sec.

Sorry, but it wasn't a good first thought :slight_smile:

if you just want something to happen every 4 seconds (which is the equivalent of centuries for an Arduino) just use millis() to manage the timing. See how it is done in Several Things at a Time. And have a look at Using millis() for timing. A beginners guide if you need more explanation.

If you insist on using the interrupt then you should just use it to set a flag variable and your code in loop() should call the

startup() function - something like this
if (interruptTriggered == true) {
   startup();
  interruptTriggered = false;
}

You should not call a long running function from inside an ISR or a function that only works with interrupts enabled.

...R