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.
The SPI bus has the following four signals:
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 |
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:
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:
In this example we are writing 64 bytes to a SPI slave, It has the following configuration:
// Create a new SPI deviceSPI SPI_Out = new SPI(new SPI.Configuration(
(Cpu.Pin)10, // SS on GPIO pin 10
false, // SS active-low
0, // No setup time
0, // No hold time
false, // Clock low on idle
false, // Data valid on falling edge
1000, // 1MHz clock rate
SPI.SPI_module.SPI1 // SPI device 1
));
// Create read bufferbyte[] ReadBuffer = new byte[64];
// Create and fill write bufferbyte[] WriteBuffer = new byte[64];
for (byte c = 0; c < 64; c++) { WriteBuffer[c] = c; }
// Transfer dataSPI_Out.WriteRead(WriteBuffer, ReadBuffer);
// Debug messageDebug.Print("Send 64 bytes to SPI Slave");
// Dispose SPI deviceSPI_Out.Dispose();
In this example we are reading 64 bytes from a SPI slave, It has the following configuration:
// Create a new SPI deviceSPI SPI_Out = new SPI(new SPI.Configuration(
(Cpu.Pin)10, // SS on GPIO pin 10
false, // SS active-low
0, // No setup time
0, // No hold time
false, // Clock low on idle
false, // Data valid on falling edge
1000, // 1MHz clock rate
SPI.SPI_module.SPI1 // SPI device 1
));
// Create read bufferbyte[] ReadBuffer = new byte[64];
// Create and fill write bufferbyte[] WriteBuffer = new byte[64];
// Fill the write buffer with 0xFF, is not always necessaryfor (int c = 0; c < 64; c++) { ReadBuffer[c] = 0xff; }
// Transfer dataSPI_Out.WriteRead(WriteBuffer, ReadBuffer);
// Debug Read dataDebug.Print("Recieved 64 bytes from SPI Slave");
for (int c = 0; c < 64; c++) { Debug.Print(c.ToString() + ": " + ReadBuffer[c].ToString());
// Dispose SPI deviceSPI_Out.Dispose();