Pages: 1 2 [3] 4 5 ... 7   Go Down
Author Topic: Arduino as SPI slave?  (Read 7680 times)
0 Members and 1 Guest are viewing this topic.
nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8452
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you could use SPI CLK directly into the SR and counter (gated by SS) and Qc to write the FIFO.

As the FIFO writes on the falling edge it will write just before the 9th clock pulse (when Qc goes low) so as long as the propagation delay of the SR isn't so fast (and the Qc signal slow) that it violates the FIFO hold time (unlikely) you should be OK.

There is a potential race condition with Qc probably happening at the same time as the SR OPs change. maybe the SR could use an inverted version of SPI CLK so it's running out of phase.

Just thinking out aloud, pity we don't have a white board.

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 439
Posts: 23751
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yeah, Qd only works every other byte.

I thought the open collector NAND was a pretty good solution. If all SS & the Qx are low, then the output is controlled by the SS clock.
Thinking maybe run SPI Clock thru couple stages of spare 74LS32 to move it out past the Qa transition.

FIFO writes in with W going high. Got to treat it like a latch.
Logged

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.

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 439
Posts: 23751
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

http://www.farnell.com/datasheets/57883.pdf

"Data set-up and hold times must be adhered to, with respect to the rising edge of the Write Enable (W)."

See Figure 3.
Logged

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.

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8452
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Qd only works every other byte.
Yep, I changed it to Qc.

WRT the W/ signal, I just read the first line in the data sheet

Quote
WRITE ENABLE ( W ) — A write cycle is initiated on the falling edge of this
input

And figured it wrote on the falling edge, but then there's the next sentence

Quote
Data set-up and hold times must be adhered to,with respect to the rising edge of the Write Enable

So yes it's rising edge, so wouldn't an inverted Qc still work?

______
Rob
« Last Edit: August 31, 2011, 09:14:10 pm by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 439
Posts: 23751
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Just realized I had the W/ pulse drawn wrong - the '06 output goes to the FIFO, SPI Clk goes to the shift register clock.

The data has to be out of the shift register 12-15-18nS before the Write pulse goes high.
Data takes 10nS to go thru shift register after the clock. So I think Qc/ would go high too early unless I delay it.

I'm gonna dig up a couple parts & give it a try.
Not sure if I have a LS161, think I have some LS193's aound.
Logged

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.

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8452
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I love these kind of circuits having made a few logic analyzers over the years, but is all this circuitry really necessary?

An AVR could easily work as a FIFO, as I said in a previous post as long as it doesn't have to do anything else it could sample at full speed I'm sure. So using a 1284 will give a FIFO of up to 16k bytes. Then transfer the data to the host Arduino or just make it standalone.

Any Arduino could to this, so I don't think I understand the original problem smiley, I'll review the posts.

______
Rob

Logged

Rob Gray aka the GRAYnomad www.robgray.com

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 439
Posts: 23751
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Rob,
Here's what I was able to confirm using 74LS163A, 74LS04, 74F32.
The 2 signals are the Clear into the '163 (bottom) and the W/ at the 'F32 pin 11.
I had to run it as discrete writes like this
Code:
int SS = 10;  // need for SPI
byte byte1 = 0x55;
byte pin13 = 13;

void setup(){
pinMode (SS, OUTPUT);
pinMode (pin13, OUTPUT);
}

void loop (){
byte x=0;
byte y=0;
digitalWrite(SS,LOW);
while (x<33){
digitalWrite(pin13, y);
y=1-y;
x=x+1;}
digitalWrite(SS,HIGH);
}
Any time I tried to go faster, or to set my scope to faster than 10uS/div, I got so much aliasing I couldn't make out anything.
I varied between x = 17 for 8 clock pulses to the counter, adn 33 for 16 pulses.
The final low going pulse out of the last OR gate was confirmed to match up with the high portion of the 8th clock pulse in the 1 and 2 byte simuation.
The wired-Or wasn't working too well, had too low of a pullup resister so the signal didn't come up sharp. Tried the '32 instead of hunting for another resistor to see if I could get a cleaner edge, and did, and then fooled around seeing how fast I could go.
Was not able to run with actual SPI clock pulses and capture data with this USP scope.  Need something better.
I don't see any glitches where I thought they might occur, so I think the routing of the clock thru the gates is gonna take care of that.

