Yahoo Groups archive

AVR-Chat

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

Thread

Can't get interrupt to work in SPI Slave mode. Sorry for the length.

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]

Re: [AVR-Chat] Can't get interrupt to work in SPI Slave mode. Sorry for the length.

2011-03-03 by Jim Wagner

On Mar 2, 2011, at 9:39 AM, Cat C wrote:

>
> 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]
>
>
> 
Just the obvious: I don't see a global interrupt enable!

Jim Wagner
Oregon Research Electronics



[Non-text portions of this message have been removed]

Re: [AVR-Chat] Can't get interrupt to work in SPI Slave mode. Sorry for the length.

2011-03-03 by Cat

Thanks for looking Jim,

I only show a small section of code... like I said: I know interrupts work 
because a timer interrupt works.

I just found an appnote that says I should read both SPDR and SPSR to "Clear 
SPI Interrupt Flag by reading SPSR and SPDR" before sei.
I don't think I did that... I thought SPIF in SPSR is clear to start with, 
and would get cleared again as it enters the ISR...
And I didn't think I need to read the data buffer (SPDR) to make interrupts 
work...

I might try tomorrow.

Thanks,

Cat
Show quoted textHide quoted text
-----Original Message----- 
From: Jim Wagner
Sent: Wednesday, March 02, 2011 7:44 PM
To: AVR-Chat@yahoogroups.com
Subject: Re: [AVR-Chat] Can't get interrupt to work in SPI Slave mode. Sorry 
for the length.


On Mar 2, 2011, at 9:39 AM, Cat C wrote:
...
>
Just the obvious: I don't see a global interrupt enable!

Jim Wagner
Oregon Research Electronics

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.