Go Down

Topic: How to set SPI clock to 76.9kHz by using the UNO R3? (Read 4 times) previous topic - next topic


It does indeed look like the slave is struggling, can you further reduce the speed?

Do you have a data sheet for the device?

Rob Gray aka the GRAYnomad www.robgray.com

Tom Carpenter

Jun 25, 2012, 05:13 pm Last Edit: Jun 25, 2012, 05:24 pm by TCWORLD Reason: 1
Just as a quick test, try adding this to the start of the setup():

 CLKPR = 0b10000000;
 CLKPR = 0b00000001;

You will also have to half all of the delays for this test as the Arduino IDE wont know how to account for this change.

What it does is prescales the whole system clock from 16MHz down to 8MHz, which will mean you get a 62.5kHz SPI clock.

The other thing is what are the three signals in the first scope trace you posted? It doesn't quite look like SPI.


It does indeed look like the slave is struggling, can you further reduce the speed?

Do you have a data sheet for the device?


I haven't the data sheet. I use the "SPI.setClockDivider(SPI_CLOCK_DIV128); " , which is the slowest spi clock in the SPI library.

I am decoding the protocol of Canon lens. There is no data sheet available. But there is a Canon services manual that was released by some guys.

The Canon services manual said as follows:
clock pulse 62.5kHz, 16us pulse
8 bit

My observation on oscilloscope:
clock pulse,13us pulse
clock idle high
rising edge sampling

Other non-official info (might be wrong):
1. Motorola SPI; 8 bit serial; Such as the protocol used with the 68HC05 chip.

Tom Carpenter

Oh, another option if you dont need the serial port is to use it in fake SPI mode. This allows you exact control over the baud rate.

Example (Note: This is untested, I based it on the code examples in the 328p datasheet):

Code: [Select]
void SPIInitialise() {
 // put your setup code here, to run once:
 pinMode(4,OUTPUT); //SCLK pin
 pinMode(0,INPUT); //MISO
 pinMode(1,OUTPUT); //MOSI
 pinMode(2,OUTPUT); //SS
 //Set UART as SPI.
 UBRR0 = 0;
 UCSR0C = (1<<UMSEL01)|(1<<UMSEL00)|(1<<UCPHA0)|(1<<UCPOL0);  //Set to MasterSPI (UMSEL0=1, UMSEL1=1), in Mode3 (CPHA=1, CPOL=1)
 UCSR0B = (1<<RXEN0)|(1<<TXEN0); //Enable TX and RX (TX = MOSI, RX = MISO)
 UBRR0 = 127; //SPI clock rate. UBRR0 = (FCPU/(2*BAUD)) -1;. So for 62.5KHz, UBRR0 = (16000000/(2*62500))-1 = 128 -1 = 127

byte SPITransfer(byte data) {
 /* Wait for empty transmit buffer */
 while ( !( UCSR0A & (1<<UDRE0)) );
 /* Put data into buffer, sends the data */
 UDR0 = data;
 /* Wait for data to be received */
 while ( !(UCSR0A & (1<<RXC0)) );
 /* Get and return received data from buffer */
 return UDR0;

void setup(){

void loop(){
 //Main loop

Nick Gammon

My bit-banged SPI used for uploading hex files:

Code: [Select]
// bit banged SPI pins
const byte MSPIM_SCK = 4;  // port D bit 4
const byte MSPIM_SS  = 5;  // port D bit 5
const byte BB_MISO   = 6;  // port D bit 6
const byte BB_MOSI   = 7;  // port D bit 7

// 8 MHz clock on this pin
const byte CLOCKOUT = 9;

// for fast port access (Atmega328)
const byte BB_SCK_BIT = 4;
const byte BB_MISO_BIT = 6;
const byte BB_MOSI_BIT = 7;

// control speed of programming


// Bit Banged SPI transfer
byte BB_SPITransfer (byte c)
  byte bit;
  for (bit = 0; bit < 8; bit++)
    // write MOSI on falling edge of previous clock
    if (c & 0x80)
        BB_MOSI_PORT |= _BV (BB_MOSI_BIT);
        BB_MOSI_PORT &= ~_BV (BB_MOSI_BIT);
    c <<= 1;

    // read MISO
    c |= (BB_MISO_PORT & _BV (BB_MISO_BIT)) != 0;

   // clock high

    // delay between rise and fall of clock
    delayMicroseconds (BB_DELAY_MICROSECONDS);

    // clock low
  return c;
  }  // end of BB_SPITransfer

By tweaking BB_DELAY_MICROSECONDS you should be able to get the frequency you want.

Go Up