system
April 15, 2012, 10:00pm
1
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.
DuaneB
April 15, 2012, 10:04pm
2
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
system
April 15, 2012, 10:13pm
3
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();
system
April 15, 2012, 10:54pm
5
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.
system
April 15, 2012, 11:57pm
7
//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?
system
April 16, 2012, 10:03am
9
No, it doesn't, not even one bit.
system
April 16, 2012, 10:04am
10
//please ignore comments, as the code is modified so frequently that I forget about comments!
If they are not important, why have them?
system
April 16, 2012, 10:23am
11
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.
MarkT
April 17, 2012, 7:27am
14
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.