SPI comms between 2 MCUs

- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hi,
I am attempting to establish SPI communication between 2 GT16a MCUs, where one is the slave and the other the master. I am able to send data from the master to the slave, but am receiving rubbish when trying to get data sent from the slave to the master. Any idea as to what could be the problem.
// For the Master MCU void laserComm(char Data[]) { if (Data[0] == 'X')PTCD_PTCD6 = 0; //Pull low to select correct slave if (Data[0] == 'Y')PTCD_PTCD5 = 0; //Pull low to select correct slave if (Data[0] == 'Z')PTCD_PTCD4 = 0; //Pull low to select correct slave for(laserCommCount=0; laserCommCount <= dataSize ; laserCommCount++) SPIdataIn[laserCommCount] = SPItransfer(Data[laserCommCount]); PTCD_PTCD6 = 1; // Pull high after data transfer PTCD_PTCD5 = 1; PTCD_PTCD4 = 1; } byte SPItransfer (byte val) { // First send, then receive while(!SPIS_SPTEF); SPID = val; while(!SPIS_SPRF); return SPID; } // For the slave MCU interrupt 15 void receiveSPI (void) { SPIdataIn[SPIReceiveIndex] = SPItransfer(Packet1[SPIReceiveIndex]); if (SPIReceiveIndex == dataSize) { SPIdataReceived = 1; // Indicate the data has been received SPIReceiveIndex = 0; // Reset receive index } else SPIReceiveIndex++; }
all the data is an array of chars.
Thanks!
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Hello,
As has already been mentioned, the SPItransfer() function is unsuited to slave use, and particularly so when using an interrupt for the slave process.
- Any data to be returned by the slave needs to be pre-loaded to the slave buffer prior to SS from the master becoming active. This data will then be shifted out to the master, as the next byte from the master is shifted in by the slave.
- It is also possible to make use of the double buffering capability of the SPI module, where the first two return bytes would be preloaded to the buffer. In this instance, it would not matter whether the new return data were loaded to the buffer prior to, or following the processing of the received byte, within the ISR.
- When appropriately using the SPI interrupt for the slave end, the ISR should handle only a single byte at a time, and then exit.
- The send process by the master may need to be suitably "paced" so that there is sufficient time for the slave ISR to complete execution, prior to the next byte being sent. This will also need to take into account the processing of any other interrupts that may be enabled within the slave.
- The master may also need to send an extra dummy byte so that the final slave byte can be returned from the SPI buffer.
// Global variables:
byte SPIdataIn[BUF_SIZE];
byte Packet1[BUF_SIZE];
byte dataSize;
byte SPIdataReceived;
static byte *Recv_buf;
static byte *Send_buf;
static byte byte_count;
...
// Initialise pointers
Recv_buf = SPIdataIn;
Send_buf = Packet1;
byte_count = 0;
SPIdataReceived = 0;
...
interrupt 15
void receiveSPI (void)
{
(void)SPIS; // Part of flag clearing
*Recv_buf++ = SPID; // Receive current byte
SPID = *Send_buf++; // Load next byte to buffer
byte_count++;
if (byte_count == dataSize) {
SPIdataReceived = 1; // Flag data received
byte_count = 0; // Reset counter
}
}
Regards,
Mac

- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Thanks for the reply.
I just want to confirm that my code for the master to receive is valid, also is shown my modified code for the slave.
// Master
byte SPItransfer (byte val)
{
// First send, then receive
while(!SPIS_SPTEF);
SPID = val;
while(!SPIS_SPRF);
return SPID;
}
/////////////////////////////////////////////////////////////////////////////////////
//Master
void laserComm(char Data[])
{
if (Data[0] == 'X')PTCD_PTCD6 = 0; //Pull low to select correct slave
if (Data[0] == 'Y')PTCD_PTCD5 = 0; //Pull low to select correct slave
if (Data[0] == 'Z')PTCD_PTCD4 = 0; //Pull low to select correct slave
for(laserCommCount=0; laserCommCount <= dataSize ; laserCommCount++)
SPIdataIn[laserCommCount] = SPItransfer(Data[laserCommCount]);
PTCD_PTCD6 = 1; // Pull high after data transfer
PTCD_PTCD5 = 1;
PTCD_PTCD4 = 1;
}
/////////////////////////////////////////////////////////////////////////////////////
//Slave receive function
interrupt 15 // SPI receive interrupt
void receiveSPI (void)
{
(void)SPIS; // Clear flags
SPIdataIn[SPIReceiveIndex] = SPID; // Receive byte
SPID = Packet1[SPIReceiveIndex]; // Load byte to send
if (SPIReceiveIndex == dataSize)
{
SPIdataReceived = 1; // Indicate the data has been received
SPIReceiveIndex = 0; // Reset receive index
}
else SPIReceiveIndex++;
}
Also I still don't seem to be receiving the data I expect. Are there any timing considerations?

- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
In the slave code, I would have checked the SPRF and read the data, followed by stuffing of byte to be sent... something like this
- byte SPItransfer_ForSlave (byte val)
- {
- byte return_data;
- // First receive, then keep the register updated with val
- while(!SPIS_SPRF);
- return_data = SPID;
- SPID = val;
- return return_data;
- }
