SPI interface with other board_AVR_ESK1100 or among Arduino itself

I suspect that your 0x3E is still in the SPDR register although it should be overwritten by SPI.transfer(array[ii]) I would think.

So I want to remove this 0x3E while sending back data from Slave.Is it possible by clearing any buffer.

If 0x12 is written into the SPDR register that's the value that will go out, I don't know why SPI.transfer() would not do that.

Have I got this right...

Arduino sends 0x3E to IMU.
Line turns around.
IMU sends data to Arduino.

Does this IMU really expect the SPI line to be turned around? Have you got a data sheet?

so before testing the actual IMU, I want to create a dummy IMU which will be Arduino board or EVK1100(which will act as Master and will send command for data) and other slave board will be Arduino board which will receive command from IMU master board(Arduino or EVK1100)

BTW, All this talk of IMU/Arduino/EVK1100 is really confusing the issue IMO, can we just say Arduino and IMU and assume that they are both SPI-capable devices.


Rob

Every transfer sends one byte and receives one. You don't "clear the buffer". Sending something, and getting a response to what was just sent, involves at least two transfers. You can't get a response at the same time you are sending because each bit is transferred at the same time.

Perhaps read this:

I want to create a dummy IMU which will be Arduino board or EVK1100(which will act as Master and will send command for data) and other slave board will be Arduino board which will receive command from IMU master board(Arduino or EVK1100) and then send back required data on SPI bus.

I really don't understand what you are doing. Normally SPI is two-way. You don't flip backwards and forwards from slave to master just to get something back. Please read the link above carefully. Then ask specific questions.

Graynomad:
I suspect that your 0x3E is still in the SPDR register although it should be overwritten by SPI.transfer(array[ii]) I would think.

So I want to remove this 0x3E while sending back data from Slave.Is it possible by clearing any buffer.

If 0x12 is written into the SPDR register that's the value that will go out, I don't know why SPI.transfer() would not do that.

Have I got this right...

Arduino sends 0x3E to IMU.
Line turns around.
IMU sends data to Arduino.

Does this IMU really expect the SPI line to be turned around? Have you got a data sheet?

so before testing the actual IMU, I want to create a dummy IMU which will be Arduino board or EVK1100(which will act as Master and will send command for data) and other slave board will be Arduino board which will receive command from IMU master board(Arduino or EVK1100)

BTW, All this talk of IMU/Arduino/EVK1100 is really confusing the issue IMO, can we just say Arduino and IMU and assume that they are both SPI-capable devices.


Rob

Respected Sir

Thanks a lot for your kind reply.
Yes , I want to communicate between IMU and Arduino board. IMU will act as a Master and Arduino will be a slave.
Once slave(Arduino) receives 0x3E(as a command) from IMU it will send back 12bytes of required data to IMU.

Thanks & Regards...:slight_smile:

ADIS16400_16405.pdf (497 KB)

According to the datasheet you just posted:

Although the ADIS16400/ADIS16405 produce data independently, these operate as SPI slave devices that communicate with system (master) processors using the 16-bit segments displayed in Figure 11.

The device operates as a slave, and thus there is no requirement to jump between master/slave for each communication. Have you read my page?

A simple yes/no will suffice.

Have you read the datasheet?

Respected Sir

How did you copy image here. I am trying to paste image here but it is not happening.

Thanks & Regards.... :slight_smile:

I put the image on my own web site and included a link to it.

OK Sir

Thanks & Regards... :slight_smile:

Hi...!!!

For testing purpose I will directly connect to OBC(On Board Computer) of satellite which will be master and my Arduino Board will be slave(IMU).

[/quote]

Hi...!!!

Can anybody share the working code on SPI.

ranjeetray:

Hi...!!!

Can anybody share the working code on SPI.
[/quote]

Any Luck....!!!

I think I'll close this thread if you don't answer my question. It's no use ignoring the questions and keep posting about wanting people to share code.

Hi..!!!

Yes.