Now to order some FIFOs. Newark UK (and US) has them, $20 handling charge!

Circuit might be overkill to monitor the SPI bus, but the software solutions Nick G was trying didn't seem to be working.
This way we can sample for as much as the FIFO will allow. IDT makes 64K parts, if they can be located.
I think the biggest I was was 8K.


* SPI_Sniffer_logic_test_sch.jpg (78.92 KB, 960x720 - viewed 11 times.)

* SPI_Sniffer_logic_test.jpg (110.5 KB, 960x720 - viewed 10 times.)
« Last Edit: September 01, 2011, 01:57:57 am by CrossRoads » Logged

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.

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 439
Posts: 23751
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here we go - 64K x 9!

http://search.digikey.com/scripts/DkSearch/dksus.dll?Detail&name=800-2143-ND
1 part is Cheaper than 2 8kx9 parts from Newark/Farnell UK and without the extra $20 handling fee.

If I put a pair on, I could do high speed audio sampling and let the SdFat library store it to SD card.

Getting some ideas ...
Logged

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.

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8452
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
or to set my scope to faster than 10uS/div, I got so much aliasing I couldn't make out anything.
Then you need a way better scope, or even better a logic analyzer.

Quote
Here we go - 64K x 9!
Jeez, do they still make PLCCs?

______
Rob
Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Back to the base question. What about using a 74HC595 shift register and a 74HC93 counter without FIFO? Looking at my oscilloscope measures the clock speed is 4 MHz and one byte arrives every 6,5 us. Since the shift register is triggered at the positive egde and the counter at negative edge I'm thinking one could use the same clock signal (SCLK) and setup the 7493 as a mod-8 counter. The only additional logic needed would be ~Qb & ~Qc & ~Qd & ~SS connected to the shift register latch clock and to an interrupt pin on the Arduino. Reading parallell inputs every 6,5 us wouldn't be a problem I guess? Otherwise polling could be done in a tight loop.

Wiring ~SS to shift register reset and to MR1 and MR2 on the counter would reset both the counter and shift register on SS high -> low.

Only problem is that this occupies 9 input pins on the Arduino. My goal is to monitor the heater controller and I'll need some of those pins. I'm thinking maybe using two Arduinos, one for monitoring SPI and one for alarm, onewire and hall sensor input.

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8452
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Everything you describe is already present in the CPU, it's called an SPI interface. I can't see how moving the logic outside will help.

I think you can record bytes every 6.5uS but I haven't tried I admit. This is the fastest code I can think of

Code:
byte buffer [100];
byte *buffer_end = buffer + sizeof(buffer) + 1;
byte *pos = buffer;
byte mask = (1<<SPIF);  // assume this will wind up in a reg and so will be faster than a literal
byte temp;

do {
  while(!(SPSR & mask));   
  temp = SPSR; // dummy read to setup a clear of SPIF
  *pos++ = SPDR;  // get the data and clear SPIF
} while (pos < buff_end)

That will record 100 bytes then exit. After that you print the array to the serial port.

If that (or something similar) doesn't do the trick then it doesn't doesn't matter how many Arduinos you have you need either a faster processor, write the code in assembler, or use some hardware like what Crossroads has designed. 

______
Rob
« Last Edit: September 01, 2011, 08:13:30 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Everything you describe is already present in the CPU, it's called an SPI interface. I can't see how moving the logic outside will help.

The AVR running as a slave samples the clock signal in software. That is the reason to why the 4 MHz clock signal is missed. The clock is not high long enough for the AVR to recognize it as a clock pulse. This could be solved using an external shift register?

Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8452
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
as a slave samples the clock signal in software.
Not sure where you get that from, AFAIK its all done with hardware.

