Skip to content

Speeding Up The SPI Clock

November 29, 2013

The initial configuration of the shield adapter has the 1802 clocking out each bit of the spi data using the N1 line(OUT 2).  That limits it to a burst speed of 100,000 bits per second and effectively much less because the of the overhead of setting up the register environment for each byte.  (My) best case code is where the address of the data is in a register(say 12) and I have a count in another register(say 13).  I end up executing something like the code below which works out to around 57,600 bits/second and is annoying to generalize.

sex 12 //point X at the string to be written
out 6 //send it out to MOSR (also advances R12)
sex 3 //prepare for inline output
out 2; db 00 //8 cycles of the clock port
out 2; db 00
out 2; db 00
out 2; db 00
out 2; db 00
out 2; db 00
out 2; db 00
out 2;db 00
dec R13 //decrease counter
glo R13;   bnz $$wrtrloop //back for more
ghi R13;   bnz $$wrtrloop //til done

The plan has been to move to an external clock where the 1802 just does OUT 6 and the external clock generates 8 pulses.  SPI theoretically can go very fast, the default for an AVR is 4 mhz. But, some devices, can’t handle that speed.  Notably, SD cards, require a 400 khz clock during initialization. An AVR can just switch speeds but I think that’s beyond me so we’ll go with a 400 khz target.  I looked at various counter based schemes like what’s below based on a 4024 counter clocked by the 1802 clock divided by 4.  This would be satisfyingly old school but it means dragging a critical high speed line off the cpu board, I have to buffer the clock which is from an RC circuit, and I still have to generate a delayed version of the clock for various of the circuits which means another RC and cleanup.  Also, if  we increased the CPU clock speed, things would have to change again to stay at 400 khz.


I might, in the end, use something like that if I put all this on one board.  For the moment though, I’m going to offload the clock generation to an 8 pin attiny.  It will run on its internal 8 mhz clock and be triggered by the required combination of signals.  Interestingly, although 8 mhz seems very fast, the attiny is hard put to keep up with the 1802 timing.  The logic analyzer output below shows my best efforts with the 1802 in a four instruction loop(which is what you get if you reduce the code above to its basics).  I think this would translate to a sustained speed of 8 bits every 40 uS or 200,000 bits per sec, or 25,000 characters/sec.  There are ways to get the 1802 to spit out a byte every cycle through DMA which would give 200,000 characters per second but I don’t think I need to do that and I would need an spi clock speed of around 2 mhz to accommodate it.


The code running on the attiny is brief but obscure – see below if you’re interested.  The most interesting thing I learned about the avr doing this is how good the GCC compiler is.  I literally can not write assembler language code that would run faster than what the compiler does.  Admittedly, I used fast access to the IO ports but all the conditionals and that inner loop are handled brilliantly.

 while(1){ //loop forever
    while(1(PINB&_BV(OUT6))==0); //wait for OUT6 to go low
         for(unsigned int i=0;i<8;i++){ //8 pulses
            sbi(PORTB,clk1); //raise 1st clock
            sbi(PORTB,clk2); //raise 2nd clock
            cbi(PORTB,clk1); //lower 1st clock
            cbi(PORTB,clk2); //lower 2nd clock
        while((PINB&_BV(OUT6))); //wait for OUT6 to be low again

From → Uncategorized

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: