Issue using SPI and Serial at the same time

Hi,

I have an ATMega2561 trying to run SPI and print back using Serial, but I'm encountering an issue when trying to do both in the same sketch.

I'm running this code:

#include "SPI.h"
void setup() {
  // put your setup code here, to run once:
  SPI.begin();
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  for(int i = 0; i < 50; i++)
  {
    Serial.println(i);
    SPI.transfer(i);
  }
}

And I get this output:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

On a logic analyzer, I see that only up to 42 gets written on the MOSI line, and then the transmissions stop. What this tells me is that sometimes, the SPI transfer does not get trigger, and possibly gets stuck waiting to put data on the MOSI line. When I remove the Serial print statement, SPI works perfectly (loops through 0-49 on the MOSI line continuously). I think this has something to do with the UART global interrupt pre-empting the SPI interrupt triggered by the write to SPDR, but I'm not sure. Does anyone have any thoughts?

Try sending bytes instead of ints.

ATMega2561

What core do you use? Which board is selected?

pylon:
What core do you use? Which board is selected?

I am using a custom board, flashed with an Arduino board definition and bootloader. Not sure what you mean by core -- the 2561 is the core.

Try swapping the print statements, the SPI is much faster. You are on the correct track, the arduino hardware is the master and does not require any hardware response from the slave however your protocol may change that. You may also put a delay between the print statements, Reason it looks like you are suffering from a serial flood, IE sending more data then the non SPI serial interface can process. you can validate this by changing baud rate on the serial console and redo the counts. This response is to help you get started in solving your problem, not solve it for you.
Good Luck & Have Fun!
Gil

gilshultz:
Try swapping the print statements, the SPI is much faster. You are on the correct track, the arduino hardware is the master and does not require any hardware response from the slave however your protocol may change that. You may also put a delay between the print statements, Reason it looks like you are suffering from a serial flood, IE sending more data then the non SPI serial interface can process. you can validate this by changing baud rate on the serial console and redo the counts. This response is to help you get started in solving your problem, not solve it for you.
Good Luck & Have Fun!
Gil

Thanks for your response. I don't think Serial flood is the issue. I tried adding a delay between the Serial print statement and the SPI transfers. Interestingly enough, the longer the delay I added, the less amount of SPI transfers happened.

I tried again with the following code:

#include "SPI.h"
void setup() {
  // put your setup code here, to run once:
  SPI.begin();
  //Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  for(int i = 0; i < 50; i++)
  {
    delay(10);
    SPI.transfer(i);
  }
}

This caused the SPI to transfer once, and then not transfer again, so now I'm not sure it actually is a UART issue. After doing some experimenting, it seems that the longer you delay between SPI transactions, the less likely it is that the transfers go through. Now I'm really stumped :confused:

I have executed your codes of Post#5 without delay(10) and with delay(0) in UNO (ATmega328P); in both cases, the SPI.transfer() has been executed for 50 times as defined by the index i.

#include "SPI.h"
byte counter = 0;

void setup() 
{
  Serial.begin(9600);
  SPI.begin();
}

void loop() 
{
  for(int i = 0; i < 50; i++)
  {
    //delay(10);
    SPI.transfer(i);
    counter++;
  }
  Serial.print(counter);
  while(1);
}

sm27.png

sm27.png

So after doing some testing, I have determined that the problem actually does not have to do with UART, but instead with some sort of internal timer. Basically, if there is a non-negligible time between SPI transfers (>3us), SPI simply stops transmitting ~20ms after SPI.begin() is called. I have a feeling this is some sort of timer interrupt issue because the ~20ms is pretty consistent.

jrsstill:
So after doing some testing, I have determined that the problem actually does not have to do with UART, but instead with some sort of internal timer. Basically, if there is a non-negligible time between SPI transfers (>3us), SPI simply stops transmitting ~20ms after SPI.begin() is called. I have a feeling this is some sort of timer interrupt issue because the ~20ms is pretty consistent.

The explanation does not seem to be rational. You may connect two UNO by SPI Port and then study the behavior of the SPI.h Library. The following diagram, could be helpful in the study. If you want to read/store a data byte sent by Slave in response to byte x = SPI.transfer(0xnn) instruction, you have to wait at least for 8 us as the default speed is 125 kHz.
spi328x.png

spi328x.png

I am using a custom board, flashed with an Arduino board definition and bootloader. Not sure what you mean by core -- the 2561 is the core.

The Arduino IDE by default doesn't offer a board setting for an ATmega2561. If you just select the Mega2560 the wrong settings are applied. So which board is selected in the Tools menu of the IDE? Do you use the standard AVR core of the Arduino IDE?

If you compile for the wrong processor you may see nondeterministic behavior. Although the 2561 is quite similar to 2560 it has less capabilities which may result in failures.