However there is a speed limitation and unfortunately the data sheet is a bit ambiguous here

Quote
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.

So does that mean 3 clock cycles?

Bottom line is that without some really good code you will never know if it's the hardware or the software that's not working.

Quote
This could be solved using an external shift register?
That's true if the SPI can't use a 4MHz clock.

Quote
Only problem is that this occupies 9 input pins on the Arduino. My goal is to monitor the heater controller and I'll need some of those pins
So this is needed permanently on the final application is it?

______
Rob
« Last Edit: September 01, 2011, 09:21:14 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 439
Posts: 23751
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@rob,
Yes, better 'scope or logic analzer would certainly help. I bet wirewrapping this up would help also, signals are pretty crappy looking with jumper wires all over a breaboard.

@torgil,
What you describe in #39 is what I have working in #36 (just control signals so far). You can do it without the FIFO - capture serially in one shift register, move in parallel to a 2nd, and read it in serially with SPI command, that way its hardware all the way thru and not software sampling.
Have to check the control signals, make sure the parallell load signal is seperate from the clock out signal.
Still have to know when to bring the data in - so use the same parallel load signal to the 2nd shift register to create an interrupt to read the data?
I think interrupts have the same issue of having to be valid in time to be clocked in.
Logged

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.

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 452
Posts: 18694
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here's some test code ...

Master:

Code:
// Written by Nick Gammon
// September 2011

#include <SPI.h>
#include "pins_arduino.h"

void setup (void)
{
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  
}  // end of setup

void loop (void)
{
  delay (2000);

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  for (byte i = 0; i < 255; i++)
    SPI.transfer (i);

  // disable Slave Select
  digitalWrite(SS, HIGH);

}  // end of loop

This sends out 255 bytes (where each byte is itself, ie. 0, 1, 2, 3, 4, 5 etc.).

Slave:

Code:
// Written by Nick Gammon
// September 2011

#include "pins_arduino.h"

byte buf [256];
byte pos;

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

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  
  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

}  // end of setup

// main loop - wait for flag set in interrupt routine
void loop (void)
{

    Serial.println ("Starting ...");
    pos = 0;
    
    while (pos < 255)
    {
    /* Wait for reception complete */
    while(!(SPSR & (1<<SPIF))) {}
    buf [pos++] = SPDR;
    }
    
    // check valid
    Serial.println ("Checking ...");
    for (byte i = 0; i < 255; i++)
      if (buf [i] != i)
        {
        Serial.print ("Error at position ");
        Serial.print (i, DEC);
        Serial.print (" got ");
        Serial.println (buf [i], DEC);
        return;  
        }
        
    Serial.println ("Passed.");        
}  // end of loop

Now to save CPU cycles the slave does not use interrupts. It uses a tight loop waiting for the byte to appear in the hardware register.

Once 255 bytes have arrived it checks that each byte is itself (eg. 0, 1, 2, 3, 4, 5 ...).

My results with the above code are:

Code:
Starting ...
Checking ...
Passed.
Starting ...
Checking ...
Passed.
Starting ...
Checking ...
Passed.
Starting ...
Checking ...
Error at position 198 got 199
Starting ...
Checking ...
Error at position 0 got 254
Starting ...
Checking ...
Passed.
Starting ...
Checking ...
Error at position 153 got 154
Starting ...
Checking ...
Error at position 0 got 254
Starting ...
Checking ...
Error at position 0 got 254
Starting ...
Checking ...
Passed.
Starting ...
Checking ...
Passed.
Starting ...
Checking ...
Passed.
Starting ...
Checking ...
Passed.

So it seems to sometimes send all 255 bytes without error. But sometimes not. And this is with clock/8.

With this instead:

Code:
 SPI.setClockDivider(SPI_CLOCK_DIV16);

... it ran without errors.
« Last Edit: September 01, 2011, 07:01:58 pm by Nick Gammon » Logged

Pages: 1 2 [3] 4 5 ... 7   Go Up
Jump to: