SPI clock has only 3 effective settings

I am using SPI to talk to an external chip. I want to use a 1 MHz SPI clock, but apparently that is not possible. Using the Duemilanove with ATMEGA328P-PU chip and 16 MHz xtal, Arduino 0019 dev environment, looking at the SPI clock line (digital pin 13) on a scope, I found the following results based on the argument to SPI.setClockDivider():

SPI_CLOCK_DIV2 gives me a 4.0 MHz SPI clock
SPI_CLOCK_DIV4 gives me a 4.0 MHz SPI clock
SPI_CLOCK_DIV8 gives me a 2.0 MHz SPI clock
SPI_CLOCK_DIV16 gives me a 2.0 MHz SPI clock
SPI_CLOCK_DIV32 gives me a 250 kHz SPI clock
SPI_CLOCK_DIV64 gives me a 250 kHz SPI clock
SPI_CLOCK_DIV128 gives me a 250 kHz SPI clock

If this is the intended behavior, I think the documentation should point this out.

By the way, I measured the actual value of my clock crystal at 15.999976 MHz, with a counter of about 1 ppm accuracy.

This looks like a bug in the SPI library. Currently it has:

void SPIClass::setClockDivider(uint8_t rate)
{
  SPCR = (SPCR & ~SPI_CLOCK_MASK) | (rate & SPI_CLOCK_MASK);
  SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | (rate & SPI_2XCLOCK_MASK);
}

The last line should be replaced with:

SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate & (1<<2)) ? SPI_2XCLOCK_MASK : 0);
}

--
The Gadget Shield: accelerometer, RGB LED, IR transmit/receive, light sensor, potentiometers, pushbuttons

Thank you! I updated that line in ..\Arduino\libraries\SPI\SPI.cpp, restarted, and sure enough, now

SPI.setClockDivider(SPI_CLOCK_DIV16);

gives me a 1.0 MHz SPI clock as expected. I am very happy to get this fixed so quickly!

Whoops. Can you post this to Google Code issue list so I don't forget to fix it? Google Code Archive - Long-term storage for Google Code Project Hosting.

Done!

--
The Quick Shield: breakout all 28 pins to quick-connect terminals

I fixed this in the source code on GitHub: Fixing SPI double-speed bug. · arduino/Arduino@b248953 · GitHub. I used a slightly different fix though (see below); can you check that it's also okay?

  SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((rate >> 2) & SPI_2XCLOCK_MASK);

Hi,

Was browsing through the SPI.h file (try to understand) and saw that there are two SPI_CLOCK_DIV64 defined. Once 0x02 and once 0x07. Is this correct? version 21 of the SPI.h lib.

#define SPI_CLOCK_DIV4 0x00
#define SPI_CLOCK_DIV16 0x01
#define SPI_CLOCK_DIV64 0x02
#define SPI_CLOCK_DIV128 0x03
#define SPI_CLOCK_DIV2 0x04
#define SPI_CLOCK_DIV8 0x05
#define SPI_CLOCK_DIV32 0x06
#define SPI_CLOCK_DIV64 0x07

There are two ways to get a divider of 64: with or without double-speed mode. If it mattered, we could change the name of one of them slightly to allow the choice of either - but from reading the datasheet, it doesn't sound like there's much (any?) difference.

I recently "upgraded" to Arduino 0021 and I notice that the SPI clock divider is once again not working right. Just a heads-up.

SPI.setClockDivider(SPI_CLOCK_DIV16);
gives me 2 MHz SPI clock (with a standard 2009 board at 16 MHz)

SPI.setClockDivider(SPI_CLOCK_DIV32);
gives me a 250 kHz SPI clock.

I went to the SPI library and found the old code with old bug is still there! Fixed it again per RuggedCircuits post above, and now it works again. Please fix before next release?

Right, this was fixed after 0021 was released. It will be in the next release.