Go Down

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

Nick Gammon


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:

Code: [Select]

  // disable timer interrupts
  TIMSK0 = 0;


Modified sketch:

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

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

Nick Gammon


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:

http://www.gammon.com.au/spi


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.


Quote
... what could be the reason.


You need to read my page and understand it.

Graynomad

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
Rob Gray aka the GRAYnomad www.robgray.com

Nick Gammon

He's probably got the 10x switch flicked on the probe.

ranjeetray


He's probably got the 10x switch flicked on the probe.


Yes , It is 10X probe of Tektronix TDS2024C(200MHz/100MHz, 10MOhm/<12pF 300V CAT II).

Go Up