Hi Team-
New user, just thought I'd add a bit of a contribution and also seek some advice.
In a nutshell, I'm using Arduino to do some control of Solar Charge Controllers using Serial ports.
I'm using a mega 2560 quite successfully.
Ran out of Serial Ports, my code is non-blocking so I don't like Software Serial - easiest way to add more serial IO is to use a second Arduino and have the two coordinate activities over SPI.
After many days I've come up with some working code for (near) synchronous transfer of data using SPI, with CRC check.
This code basically sends a structure from master to slave, and slave sends back another structure at the same time. It's a very basic framework. I've added Nick's CRC code into his SPI_Anything.h code, and amended the SPI Write Anything and Read Anything code to add pointers to two structures (incoming and outgoing) to make synchronous SPI communication easier... So here's my contribution, I hope it's useful to someone. I've commented extensively to hopefully make it self explanatory.
The Amended SPI Anything Library
#include <Arduino.h>
template <typename T> unsigned int SPI_writeAnything (T& outgoingStructure, T& incomingStructure)
{
//byteCRC=0;
//byte returnByte;
byte * outgoingByte = (byte*) &outgoingStructure;
byte * incomingByte = (byte*) &incomingStructure;
unsigned int i;
for (i = 0; i < sizeof outgoingStructure; i++) {
if (i==0) {
SPI.transfer(*outgoingByte++);//we write the next byte but ignore the result as the result will be whatever was in the slave arduino's buffer.
delayMicroseconds(20);// the Arduino implementation has an error that results in unpredictable behavior if this delay is not put here.
}
else
{
*incomingByte++=SPI.transfer(*outgoingByte++); //after the first byte is written every subsequent byte received will be the contents of the slave structure - so record in master structure.
//delayMicroseconds(50);
}
}
*incomingByte=SPI.transfer(0); //need to do one final dummy write to get the last byte of data from the slave structure.
return i;
} // end of SPI_writeAnything
template <typename T> unsigned int SPI_readAnything_ISR(T& incomingStructure,T& outgoingStructure)
{
byte * incomingByte = (byte*) &incomingStructure;
byte * outgoingByte = (byte*) &outgoingStructure;
unsigned int i;
*incomingByte++ = SPDR; //at the beginning of the interrupt, the very first byte will be sitting in the SPDR buffer.
for (i = 1; i < sizeof incomingStructure; i++)
{
*incomingByte++ = SPI.transfer (*outgoingByte++); //with every subsequent byte we send the next byte of the local structure (*outgoingByte)
} //to the master and store to the remote structure locally (*incomingByte++).
SPI.transfer(*outgoingByte);
return i;
} // end of SPI_readAnything_ISR
template <typename T> unsigned int SPI_CalculateCRC (T& targetStructure)
{
byte * addr = (byte*) &targetStructure;
byte crc = 0;
long len=(sizeof targetStructure - sizeof (byte)); //the last byte of my structure is always the CRC.
//so ignore the last byte of the structure or we'd
//be calculating the CRC on our CRC.
while (len--)
{
byte inbyte = *addr++;
for (byte i = 8; i; i--)
{
byte mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix)
crc ^= 0x8C;
inbyte >>= 1;
} // end of for
} // end of while
return crc;
} // end of CRC Calculation
part 2 follows...