Pages: [1]   Go Down
Author Topic: Hardware SPI questions  (Read 11831 times)
0 Members and 1 Guest are viewing this topic.
Manchester, New Hampshire
Offline Offline
Edison Member
*
Karma: 1
Posts: 1283
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys,

I'm studying how to do hardware SPI because I don't think doing it in software is going to be fast enough to write to a DAC at the sampling rates I need.

I've already discovered that to do hardware SPI I need to connect my DAC to specific pins.  SPI may use any or all of the following:

D10 - CS aka Chip Select aka SS aka Slave Select
D11 - SDI aka ??? aka MOSI aka Master Out Slave In aka Output
D12 - ??? aka ??? aka MISO aka Master In Slave Out aka Input
D13 - CLK aka SLK aka Serial Clock

What I need to know is this:

1) Do I need to connect pin 10 to the DAC, if it is the only thing I am communicating with?  Could I stick a pullup/pulldown resistor on the DAC's CS pin instead to keep it eneabled?

2) If I can get away without connecting pin 10 to the DAC, can I put it to other use without issue, or will the hardware SPI mess with the pin?

3) Question 2 applies to pin 12 as well.  The DAC has no way to send data back to the atmega, so that pin will be connected to nothing.  Can I use it for something else without screwing up my communications, and without the communications messing with whatever's on the pin?
Logged

Manchester, New Hampshire
Offline Offline
Edison Member
*
Karma: 1
Posts: 1283
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I found the page for the SPI library:
http://arduino.cc/en/Reference/SPI

It says the following:

Quote
On the Arduino Duemilanove and other ATmega168 / 328-based boards, the SPI bus uses pins 10 (SS), 11 (MOSI), 12 (MISO), and 13 (SCK). On the Arduino Mega, this is 50 (MISO), 51 (MOSI), 52 (SCK), and 53 (SS). Note that even if you're not using the SS pin, it must remain set as an output; otherwise, the SPI interface can be put into slave mode, rendering the library inoperative.

When they say "even if you're not using the SS pin, it must remain set as an output" do they mean you can't do anything with the pin, or is it just a warning that if you do do anything with the pin, like blink an LED, it's gotta be used as an ouput pin?


Also:
http://arduino.cc/en/Reference/SPITransfer

This transfer function sends and recieves a byte at the same time.  What happens if after I set up my SPI communications I set pin 12 to output and use it for other things and then call this function?  Will I just get garbage back?  Will it toggle pin 12 back to an input?
« Last Edit: October 11, 2010, 05:14:23 am by scswift » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 508
Posts: 31390
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The DAC has no way to send data back to the atmega, so that pin will be connected to nothing.  Can I use it for something else without screwing up my communications,

Yes
Logged

Manchester, New Hampshire
Offline Offline
Edison Member
*
Karma: 1
Posts: 1283
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So how about pin 10?  As long as I leave that set to output, can I do other things with that?  Or will the SPI lib pull it low every time I try to send a byte to the DAC?
Logged

Rural Arizona
Offline Offline
Edison Member
*
Karma: 7
Posts: 1711
Incorrigible tinkerer
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So how about pin 10?

It's absolutely essential to "real" SPI (occasionally, you'll see a manufacturer call some other shift-register-based interface "SPI" when it's not the same as the original Motorola design.  You need to watch out for that when picking parts):  it tells the slave "This data  is for you" and "This is where the byte starts and ends".  So you can't just tie it low if you have only one slave.
Logged

Manchester, New Hampshire
Offline Offline
Edison Member
*
Karma: 1
Posts: 1283
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks.  That confirms what I read earlier this morning when trying to figure out how to communicate with my dac:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1286797300

My main problem now is that I think I can't use hardware SPI to communicate with this DAC because I think it expects 16 bits before the CS pin goes high again.
Logged

Manchester, New Hampshire
Offline Offline
Edison Member
*
Karma: 1
Posts: 1283
Propmaker
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Got another question about hardware SPI.

The DAC I want to talk to requores 16 bits before the CS pin goes high.

Yet from what I've read, it seems the Arduino's hardware SPI library sets the CS pin high after each bit you tell it to send.

Posts by Grumpymike and others have indicated that you may need to bit bang if you want to send a 16 bit word to an SPI device because the Arduino's hardware can't handle that.

But I was reading the ATMega328's datasheet, and it had this to say on page 168:

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

