Shiftout Speeds? What is it now and Can it be adjusted?

Working with some shift registers that say max input is 8mhz
I have used this on a 8mhz Atmel 328p (internal clock) with no issues, but looking to add a photon or electron to my project instead of the 328, but I can’t seem to find any reference on how fast the particle devices will shiftout data.
And if the speed is above 8mhz is there an easy adjustment (setting) to specify shiftout to slow down to my needed speed?

With shiftOut() you are responsible for driving the clock pin and hence provide the frequency.
Whatever speed you decide to toggle the clock pin is entirely up to you.

This function is actually meant to allow an external clock source to control the transfer speed.
If the controler should be in full control of the transfer I’d rather go with SPI and only use the MOSI and CLK pins.

I’m not so sure about this. How does the ShiftOut function accept an EXTERNAL clock? The shift out function doesn’t have an argument to set the clock rate either, you pass it a GPIO that you want to use as the clock and it simply toggles this GPIO for each bit clocked out. The actual rate is unstated.

Yeah the fastest controlled method I could think of would be to add a delayMicroseconds(1)
And that would limit it to a max of 1mhz.
But no clue what the speed would be without adding any delays (Which I understand will depend on what other things are running),
but wonder what the rough speed would be,
and is there any way to make it faster than 1 mhz without going completely uncontrolled to who knows how high it’s capable of?

Right, my bad :flushed:
I looked at the implementation and it does not do what I said.
Here it is

With that the speed entirely relies on the internal clock and code execution speed.

However, if you only need one or two “shiftOut pins” one could use SPI & SPI1 and set the clock rate via SPI.setClockSpeed() - this even allows for asynchronous DMA transfer of the contents of a larger buffer instead of byte per byte in code.

Alternatively one could create the behaviouf I thought shiftOut() uses and turn the clock pin into an INPUT to control the speed externally (e.g. via a PWM signal).

e.g.

void shiftOutEx(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val, uint8_t validAt = HIGH, uint32_t bitTimeout = 100)
{
  uint8_t  i;
  uint32_t t;
  bool     extClock = !(getPinMode(clockPin) == OUTPUT);

  for (i = 0; i < 8; i++)  {
    if (extClock)  // with external clocking wait for clock to go to "blind" state (max bitTimeout/2)
      for(t = millis(); pinReadFast(clockPin) == validAt && millis() - t < bitTimeout/2;);
    else           // otherwise signal transitioning state
      digitalWriteFast(clockPin, !validAt);
                   // set next bit
    if (bitOrder == LSBFIRST)
      digitalWriteFast(dataPin, !!(val & (1 << i)));
    else
      digitalWriteFast(dataPin, !!(val & (1 << (7 - i))));

    if (extClock)  // with external clocking wait for clock to go to "valid" state (max bitTimeout/2)
      for(t = millis(); pinReadFast(clockPin) != validAt && millis() - t < bitTimeout/2;);
    else           // otherwise signal valid state 
      digitalWriteFast(clockPin, validAt);
  }
  if (!extClock)   // finally "invalidate" the state as it's beyond control of this function from now on
    digitalWriteFast(clockPin, !validAt); 
}

(pre-assigning pinMode(clockPin, OUTPUT) would behave pretty much the same as shiftOut() but any INPUT* mode should allow external clocking - not tested tho’ :blush:)

There are also other options thinkable that may involve HW timers and/or interrupts or SPI slave mode but the above may be worth a try.

1 Like