Let's say I need to send 16 bits of data to a device at 44khz. That's 704,000 bits per second. My Arduino is running at 16mhz. And the default SPI divider is 4. So the SPI bus by default runs at 4mhz, but I only actually need it to be able to send 1 million bits per second.
Is there any advantage to be gained by slowing the SPI bus down? Will it use less CPU time? Or will I use less CPU time by speeding it up? The chip I'm sending data to can handle data at 20mhz, so I could set the SPI bus to the fastest speed... 16mhz/2... and the Arduino still couldn't outpace it.
So what should I do? Speed it up, slow it down, or just leave it as is because changing the speed will have no effect at all on the speed at which my program executes?
If you send more than one byte at a time, you need to wait for the first byte to shift out before sending the second one. The faster you send the less time you need to wait.
Typically you'll want to run the fastest you can and then start reducing speed if you have problems. With a multi-MHz TTL interface the problems will mostly be bad transmission line characteristics. Cables more than a couple inches would be one example. I see this with ShiftBrite setups occasionally. Sometimes it's possible to measure the amount of ringing and calculate the right termination for the cable to continue running at higher speeds.
So when you call the function to send a byte out over hardware SPI, does the function return immediatley, or after the transfer of the byte has completed?
It returns immediately. Most coders do a busy loop watching the completion flag. At 8 bit times there's not much reason to call and return from a function for every byte.
You're not calling a function, you're putting a byte into a register. Then the SPI electronics do the rest. If you try to write into the register before the last byte has been written, the AVR just won't do it. So you'll lose whatever byte you tried to send second.
I don't really understand what that's doing, but since you mentioned registers, maybe SPDR is a register.
It looks like this function does in fact wait for something. I suspect that is for the transfer to finish, because the documentation for the SPI lib makes no mention of having to wait or check any bits before you attempt the next write.
How might I change this code so it doesn't set the CS bit high after transferring the first byte, so I can transfer a second to my DAC which requires 16 bits in a row?
I guess I'll look at the Arduino datasheet and see if I can find these registers in there. I'm not sure how I'm supposed to know the constants used for different registers.
Oh...there's an SPI lib. Not sure why, it's pretty simple to do once you have the SPI registers configured correctly.
Rather than continuing to answer questions piecemeal like this, definitely take yourself up on your suggestion to read the AVR datasheet. Most new users seem to avoid it at all costs...you're growing up, we'll make an engineer out of you yet! wipes a tear
The thing is, I don't have much time to get this working. I have to finish the design of this circuit by the end of the week. And I could look at the datasheet all day but in the end all I can do is guess about whether I understand something or not.
For example, the datasheet seems to indicate the SS pin isn't modified when you transfer a byte. But then there is a diagram of how the data is sent when you initiate a transfer and the SS pin is being shown going high and low. So which is it? Is it set high after a single byte is transferred, or not? The data sheet says it's not, but some posts I've read here says it does, and the digaram indicates it does, so I have no idea what's right.
SPI is actually transferring in both directions at once: it's clocking data from MISO into a serial-in shift register at the same time it's sending data via a serial-out shift register through MOSI. If the slave isn't sending data on MISO, the SPDR will contain garbage at the end of the transfer.
The SS line toggles to mark the beginning and end of a "transfer", which is usually a single byte, but doesn't have to be: some SPI peripherals I've seen are designed to accept a couple or three bytes per transfer, instead of one. There could also be ones that do longer strings that I don't know about. I haven't interfaced any of those multi-byte peripherals to an Arduino, so I don't know whether the library's handling of SS will cause problems with them.
The SPI Data Register is a read/write register used for data transfer between the Register File
and the SPI Shift Register. Writing to the register initiates data transmission. Reading the register
causes the Shift Register Receive buffer to be read.
What? Simply looking at the data register or writing a value to it causes some action to be taken? No command beyond simply writing the data needs to be given to the processor to cause it to take this action?
I always thought of registers just as little fast access memory locations on the CPU. I don't think I ever encountered a situation when I was working with them on a PC where writing one alone could cause something to happen.
Not hard to conceptualize really. Say the pulse that writes data into SPDR also clocks a FF that releases a counter and gates a clock through to a shift reg. The timer allows 8 clock pulses to the SR then resets the FF which stops the SR and counter.
Result, data gone out the MOSI pin.
_BV = Bit Value, a macro I think that will eveluate to 1000000 or bit 7 which is the location of the SPIF flag.
So the code is ANDing the SPSR reg with 1000000, if the result is 0 then the flag is not set and therefore the byte has not been fully transmitted.
Not hard to conceptualize really. Say the pulse that writes data into SPDR also clocks a FF that releases a counter and gates a clock through to a shift reg. The timer allows 8 clock pulses to the SR then resets the FF which stops the SR and counter.
_BV = Bit Value, a macro I think that will eveluate to 1000000 or bit 7 which is the location of the SPIF flag.
So the code is ANDing the SPSR reg with 1000000, if the result is 0 then the flag is not set and therefore the byte has not been fully transmitted.
Hm...
while (!(SPSR & _BV(SPIF))) ;
So SPSR is a register, and _BV(SPIF) is a macro which converts the constant SPIF into the binary balue 1000000. Presumably the value of SPIF is either 6 or 7.
And the SPIF bit does this:
? Bit 7 – SPIF: SPI Interrupt Flag
When a serial transfer is complete, the SPIF Flag is set. An interrupt is generated if SPIE in
SPCR is set and global interrupts are enabled. If SS is an input and is driven low when the SPI is
in Master mode, this will also set the SPIF Flag. SPIF is cleared by hardware when executing the
corresponding interrupt handling vector. Alternatively, the SPIF bit is cleared by first reading the
SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR).
So somehow... in the cpu, that SPIF bit is cleared for me by the act of checking to see if the bit is set, and the act of returning SPDR from the function.
Oy.
So many acronyms. Why can't there be some kind of identifier in these register names so I know when I'm looking at a register or a constant?
Let's say I don't need to read anything from the SPI bus. Would it be more efficient and possible to do this?
byte SPIClass::transfer(byte _data) {
while (!(SPSR & _BV(SPIF))); // Wait for previous transfer, if any, to complete.
SPSR = SPSR & !_BV(SPIF); // Set SPIF bit in SPSR register to 0.
SPDR = _data; // Begin transfer of next byte.
}
The idea here is that since I can do other things while I'm waiting for the transfer to complete, why sit around waiting for that to happen? By the time I go to transfer another byte the transfer will probably have completed, but if not, the function will wait. And in general even if it did have to wait, it would waste less time than it would if every time I initiated a transfer I waited for it to finish.
What do ya think?
(I'm not sure if it's okay to just reset the SPIF bit like that.)