Now that sure sounds to me like the library is at fault here, and that the library must be the one setting the CS/SS pin high and low and that the hardware transfer that takes place has nothing to do with that pin's state being changed.  Is that correct?

If so, it sure would be nice if the hardware SPI lib had a function to send 16bits at once, or a function that sent a byte but didn't toggle the SS/CS pin at the start and end of the transmission.
Logged

Cape Town South Africa
Offline Offline
Edison Member
*
Karma: 19
Posts: 1183
A newbie with loads of posts, and still so much to learn !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I know this thread is a bit old now, but it came up in a search about SPI.

I am using just the clock and data ( SCK  and MOSI ) outputs with a SPI.transfer(a); type instruction.

I am not driving a real SPI device, just some shift registers.

I completely forgot about the SS and MISO pins 10 and 12 being used by the SPI library, and I used them for completely different functions, and luckily it all works fine.

It was also luck that  I had pin  12 as an input and 10 as an output, as the SPI spec requires.
Logged

With my mobile phone I can call people and talk to them -  how smart can you get ?

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

From the SPI wiki page:

Quote
Note that even if you're not using the SS pin, it must remain set as an output; otherwise, the SPI interface can be put into slave mode, rendering the library inoperative.

I was initially confused about this too until I read the ATmega328 documentation. The important thing is that pin 10 be configured as an output, the value of it is then ignore by the SPI hardware.

The Atmega documentation says:

Quote
If SS is configured as an output, the pin is a general output pin which does not affect the SPI system.

This means you can usefully set it high and low yourself to tell your peripheral that you are about to send data to it (with SPI.transfer). The library doesn't do this for you because it doesn't know for sure which pin you are going to use for the SS pin (you might have multiple peripherals).

As for the 16 or more bits, I don't see what is stopping you sending more than 8 bits before raising SS back to high. For example, this test code appears to "work", at least, connected to a logic analyzer:

Code:
const char * test = "Hello world";

 SPI.begin ();
 char c;
 const char * p = test;

// commence "transaction"
 digitalWrite(SS_PIN, LOW);  // this is pin 10 in SPI.h
 
// send test string
for ( ; c = *p; p++)
  SPI.transfer (c);

// end of transaction
 digitalWrite(SS_PIN, HIGH);
 SPI.end ();

Analysing the Ethernet shield in operation appears to confirm that holding the SS pin low for extended transfers is perfectly normal.

The constructor for the inbuilt SPI library appears to configure all 4 pins in the correct directions, so you shouldn't need to change them yourself, unless you are planning to use a different SS pin (in which case you also need to set that to output).

But as I said above, it appears that the library does not manage the SS pin for you apart from setting pin 10 as an output.
Logged

Cape Town South Africa
Offline Offline
Edison Member
*
Karma: 19
Posts: 1183
A newbie with loads of posts, and still so much to learn !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Nick, that explains the SS function a  lot better, I wont worry about changing pin 10 now.

I am feeding a row of shift registers to run a display,and the latching is done externally from the micro, so I just bang all the pixel pattern bits ( at the right time ) without using the SS function at all .


     SPI.transfer(h);
     SPI.transfer(hx);   and so on.


I suppose I could make my 2 bytes  into a sixteen bit word , but it works fine like this, and makes the lookup table smaller.

I have just noticed that I don't even take the SS low at the beginning and it works fine .....  (  a little knowledge is a dangerous thing  :-)  I am a newbie  )
  

On another project I take SS low and then send 50 bytes before bringing it high again to latch the registers.


 

      
Logged

With my mobile phone I can call people and talk to them -  how smart can you get ?

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

Glad I could help. smiley

According to some documentation I read, you could leave SS low (eg. tie it to ground at the peripheral end) and that would work with some devices but not others.

However some other devices (apparently) do not respond until they see the high-to-low transition. This makes a certain amount of sense, because otherwise a single glitch on the clock line could throw everything out by one bit, forever.

The act of pulling SS low effectively synchronizes sending and receiving, at least for those devices that look for such a transition.
Logged

Cape Town South Africa
Offline Offline
Edison Member
*
Karma: 19
Posts: 1183
A newbie with loads of posts, and still so much to learn !
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, I pull the shift registers latch low and high from the external circuit to latch it all in.
I should really do a notSCLR  between data I suppose to make sure it doesn't get out of sync?
Logged

With my mobile phone I can call people and talk to them -  how smart can you get ?

Pages: [1]   Go Up
Jump to: