Go Down

Topic: Change shiftOut() Clock Speed (Read 1 time) previous topic - next topic

tms8c8

Jan 15, 2013, 06:30 pm Last Edit: Jan 15, 2013, 06:32 pm by tms8c8 Reason: 1
I've put the following code in my sketch to speed up the shiftOut() function. I'm using the typical MC74HC595 shift register but the maximum  clock frequency for my application is (conservatively) 4 MHz. If my code works, my clock frequency will be considerably faster (see thread below - I'm using Stimmer's code; it takes about 24 nS to write a pin high). I need a "delay" of say ... 250 nS between each clock write cycle. So ... can I modify an existing (e.g. micros()) or write my own function to have better 100 nS resolution? Or a better way to accomplish what I want?

Code: [Select]
inline void digitalWriteDirect(int pin, boolean val){
 if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
 else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
 return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);
}

//High speed shift register function
void shiftOutFast( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal )
{
 uint8_t i ;
 for ( i=0 ; i < 8 ; i++ ){
   if ( ulBitOrder == LSBFIRST ){
     digitalWriteDirect( ulDataPin, !!(ulVal & (1 << i)) );
   }
   else{
     digitalWriteDirect( ulDataPin, !!(ulVal & (1 << (7 - i))) );
   }
   digitalWriteDirect( ulClockPin, HIGH );
    //need to delay 200 nS
   digitalWriteDirect( ulClockPin, LOW );
   //need to delay 200 nS
 }
}



http://arduino.cc/forum/index.php/topic,129868.15.html

CrossRoads

#1
Jan 15, 2013, 07:14 pm Last Edit: Jan 15, 2013, 10:16 pm by CrossRoads Reason: 1
I think the best you can do is use SPI.transfer( ) instead of shiftclk( ).
There are some clock divisors you can use, fastest is 1/2 processor clock speed, or 133nS.
http://arduino.cc/en/Reference/SPI

[Edit - right answer, wrong processor]
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

stimmer

Here's a useful macro:
Code: [Select]
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")
It outputs nop instructions - each nop wastes approx. 1 clock cycle which is about 12nS. So use MNOP(16); for about 200nS.

Beware that doing delays this way isn't very deterministic, you might find that you add a line somewhere completely different in the code and it changes the length of the delay!
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

CrossRoads

How is 1 clock cycle 12nS when  ...
Ah, never mind, didnt realize this was a Due question.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

tms8c8


Here's a useful macro:
Code: [Select]
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")
It outputs nop instructions - each nop wastes approx. 1 clock cycle which is about 12nS. So use MNOP(16); for about 200nS.

Beware that doing delays this way isn't very deterministic, you might find that you add a line somewhere completely different in the code and it changes the length of the delay!


Thanks Stimmer. Saved me twice today! The digitalWriteDirect() is super handy and the MNOP is exactly what I needed.

Go Up