Go Down

Topic: Arduino as SPI slave? (Read 10 times) previous topic - next topic

Nick Gammon


I'm trying to use an Arduino to eavesdrop SD card writes from a heater system controller (AVR based). I've soldered wires on the SD card holder and converted the signal from 3v3 to 5v0.

I've tried to change clock phase, clock polarity and bit order without any progress. Arduino source code:

Code: [Select]

...

void setup (void)
{
  Serial.begin (9600);   // debugging

  // setup pins
  pinMode(MISO, OUTPUT);
  pinMode(MOSI, INPUT);
  pinMode(SS, INPUT);
  pinMode(SCK, INPUT);
 
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

 ...
 
}  // end of setup





This looks like my code for an SPI slave. That's nice that someone is reading it!

I wouldn't do this:

Code: [Select]
  pinMode(MISO, OUTPUT);

You are eavesdropping, right? So no need to configure output pins.

I would stick with the ISR - SPI is pretty fast, and not using an ISR is not going to help you very much.

When testing the SPI master/slave setup I had to drop down the clock rate that the master sent at. Otherwise the slave can't keep up. With the master clocking out at maximum rate, there aren't many spare clock cycles for the slave to do stuff in, like storing what it got.

From your scope output the clock polarity is clearly normal. It is usually low, and goes high to pulse (like on my web page). What pins are you hooking up to - ie. what is your wiring?

Can you zoom in on the first character from the AVR? It is hard to see what it is. And report what the timebase is, that is, the time difference between clock pulses.

Nick Gammon

Now that I look at the graphic again, it looks like it is  1 uS per division. So a byte is clocked out in 2 uS, is that right?  That's too fast to monitor, I had to slow down my master somewhat when testing that code. And it isn't the code's fault. :)

Unless you can slow down the AVR (perhaps you can) you might need faster hardware. For example, an FPGA board might be able to capture it fast enough, in bursts.

CrossRoads

"you might need faster hardware.  For example, an FPGA board"    No no no!
You've got faster hardware in the '328 doing the monitoring - just need to figure out how to use it.

Nick, go take a look here. This unit is described as being a '328 that uses SPI to receive data from a master to display on a screen.  Should be able to clean this up to accept a variable number of bytes & load into an array for spitting out via the serial port later.  Ditch the EEPROM stuff, ditch the screen display stuff.

I am very interested in this for they dual ATMega I've got in the works.  I'm thinking should be similar to code up as reading from Serial port when data comes in.

http://www.arduino.cc/playground/Code/RGBBackpack
Go down to this link
http://www.sparkfun.com/datasheets/Components/RGB_Backpack_v4.zip

See Also section 18 of the data sheet:
18. SPI - Serial Peripheral Interface
18.1 Features
• Full-duplex, Three-wire Synchronous Data Transfer
• Master or Slave Operation
• LSB First or MSB First Data Transfer
• Seven Programmable Bit Rates
• End of Transmission Interrupt Flag
• Write Collision Flag Protection
• Wake-up from Idle Mode
• Double Speed (CK/2) Master SPI Mode

The Serial Peripheral Interface (SPI) allows high-speed synchronous data transfer between the
ATmega48PA/88PA/168PA/328P and peripheral devices or between several AVR devices.

The interconnection between Master and Slave CPUs with SPI is shown in Figure 18-2 on page
167. The system consists of two shift Registers, and a Master clock generator. The SPI Master
initiates the communication cycle when pulling low the Slave Select SS pin of the desired Slave.
Master and Slave prepare the data to be sent in their respective shift Registers, and the Master
generates the required clock pulses on the SCK line to interchange data. Data is always shifted
from Master to Slave on the Master Out - Slave In, MOSI, line, and from Slave to Master on the
Master In - Slave Out, MISO, line. After each data packet, the Master will synchronize the Slave
by pulling high the Slave Select, SS, line.
When configured as a Master, the SPI interface has no automatic control of the SS line. This
must be handled by user software before communication can start. When this is done, writing a
byte to the SPI Data Register starts the SPI clock generator, and the hardware shifts the eight
bits into the Slave. After shifting one byte, the SPI clock generator stops, setting the end of
Transmission Flag (SPIF). If the SPI Interrupt Enable bit (SPIE) in the SPCR Register is set, an
interrupt is requested. The Master may continue to shift the next byte by writing it into SPDR, or
signal the end of packet by pulling high the Slave Select, SS line. The last incoming byte will be
kept in the Buffer Register for later use.
When configured as a Slave, the SPI interface will remain sleeping with MISO tri-stated as long
as the SS pin is driven high. In this state, software may update the contents of the SPI Data
Register, SPDR, but the data will not be shifted out by incoming clock pulses on the SCK pin
until the SS pin is driven low. As one byte has been completely shifted, the end of Transmission
Flag, SPIF is set. If the SPI Interrupt Enable bit, SPIE, in the SPCR Register is set, an interrupt
is requested. The Slave may continue to place new data to be sent into SPDR before reading
the incoming data. The last incoming byte will be kept in the Buffer Register for later use.

The system is single buffered in the transmit direction and double buffered in the receive direction.
This means that bytes to be transmitted cannot be written to the SPI Data Register before
the entire shift cycle is completed. When receiving data, however, a received character must be
read from the SPI Data Register before the next character has been completely shifted in. Otherwise,
the first byte is lost.

In SPI Slave mode, the control logic will sample the incoming signal of the SCK pin. To ensure
correct sampling of the clock signal, the minimum low and high periods should be:
Low periods: Longer than 2 CPU clock cycles.
High periods: Longer than 2 CPU clock cycles.

When the SPI is enabled, the data direction of the MOSI, MISO, SCK, and SS pins is overridden
according to Table 18-1 on page 168.

and it goes on a few pages more.
Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Nick Gammon


  No no no!
You've got faster hardware in the '328 doing the monitoring - just need to figure out how to use it.


I'll look at the links in a minute, but I note from the datasheet pages you quoted:

Code: [Select]

   ; Enable SPI, Master, set clock rate fck/16
   ldi r17,(1<<SPE)|(1<<MSTR)|(1<<SPR0)
   out SPCR,r17


It's interesting, isn't it, that in their own example code they slow down the clock to fck/16?

In my code example I had this:

Code: [Select]
// Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);


I got away with slowing the master down to 1/8 clock, they showed 1/16 in the example code.

CrossRoads

I will say upfront I only glanced thru to see what kind of stuff was there.
Programming at  the lower level is not my current forte - but I bet if the EEPROM & display stuff is taken out, that code could be run faster.
I'm thinking something like this, only I haven't dug in to see what is  needed to recognize the data byte is finished being clocked in:
array_name [size_limit]
end_array = size_limit+1;
array_pointer = 0;  // start at beginning of array
while (array_pointer <end_array){
    if (register has data){ 
    array_name[array_pointer] = register_contents;
    array_pointer = array_pointer+1;
    }
}

And somehow get checking the SS line around that to know when to  start this.
What's it take to make this work?
Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Go Up