SPI question

Hi All,

I try to communicate with an Arduino Pro Atmega 328, actually part of the Mongoose IMU. Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino. First I knew nothing about SPI and asked a question here Arduino Forum and Nick Gammon provided me with extremely usefull information (Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino) but I'm ashamed to say I still can't get it to work.

I want mij microprocessor (NetMF framework) to be the master and communicate with the Arduino. If the microprosessor sends out one byte "start updating me" the Arduino should send back the actual values.

I've created this on the Arduino:

void setup()
//  SPI.setDataMode(SPI_MODE1);
//  SPI.setBitOrder(MSBFIRST);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

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

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

// SPI interrupt routine
ISR (SPI_STC_vect)
  byte c = SPDR;
  if(c == 8)
      SPDR = 16;
    SPDR = 255;

}  // end of interrupt service routine (ISR) SPI_STC_vect

And this on the NetMF:

                SpiCom = new SPI(new SPI.Configuration(Cpu.Pin.GPIO_NONE,
                    false, 0,0, true, false, 4000, SPI.SPI_module.SPI1));
                byte[] ReadBuffer = new byte[1];
                // Create and fill write buffer
                byte[] WriteBuffer = new byte[1];
                WriteBuffer[0] = 4;
                while (1 == 1)
                        SpiCom.WriteRead(WriteBuffer, ReadBuffer);

I would have expected 16 on the readbuffer if I would send 8 and 255 otherwise. But somehow It sends back 6 if I write 4 and 12 if I write 8. I can't figure out why. I don't use a slave select pin, there is only one slave. This is why I pass Cpu.Pin.GPIO_NONE as slave select pin on NetMf. ChipSelect active state = false, setuptime and hold time = 0, clock idle state = true, clock edge = false, ClockRate = 4000 Khz (I read somewhere that Arduino would be at 4Mhz?). SPI module = SPI1, whatever that might be. I also used about every possible other combination of the parameters on NetMF.

On Arduino I tried SPI.setDataMode(SPI_MODE1); and SPI.setBitOrder(MSBFIRST); as well, but no better results. I could also remove SPI.Begin(); and get the same results.

I did blink the status led within the ISR (SPI_STC_vect) routine and that seems to work. But the bytes don't match to what I would have expect. I thought SPDR would have been the byte incomming from the master and could be altered to represent the result from the slave.

I can't find anything on google about connecting NetMf to Arduino over SPI.

Thanks for taking the time to read this. Any information about what I'm doing wrong is very much appreciated. I don't have any Arduino skills.

You need a slave select pin.

The slave select pin serves two purposes, one obvious, and one somewhat more subtle.

The obvious use is to identify an individual slave device in a bus of devices. We can ignore that as there is only one device.

What we cannot ignore is the more subtle use of the SS pin, and that is to frame the SPI transaction.

An SPI transaction consists of a number of clock pulses with two data streams synchronised with that clock. The slave device has to know where in that stream of clock pulses an actual message is.

Yes, you can assume that you send 8 clock pulses, and the slave receives 8 clock pulses, and then calls that a received byte and acts on it. However, what if the first clock pulse you send as part of your actual byte isn’t the first pulse the slave has seen on the clock line? Say when setting up all the ports a single clock edge is created (say from a port going from high impedance to high), or while the output is high impedance while it’s setting up the clock input on the slave is floating and receiving all sorts of noise … ? The first clock you send might be the second clock the slave receives, or the thirty-second, or the three thousand two hundred and second. Who knows?

By having a slave select, you are telling the slave “Everything between this point and when I raise the slave select line is valid data - treat it as such.” Everything that the slave receives while the slave select line is high should be completely ignored. In fact, while the slave select line is high the whole of the SPI module can be disabled so that it doesn’t react in any way whatsoever to any spurious data outside the SS frame.


Yes, I know this is an old topic, but I think it’s nice to have these things answered anyway for future user reference.

What does this do?

                        SpiCom.WriteRead(WriteBuffer, ReadBuffer);

Does that do two SPI transfers? Remember, SPI is two-way. Whilst sending the first byte you can't get a response at the same time. The other end has to receive the whole byte, and respond during the next transfer.