.NET Micro Framework Wiki :: SPI

From .NET Micro Framework Wiki
Jump to: navigation, search

SPI stands for Serial Peripheral Interface. It is a 4 wire serial bus originally designed by Motorola. It runs in full duplex, which means it sends and receives data at the same time. It allows fast data transfer between a master device and a slave.

Here, one SPI Master controls two Slaves. The master selects the device by using the SS1 and SS2 lines
Here, one SPI Master controls two Slaves. The master selects the device by using the SS1 and SS2 lines

The SPI bus has the following four signals:

  • SCLK, Serial Clock (Produced by Master)
  • MISO, Master In, Slave Out (Data from Slave to Master)
  • MOSI, Master Out, Slave In (Data from Master to Slave)
  • SS, Slave Select

Some datasheets use other names for the signals. Also not all signals may be used on every device. A device that only outputs data doesn't need the MOSI pin. On the right you can see an example implementation of two SPI Slaves controlled by a Master. The master selects the device it wants to talk to by asserting the Slave Select line of the device. On most slaves the SS line is active low.

The SPI bus can be very fast. This is why it's commonly used on devices that require a high throughput like SD Cards, Music DACs and LCD displays. This is because the protocol requires very simple logic. One drawback of SPI is that it doesn't have strict specifications. The time required between asserting SS and start of data transfer, Edge for data valid and SS active state all vary.

Contents

SPI

Depending on the device used, .NET Micro Framework supports being a SPI Master device. The base class is SPI. The constructor looks like this:

new SPI(Configuration config);

The only parameter is an SPI Configuration which has the following constructor:

public Configuration(
  Cpu.Pin ChipSelect_Port, 
  bool ChipSelect_ActiveState, 
  uint ChipSelect_SetupTime,
  uint ChipSelect_HoldTime, 
  bool Clock_IdleState, 
  bool Clock_Edge, 
  uint Clock_RateKHz, 
  SPI.SPI_module SPI_mod
);

Because of the loose SPI specifications, the Configuration constructor has a lot of parameters:

  1. Selects which GPIO port to assert for SS. Pass Cpu.Pin.GPIO_NONE if you don't want to use it.
  2. The active state for SS. On most slave devices this is active-low (=false)
  3. The time between asserting SS and reading/writing data
  4. The time between the last data send an de-asserting of SS
  5. Defines the idle state of SCLK.
  6. Defines the clock edge that is used for sampling data. false means data is valid on the falling edge, high means data is valid on the rising edge.
  7. Clock rate in Khz
  8. SPI module to use. Which modules are available depend on the .NET Micro Framework device that is used.


WriteRead

To read and write to a SPI slave you can use the WriteRead command:

// For 8-Bit SPI transfer
YourSPIDevice.WriteRead(byte[] writeBuffer, byte[] readBuffer);
YourSPIDevice.WriteRead(byte[] writeBuffer, byte[] readBuffer, int readOffset);
 
// For 16-Bit SPI transfer (Not all .NET Micro Framework devices support this)
YourSPIDevice.WriteRead(UInt16[] writeBuffer, UInt16[] readBuffer);
YourSPIDevice.WriteRead(UInt16[] writeBuffer, UInt16[] readBuffer, int readOffset);

Where YourSPIDevice is the SPI device you have created and it has the following parameters:

  1. byte[] or UInt16[] array of bytes/words to write. If you only want to read you can use 0xFFFF/0xFF as data
  2. byte[] or UInt16[] array that is filled with the received bytes/words. When you don't use readOffset it should be the same size as the write buffer.
  3. (optional) The number of bytes/words that are written before data is stored to the read buffer.


Example usage: Write 64 bytes to a SPI slave

In this example we are writing 64 bytes to a SPI slave, It has the following configuration:

  • SS is active-low and on GPIO pin 10
  • SCLK is low on idle and has a rate of 1Mhz
  • Data is valid on the falling clock edge
  • SPI Device 1 is used
  • No setup and hold time


  1. // Create a new SPI device
  2. SPI SPI_Out = new SPI(new SPI.Configuration(
  3.     (Cpu.Pin)10,            // SS on GPIO pin 10
  4.     false,                  // SS active-low
  5.     0,                      // No setup time
  6.     0,                      // No hold time
  7.     false,                  // Clock low on idle
  8.     false,                  // Data valid on falling edge
  9.     1000,                   // 1MHz clock rate
  10.     SPI.SPI_module.SPI1     // SPI device 1
  11.     )
  12. );
  13.  
  14. // Create read buffer
  15. byte[] ReadBuffer = new byte[64];
  16.  
  17. // Create and fill write buffer
  18. byte[] WriteBuffer = new byte[64];
  19. for (byte c = 0; c < 64; c++) { WriteBuffer[c] = c; }
  20.  
  21. // Transfer data
  22. SPI_Out.WriteRead(WriteBuffer, ReadBuffer);
  23.  
  24. // Debug message
  25. Debug.Print("Send 64 bytes to SPI Slave");
  26.  
  27. // Dispose SPI device
  28. SPI_Out.Dispose();


Example usage: Read 64 bytes to a SPI slave

In this example we are reading 64 bytes from a SPI slave, It has the following configuration:

  • SS is active-low and on GPIO pin 10
  • SCLK is low on idle and has a rate of 1Mhz
  • Data is valid on the falling clock edge
  • SPI Device 1 is used
  • No setup and hold time


  1. // Create a new SPI device
  2. SPI SPI_Out = new SPI(new SPI.Configuration(
  3.     (Cpu.Pin)10,            // SS on GPIO pin 10
  4.     false,                  // SS active-low
  5.     0,                      // No setup time
  6.     0,                      // No hold time
  7.     false,                  // Clock low on idle
  8.     false,                  // Data valid on falling edge
  9.     1000,                   // 1MHz clock rate
  10.     SPI.SPI_module.SPI1     // SPI device 1
  11.     )
  12. );
  13.  
  14. // Create read buffer
  15. byte[] ReadBuffer = new byte[64];
  16.  
  17. // Create and fill write buffer
  18. byte[] WriteBuffer = new byte[64];
  19.  
  20. // Fill the write buffer with 0xFF, is not always necessary
  21. for (int c = 0; c < 64; c++) { ReadBuffer[c] = 0xff; }
  22.  
  23. // Transfer data
  24. SPI_Out.WriteRead(WriteBuffer, ReadBuffer);
  25.  
  26. // Debug Read data
  27. Debug.Print("Recieved 64 bytes from SPI Slave");
  28. for (int c = 0; c < 64; c++) { Debug.Print(c.ToString() + ": " + ReadBuffer[c].ToString());
  29.  
  30. // Dispose SPI device
  31. SPI_Out.Dispose();
Personal tools