Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Message

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]

Attachments

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.