The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
It's actually relatively easy to use, really, as many SPI devices as you want. From a hardware perspective, you of course need to hook them all up to the correct MISO, MOSI, and SCLK pins. After that, you need to hook up each device to its own CS pin.
The important thing is to give each deivce it's own configuration, and then swap out the configurations of the devices. This wiki page has some good examples: http://wiki.netduino.com/SPI.ashx
I could be mistaken, but when using an SD card, you don't need to swap the configuration, as the framework does that for you whenever you try to access the SD card, but you will need to swap out the configuration for using other attached devices, like so:
class Program
{
private static SPI spi;
public static void Main()
{
StorageDevice.MountSD("SD", SPI.SPI_module.SPI1, Pins.GPIO_PIN_D10, Pins.GPIO_NONE);
//Use this to initialize the SPI module, the conif doesn't really matter since we'll change it anyway
SPI.Configuration config = new SPI.Configuration(
SPI_mod: SPI.SPI_module.SPI1,
ChipSelect_Port: Pins.GPIO_NONE,
ChipSelect_ActiveState: false,
ChipSelect_SetupTime: 0,
ChipSelect_HoldTime: 0,
Clock_IdleState: false,
Clock_Edge: true,
Clock_RateKHz: 1000);
spi = new SPI(config);
//Test the SD card
using (StreamWriter sw = new StreamWriter(@"SDTest.txt", true))
{
sw.WriteLine("This is test one");
}
//Write to device one
writeByteToOne(new byte[] { 255 });
//Write to device two
writeByteToTwo(new byte[] { 128 });
//Test the SD card again
using (StreamWriter sw = new StreamWriter(@"SDTest.txt", true))
{
sw.WriteLine("This is test two");
}
}
private static void writeByteToOne(byte[] data)
{
//Set the configuration of device one
SPI.Configuration config = new SPI.Configuration(
SPI_mod: SPI.SPI_module.SPI1,
ChipSelect_Port: Pins.GPIO_PIN_D0,
ChipSelect_ActiveState: false,
ChipSelect_SetupTime: 0,
ChipSelect_HoldTime: 0,
Clock_IdleState: false,
Clock_Edge: true,
Clock_RateKHz: 40000);
//Set the config of the SPI module
spi.Config = config;
spi.Write(data);
}
private static void writeByteToTwo(byte[] data)
{
//Set the configuration of device two
SPI.Configuration config = new SPI.Configuration(
SPI_mod: SPI.SPI_module.SPI1,
ChipSelect_Port: Pins.GPIO_PIN_D1,
ChipSelect_ActiveState: false,
ChipSelect_SetupTime: 0,
ChipSelect_HoldTime: 0,
Clock_IdleState: false,
Clock_Edge: true,
Clock_RateKHz: 5000);
//Set the config of the SPI module
spi.Config = config;
spi.Write(data);
}
//Add more devices if you want. Better, put each device in its own class.
}
This is just a quick and dirty unoptomized example, and assumes the CS pin of the SD card is D10, and that you're not using the CD pin. You could improve things by putting each device it its own class with a configuration that gets swapped in whenever you call a write or read from the device class, for instance.
But how would I go about attaching other devices to the SPI bus?
In theory the netmf toolbox MultiSPI would suit me well but the SD card is not a normal SPI configuration from what i can see (you pass slave select pin and spi device in mountSD not through a normal SPI config). So how would I switch SPI configs?
It's actually relatively easy to use, really, as many SPI devices as you want. From a hardware perspective, you of course need to hook them all up to the correct MISO, MOSI, and SCLK pins. After that, you need to hook up each device to its own CS pin.
The important thing is to give each deivce it's own configuration, and then swap out the configurations of the devices. This wiki page has some good examples: http://wiki.netduino.com/SPI.ashx
I could be mistaken, but when using an SD card, you don't need to swap the configuration, as the framework does that for you whenever you try to access the SD card, but you will need to swap out the configuration for using other attached devices, like so:
class Program
{
private static SPI spi;
public static void Main()
{
StorageDevice.MountSD("SD", SPI.SPI_module.SPI1, Pins.GPIO_PIN_D10, Pins.GPIO_NONE);
//Use this to initialize the SPI module, the conif doesn't really matter since we'll change it anyway
SPI.Configuration config = new SPI.Configuration(
SPI_mod: SPI.SPI_module.SPI1,
ChipSelect_Port: Pins.GPIO_NONE,
ChipSelect_ActiveState: false,
ChipSelect_SetupTime: 0,
ChipSelect_HoldTime: 0,
Clock_IdleState: false,
Clock_Edge: true,
Clock_RateKHz: 1000);
spi = new SPI(config);
//Test the SD card
using (StreamWriter sw = new StreamWriter(@"SDTest.txt", true))
{
sw.WriteLine("This is test one");
}
//Write to device one
writeByteToOne(new byte[] { 255 });
//Write to device two
writeByteToTwo(new byte[] { 128 });
//Test the SD card again
using (StreamWriter sw = new StreamWriter(@"SDTest.txt", true))
{
sw.WriteLine("This is test two");
}
}
private static void writeByteToOne(byte[] data)
{
//Set the configuration of device one
SPI.Configuration config = new SPI.Configuration(
SPI_mod: SPI.SPI_module.SPI1,
ChipSelect_Port: Pins.GPIO_PIN_D0,
ChipSelect_ActiveState: false,
ChipSelect_SetupTime: 0,
ChipSelect_HoldTime: 0,
Clock_IdleState: false,
Clock_Edge: true,
Clock_RateKHz: 40000);
//Set the config of the SPI module
spi.Config = config;
spi.Write(data);
}
private static void writeByteToTwo(byte[] data)
{
//Set the configuration of device two
SPI.Configuration config = new SPI.Configuration(
SPI_mod: SPI.SPI_module.SPI1,
ChipSelect_Port: Pins.GPIO_PIN_D1,
ChipSelect_ActiveState: false,
ChipSelect_SetupTime: 0,
ChipSelect_HoldTime: 0,
Clock_IdleState: false,
Clock_Edge: true,
Clock_RateKHz: 5000);
//Set the config of the SPI module
spi.Config = config;
spi.Write(data);
}
//Add more devices if you want. Better, put each device in its own class.
}
This is just a quick and dirty unoptomized example, and assumes the CS pin of the SD card is D10, and that you're not using the CD pin. You could improve things by putting each device it its own class with a configuration that gets swapped in whenever you call a write or read from the device class, for instance.
I admit, I didn't actually test the code I posted here, but I have used an SD card with other SPI devices, and I've only had to swap the configs when using more than one other device (besides the SD). So if you're using just the SD and one other device, you might not need to swap any configs at all (the framework is pretty slick that way).
Welll I set everything up and it all worked just like you said. I didn't even have to switch SPI configs as all I have is one SPI device (shift register) attached to the bus other than the SD card.
I did feel the SD card implementation is a bit... shaky, though I've seen other users with some issues with the SD card... such as not writing the file to the card unless Unmount is called and stuff like that, so I know I'm probably not alone. Mine did write without calling Unmount..... sometimes. Other times not but it might have been user error. I didn't spend much time looking at this though (it got late for my bedtime ) so I am still blaming myself for now!
I've also seen those posts about problems with writing to the SD card, but haven't had them myself. Using the card detect pin might make things more reliable, but I've never played around with that. That's the thing about the framework, it makes things easy, but sometimes it hides things too well when there are problems.
Well, just as I suspected, the problem with writing to the SD card was totally caused by me . It all works perfectly now. Just need to treat it with care. I implemented a Queue which everything writes to, then a dedicated SD card thread simply processes that queue at its leisure at regular intervals.
Having everything try to write to the SD card (even in different files) just like it always worked on desktop hard disks just didn't give the sort of reliable results that I could feel comfortable with.
That's good info; it means that we have to make sure writing to the SD card is extremely thread safe. I wonder if the card can handle multiple simultaneous reads or a read at the same time as a write... I sense a lot of experimentation in the future!