Can't get interrupt to work in SPI Slave mode. Sorry for the length.
2011-03-02 by Cat C
Hi,
I have to systems that I need to talk to each other:
1. An ATMega644 that is the SPI Master, clocked at 20MHz, SPI clk = CLK/16 (under 2MHz).
2. An ATMega168 that is the SPI slave, clocked at 8MHz (internal RC).
The setup of 2:
void SPI_Init()
{
//Here we setup PortB to be our SLAVE SPI
DDRB = 0
// | _BV(PB0) //NC
| _BV(PB1) //OC1A PWM Output
// | _BV(PB2) //SS SPI Chip Select INPUT for Slave
// | _BV(PB3) //MOSI - Slave Input
| _BV(PB4) //MISO - Slave Output
// | _BV(PB5) //SCK - Slave Clock Input
// | _BV(PB6) //XTAL1
// | _BV(PB7) //XTAL2
;
//We may need to use interrupts so we may want to also set SPIE
SPCR = 0b1100000;//(1<<SPE); //Enable SPI, Slave
// |||||||\ - SPR0: SPI Clock Rate Select 1 and 0. No effect for SPI Slave
// ||||||\- - SPR1: SPI Clock Rate Select 1 and 0. No effect for SPI Slave
// |||||\-- - CPHA: Clock Phase: CPHA Leading Edge Trailing Edge
// ||||\--- - CPOL: Clock Polarity: When CPOL == 0, SCK is LOW when idle
// |||\---- - MSTR: Master/Slave Select: When MSTR == 0, chip is SLAVE
// ||\----- - DORD: Data Order: When DORD == 0, MSB transmitted first.
// |\------ - SPE: SPI Enable
// \------- - SPIE: SPI Interrupt Enable
}
The ISR looks like this, to start with:
volatile char vcSPI_Char;
ISR(SPI_STC_vect) //SPI_STC_vect SIG_SPI
{
vcSPI_Char = SPDR;
UDR0 = vcSPI_Char; //Send to serial port for debugging
}
I know interrupts are enabled because I have a timer interrupt that works fine.
My "ISR(SPI_STC_vect)" never gets called, BUT checking "if (SPSR & _BV(SPIF))" in the main loop works (it's true when expected), so I have good reason to believe that the hardware is connected properly.
I still have some ideas to try on this next part:
Something else I must be doing wrong in the main loop: it appears that I'm not reading the data correctly from the SPI buffer because my if-else never match what I know I'm sending AND I can see on the scope that whatever was first sent by the master is sent back by the slave next time... what's wrong below, please?
It's also possible the master-slave have different MSB-LSB settings (master settings are not easy to find) but I thought I tried all variations in slave to no avail...
if (SPSR & _BV(SPIF)) //If we received an SPI byte
{
ui8TempSPDR = SPDR;
UART_PutChar(ui8TempSPDR); //This displays sometimes * (00101010) that I might be due to MSB<->LSB
if (ui8TempSPDR == 'T') //01010100
SPDR = 4;//Sending back, to look nice on the scope
else if (ui8TempSPDR == 'U')//01010101
SPDR = 8;//Sending back, to look nice on the scope
else
SomethingElse = ui8TempSPDR;
}
Just in case one wonders, for testing purposes, this is what the master sends:
SPI_SendTempControlData('T'); //For Requesting MSB of Value which will come next time
_delay_ms(1000);
SPI_SendTempControlData('U'); //For Requesting LSB of Value which will come next time
ui16_8Value.ui8Temp[1] = SPDR;
Utils_SendNumberStrToSerial(ui16_8Value.ui8Temp[1]);UART_PUTSTR_P("\t");
_delay_ms(1000);
SPI_SendTempControlData(25); //For Debugging
ui16_8Value.ui8Temp[0] = SPDR;
Utils_SendNumberStrToSerial(ui16_8Value.ui8Temp[0]);UART_PUTSTR_P("\r\n>");
UART_PUTSTR_P("Value = ");Utils_SendFloatStrToSerial(ui16_8Value.ui16Temp);
I would like to get the interrupt working, but failing that... why am I reading the wrong thing, why do the 'T' and 'U' never match?
I think I can sort out this part, but the interrupt?
Many thatks,
Cat
[Non-text portions of this message have been removed]