Go Down

Topic: SPI interface with other board_AVR_ESK1100 or among Arduino itself (Read 10 times) previous topic - next topic

Nick Gammon

#70
Nov 16, 2012, 05:29 am Last Edit: Nov 16, 2012, 05:33 am by Nick Gammon Reason: 1
If you aren't sending any data back, what do you expect? It will happen to return what is in SPDR at the time. You have to change it in the ISR. Also you can't do Serial.print in an ISR, it takes too long.

Modified sketch, returns 0x42:


Code: [Select]

//Slave receiving data
#include <SPI.h>

void setup (void)
{
 Serial.begin(115200);
 // have to send on master in, *slave out*
 pinMode(MISO, OUTPUT);
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode (SPI_MODE2);
 SPI.setClockDivider(SPI_CLOCK_DIV64) ;

 // turn on SPI in slave mode
 SPCR |= _BV(SPE);

 // turn on interrupts
 SPCR |= _BV(SPIE);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
 byte c = SPDR;  // what we received from the master
 SPDR = 0x42;    // what to return to the master
}  // end of ISR SPI_STC_vect


void loop (void)
{

}  // end of loop


Logic analyzer confirms we got the 0x42 returned each time:



ranjeetray


If you aren't sending any data back, what do you expect? It will happen to return what is in SPDR at the time. You have to change it in the ISR. Also you can't do Serial.print in an ISR, it takes too long.

Modified sketch, returns 0x42:


Code: [Select]

//Slave receiving data
#include <SPI.h>

void setup (void)
{
 Serial.begin(115200);
 // have to send on master in, *slave out*
 pinMode(MISO, OUTPUT);
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode (SPI_MODE2);
 SPI.setClockDivider(SPI_CLOCK_DIV64) ;

 // turn on SPI in slave mode
 SPCR |= _BV(SPE);

 // turn on interrupts
 SPCR |= _BV(SPIE);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
 byte c = SPDR;  // what we received from the master
 SPDR = 0x42;    // what to return to the master
}  // end of ISR SPI_STC_vect


void loop (void)
{

}  // end of loop


Logic analyzer confirms we got the 0x42 returned each time:





Thanks a lot Sir.

ranjeetray


If you aren't sending any data back, what do you expect? It will happen to return what is in SPDR at the time. You have to change it in the ISR. Also you can't do Serial.print in an ISR, it takes too long.

Modified sketch, returns 0x42:


Code: [Select]

//Slave receiving data
#include <SPI.h>

void setup (void)
{
 Serial.begin(115200);
 // have to send on master in, *slave out*
 pinMode(MISO, OUTPUT);
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode (SPI_MODE2);
 SPI.setClockDivider(SPI_CLOCK_DIV64) ;

 // turn on SPI in slave mode
 SPCR |= _BV(SPE);

 // turn on interrupts
 SPCR |= _BV(SPIE);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
 byte c = SPDR;  // what we received from the master
 SPDR = 0x42;    // what to return to the master
}  // end of ISR SPI_STC_vect


void loop (void)
{

}  // end of loop


Logic analyzer confirms we got the 0x42 returned each time:





Thank you Sir.

Can we do like this, after receiving data can we check(if condition) data and then send back data to master like this.
Code: [Select]


#include <SPI.h>

void setup (void)
{
  Serial.begin(115200);
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode (SPI_MODE2);
  SPI.setClockDivider(SPI_CLOCK_DIV64) ;

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR;  // what we received from the master
  //delay(15);
if(c == 0x04)
{
   digitalWrite(SS, LOW);
    SPDR = 0x45;
  SPI.transfer(0xFF);
digitalWrite(SS, HIGH);
}
  else
SPDR = 0x00;    // what to return to the master
}  // end of ISR SPI_STC_vect


void loop (void)
{

}  // end of loop

It is not working, I tried.

ranjeetray


If you aren't sending any data back, what do you expect? It will happen to return what is in SPDR at the time. You have to change it in the ISR. Also you can't do Serial.print in an ISR, it takes too long.

Modified sketch, returns 0x42:


Code: [Select]

//Slave receiving data
#include <SPI.h>

void setup (void)
{
 Serial.begin(115200);
 // have to send on master in, *slave out*
 pinMode(MISO, OUTPUT);
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode (SPI_MODE2);
 SPI.setClockDivider(SPI_CLOCK_DIV64) ;

 // turn on SPI in slave mode
 SPCR |= _BV(SPE);

 // turn on interrupts
 SPCR |= _BV(SPIE);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
 byte c = SPDR;  // what we received from the master
 SPDR = 0x42;    // what to return to the master
}  // end of ISR SPI_STC_vect


void loop (void)
{

}  // end of loop


Logic analyzer confirms we got the 0x42 returned each time:





Hi...!!

This code works fine with making SPDR = 0x00; at ISR but I have observed on Oscilloscope that sometime few data goes back to MISO, Slave is not able to clear SPDR perfectly, what could be the reason.

Code: [Select]

//Slave receiving data
#include <SPI.h>

void setup (void)
{
  Serial.begin(115200);
  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode (SPI_MODE2);
  SPI.setClockDivider(SPI_CLOCK_DIV64) ;

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);

}  // end of setup


// SPI interrupt routine
ISR (SPI_STC_vect)
{
  byte c = SPDR;  // what we received from the master
  SPDR = 0x00;    // what to return to the master
}  // end of ISR SPI_STC_vect


void loop (void)
{

}  // end of loop

Just keeping bandwidth of site in mind I am attaching one oscilloscope photo for your reference.

Nick Gammon


Can we do like this, after receiving data can we check(if condition) data and then send back data to master like this.


I really don't know what you are trying to do. You are doing an SPI.transfer in the middle of the ISR?

You send back data to the master by assigning to SPDR in the interrupt service routine. No other way. What are you thinking?

Go Up