SPI in loop() working fine, but not in ISR TIMER 1 interrupt

I am using SPI to control LEDs via serial registers.

Works fine:

void loop() 
{
  SPI.transfer(matrica[1][1]); dilej();
  SPI.transfer(matrica[1][2]); dilej();
 SPI.transfer(matrica[1][3]); dilej();    
  

}

Doesn’t work at all

ISR(TIMER_1_COMPA_vect)
 
{
  SPI.transfer(matrica[1][1]); dilej();
  SPI.transfer(matrica[1][2]); dilej();
  SPI.transfer(matrica[1][3]); dilej();    
}

dilej() is just delay function. Works fine.

Settings:

SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV2);

TIMSK1 =0;
TCCR1A=0;
TCR1B |= (1<<WGM12);
TCCR1B &= ~(1<<CS12);
TCCR1B |= (1<<CS11);  
TCCR1B |= (1<<CS10); 
TIMSK1 |= (1<<OCIE1A);

Timer tested. I think it works fine, I even added one LED and flashed it everytime interrupt executed, and LED was dimmer as usual.

So what could be the problem? Please help, I am mindfucking myself 6 hours already with this, and it just doesn’t work :(. Gotta finish this for school in 3 days.

Thanks in advance.

Hi,

I might be wrong, but does the spi library rely on interrupts ? If so it will not work inside an interrupt service routine because interrupts are disabled temporarily while an isr runs.

To get around this, just set a flag in the isr which you can test for in loop, when the flag is set, you know it's time to send your data.

Duane b

rcarduino.blogspot.com

Ok, I typed sei() in the beggining of ISR function, but it doesn't work. Or did I misunderstood you?

sei() in the ISR will do nothing if the interrupts don't run, try calling the SPI.detachInterrupt(); This might not do anything as SPI defaults with ISR off. Also do you call SPI.begin();

You cannot use delay() in an ISR. Time does not ‘tick’ inside the ISR.

Instead, have a look at <util/delay.h> and

_delay_ms()

Warning: you must not use variables as the argument for _delay_ms() or the code will blow up like pop-corn. Only compile-time known constants. If you need it variable, use a wrapper that calls _delay_ms(1).

kobilica: dilej() is just delay function. Works fine.

Depending on how it is written, delay functions might not work inside an ISR. Sadly you haven't shown us the dilej function.

DuaneB: I might be wrong, but does the spi library rely on interrupts ?

No - SPI.transfer is so fast that attempting to use interrupts would be slower.

@op - show the whole thing, not just snippets.

kobilica: Ok, I typed sei() in the beggining of ISR function, but it doesn't work. Or did I misunderstood you?

Don't do that. Enabling interrupts inside an ISR is not a good idea.

//please ignore comments, as the code is modified so frequently that I forget about comments!

#include <avr/interrupt.h>
#include <avr/io.h>
#include <SPI.h>

volatile byte matrica[8][3];
volatile byte counting1;
volatile byte counting2;

volatile byte bitek;
volatile byte counter=0;

void setup() {
  
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode(SPI_MODE0);
 SPI.setClockDivider(SPI_CLOCK_DIV2);
 
   pinMode(4, OUTPUT);
   pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
  
  //Serial.begin(57600);
  
  TIMSK1 = 0;  
  // TIMER 1 CTC mode
  TCCR1A = 0;    // CORRECT
  TCCR1B |= (1<<WGM12); // CORRECT 
  /* IZBERI IZVOR URE ZA TIMER 2, IZVOR JE MULTIPLEXER */
  //ASSR &= ~(1<<AS2);  

  /* Enable Compare Match A interrupt enable  */
  
  //TIFR2 |= (1<<OCF2A);

  /* Now configure the prescaler to CPU clock divided by 64 */
  TCCR1B &= ~(1<<CS12);   // 
  TCCR1B |=  (1<<CS11);  // 001 - prescaler -2 ??  
  TCCR1B &=  ~(1<<CS10);  //

  SPCR |= (0<<SPIE);
for(counting1=0;counting1<4;counting1++)
for(counting2=0;counting2<3;counting2++)  
{ matrica[counting1][counting2]=1;
  matrica[counting1+4][counting2]=255;
}
  TCNT1 = 0;
  OCR1A = 255;
TIMSK1 |= (1<<OCIE1A);// correczt


sei();
bitek=0;

SPI.begin();
}
;
volatile byte krneki=0;

volatile void dilej() { krneki=0; while(krneki > 20) {krneki++;} }  

ISR(TIMER1_COMPA_vect) 
{  
  switch(bitek)  
  {       
    case 0: bitek=1;
            OCR1A=2; TCNT1 = 0;                   
                        SPI.transfer(matrica[0][1]); dilej();
                        SPI.transfer(matrica[0][2]); dilej();
                        SPI.transfer(matrica[0][3]);  dilej();
            break;
    case 1: bitek=2;
            OCR1A=2; TCNT1 = 0;   
                        SPI.transfer(matrica[1][1]); dilej();
                        SPI.transfer(matrica[1][2]); dilej();
                        SPI.transfer(matrica[1][3]); dilej();
                      
            break;
    case 2: bitek=3; 
            OCR1A=4;  TCNT1 = 0;
                        SPI.transfer(matrica[2][1]); dilej();
                        SPI.transfer(matrica[2][2]); dilej();
                        SPI.transfer(matrica[2][3]); dilej();                 
            break;
    case 3: bitek=4;
            OCR1A=8;   TCNT1 = 0; 
                        SPI.transfer(matrica[3][1]); dilej();
                        SPI.transfer(matrica[3][2]); dilej();
                        SPI.transfer(matrica[3][3]); dilej();
            break;
    case 4: bitek=5;
            OCR1A=16;  TCNT1 = 0;          
                        SPI.transfer(matrica[4][1]); dilej();
                        SPI.transfer(matrica[4][2]); dilej();
                        SPI.transfer(matrica[4][3]); dilej();
            break;
    case 5: bitek=6;
            OCR1A=32;   TCNT1 = 0;        
                        SPI.transfer(matrica[5][1]); dilej();
                        SPI.transfer(matrica[5][2]); dilej();
                        SPI.transfer(matrica[5][3]); dilej();
            break;            
    case 6: bitek=7;
            OCR1A=64;   TCNT1 = 0;
                        SPI.transfer(matrica[6][1]); dilej();
                        SPI.transfer(matrica[6][2]); dilej();
                        SPI.transfer(matrica[6][3]); dilej();
                      
            break;
    case 7: bitek=8; 
            OCR1A=255;  TCNT1 = 0;
                        SPI.transfer(matrica[7][1]); dilej();
                        SPI.transfer(matrica[7][2]); dilej();
                        SPI.transfer(matrica[7][3]); dilej();
                      
            break;
    case 8: bitek=9; 
            OCR1A=64;   TCNT1 = 0;
                        SPI.transfer(matrica[6][1]); dilej();
                        SPI.transfer(matrica[6][2]); dilej();
                        SPI.transfer(matrica[6][3]); dilej();
            break;
    case 9: bitek=10;
            OCR1A=32;  TCNT1 = 0;
                        SPI.transfer(matrica[5][1]); dilej();
                        SPI.transfer(matrica[5][2]); dilej();
                        SPI.transfer(matrica[5][3]); dilej();
                     
            break;
    case 10:bitek=11; 
            OCR1A=16;  TCNT1 = 0;
                        SPI.transfer(matrica[4][1]); dilej();
                        SPI.transfer(matrica[4][2]); dilej();
                        SPI.transfer(matrica[4][3]); dilej();
            break;
    case 11:bitek=12;
            OCR1A=8;   TCNT1 = 0;
            
                        SPI.transfer(matrica[3][1]); dilej();
                        SPI.transfer(matrica[3][2]); dilej();
                        SPI.transfer(matrica[3][3]); dilej();
            
            break;
    case 12: bitek=13; 
            OCR1A=4;   TCNT1 = 0;
                      
                        SPI.transfer(matrica[2][1]); dilej();
                        SPI.transfer(matrica[2][2]); dilej();
                        SPI.transfer(matrica[2][3]); dilej();
            
            break;
    case 13: bitek=0; 
            OCR1A=2;    TCNT1 = 0;
                        SPI.transfer(matrica[1][1]); dilej();
                        SPI.transfer(matrica[1][2]); dilej();
                        SPI.transfer(matrica[1][3]); dilej();             
            break;
          
    default: bitek=0; break; //?e se je slu?ajno kaj sfukalo, resetiramo bitek na 0
  }                    
         PORTB |= 0b00000100; // <-latch_on
         PORTB &= 0b11111011; // <-latch_off    
}  
//*/
void loop() 
{
  
  



}

I know, what a mess

Is there a question? Or are you saying it works now?

No, it doesn't, not even one bit.

//please ignore comments, as the code is modified so frequently that I forget about comments!

If they are not important, why have them?

Nevermind, I have fixed the problem. I had to put SPI.begin() at start of interrupt. I had it only in setup, which worked fine for loop() but not for ISR(). So there, you may learn from my stupid mistake...

But you don't need to do that. SPI.begin() only needs to be done once. Whatever you have done it has just masked the real problem.

volatile void dilej() { krneki=0; while(krneki > 20) {krneki++;} }

What does this achieve? You set krneki to 0, and while it is greater than 20 (which it isn't) you add 1.

If you use SPI both in an ISR and in the loop() function then you must disable interrupts around all uses of SPI not in the ISR.

Good point. Otherwise you'll get into a race condition.

However in this particular case, his loop function is empty.