I have read this again and again, but still problem is there.
From master I am sending following data (int array[8] = {0x04, 0x00, 0x06, 0x00, 0x08, 0x00, 0x0A, 0x00}:wink: and on slave side I am receiving the same data. But same data are available on both MOSI and MISO.
I can see on oscilloscope that even MISO line has the same data which are ( int array[8] = {0x04, 0x00, 0x06, 0x00, 0x08, 0x00, 0x0A, 0x00}:wink: on MOSI also.
But from slave side I am not sending any data then why data are available on line(MISO), is there any way to clear buffer or SPDR.

//Master sending data

//Master sending data
#include <SPI.h>// include the SPI library:
#define SCK_PIN   13
#define MISO_PIN  12
#define MOSI_PIN  11

const int spidata = 10;//Pin 11 is data(MOSI) and pin 13 SCK ,set pin 10(SS) as the slave select for the digital pot:
int array[8] = {0x04, 0x00, 0x06, 0x00, 0x08, 0x00, 0x0A, 0x00};
int chr;

void setup() {
  
  pinMode (spidata, OUTPUT);// set the spi_data_pin as an output:
  
  SPI.begin();// initialize SPI:
  Serial.begin(115200);
  SPI.setDataMode(SPI_MODE2);
  SPI.setClockDivider(SPI_CLOCK_DIV64) ;
  SPI.setBitOrder(LSBFIRST);
 
}

void loop() {
  int data[10];
  char ch;
 

    
   digitalWrite(spidata,LOW);
   SPI.transfer(array[0]); 
   SPI.transfer(array[1]);
   digitalWrite(spidata,HIGH);
   
   digitalWrite(spidata,LOW);
   SPI.transfer(array[2]); 
   SPI.transfer(array[3]);
   digitalWrite(spidata,HIGH);
   
   digitalWrite(spidata,LOW);
   SPI.transfer(array[4]); 
   SPI.transfer(array[5]);
   digitalWrite(spidata,HIGH);
   
   digitalWrite(spidata,LOW);
   SPI.transfer(array[6]); 
   SPI.transfer(array[7]);
   digitalWrite(spidata,HIGH);
   

    }

//Slave receiving data

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

// what to do with incoming data
byte command = 0;

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;
  Serial.println(c, HEX);
}


void loop (void)
{
  
  // if SPI not active, clear current command
  if (digitalRead (SS) == HIGH)
    command = 0;
}  // end of loop

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:

//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.

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.

#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.

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.

//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.

TEK0000.BMP (76.1 KB)

ranjeetray:
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?

ranjeetray:
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.
...
Just keeping bandwidth of site in mind I am attaching one oscilloscope photo for your reference.

I can reproduce that. I am guessing that the Timer interrupt (used by millis() and delay() ) is slowing it down enough that it cannot respond quickly (this would happen every few milliseconds, because if the timer interrupt happens to fire when the SPI interrupt needs to fire, the SPI interrupt won't change SPDR fast enough).

By adding this line to setup the problem goes away:

  // disable timer interrupts
  TIMSK0 = 0;

Modified sketch:

//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);

  // disable timer interrupts
  TIMSK0 = 0;
}  // end of setup


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


void loop (void)
{
 
}  // end of loop

This is why you cannot use delay inside the ISR (as you had, commented out). In any case, delay() doesn't work inside an ISR.

The ISR has to be fast, because if you don't change SPDR fast enough, the incorrect data will be sent on the next transfer.

Of course, if you turn off timer interrupts you won't know how much time has elapsed.

What you could do is have an interrupt on the SS (slave select) line. When that goes low, turn off timer interrupts, wait for the incoming data, and when SS goes high again, turn timer interrupts back on.

ranjeetray:
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.

I'm not convinced you read and understood my page here:

In that I mention this exact problem. To get a response you need to allow time for the slave to do whatever it needs to do, and set up a response (ie. set SPDR). See this diagram from that page:

In the code on that page I built in a delay on the master end, to slow down communications long enough to give the slave time to respond. It's all on the page. Please read it again, and again.

... what could be the reason.

You need to read my page and understand it.

Is channel 1 on the scope trace really set to 50mV/div? If so you are in deep trouble.

At the other extreme the top trace seems to pulse well over 7v. Is that right?


Rob